LCOV - code coverage report
Current view: top level - lib/Support - DynamicLibrary.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 46 63 73.0 %
Date: 2018-10-20 13:21:21 Functions: 8 12 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : //  This file implements the operating system DynamicLibrary concept.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #include "llvm/Support/DynamicLibrary.h"
      15             : #include "llvm-c/Support.h"
      16             : #include "llvm/ADT/DenseSet.h"
      17             : #include "llvm/ADT/STLExtras.h"
      18             : #include "llvm/ADT/StringMap.h"
      19             : #include "llvm/Config/config.h"
      20             : #include "llvm/Support/ManagedStatic.h"
      21             : #include "llvm/Support/Mutex.h"
      22             : #include <cstdio>
      23             : #include <cstring>
      24             : #include <vector>
      25             : 
      26             : using namespace llvm;
      27             : using namespace llvm::sys;
      28             : 
      29             : // All methods for HandleSet should be used holding SymbolsMutex.
      30             : class DynamicLibrary::HandleSet {
      31             :   typedef std::vector<void *> HandleList;
      32             :   HandleList Handles;
      33             :   void *Process;
      34             : 
      35             : public:
      36             :   static void *DLOpen(const char *Filename, std::string *Err);
      37             :   static void DLClose(void *Handle);
      38             :   static void *DLSym(void *Handle, const char *Symbol);
      39             : 
      40         694 :   HandleSet() : Process(nullptr) {}
      41             :   ~HandleSet();
      42             : 
      43             :   HandleList::iterator Find(void *Handle) {
      44          91 :     return std::find(Handles.begin(), Handles.end(), Handle);
      45             :   }
      46             : 
      47             :   bool Contains(void *Handle) {
      48             :     return Handle == Process || Find(Handle) != Handles.end();
      49             :   }
      50             : 
      51         472 :   bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) {
      52             : #ifdef _WIN32
      53             :     assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
      54             : #endif
      55             : 
      56         472 :     if (LLVM_LIKELY(!IsProcess)) {
      57          91 :       if (Find(Handle) != Handles.end()) {
      58           0 :         if (CanClose)
      59           0 :           DLClose(Handle);
      60           0 :         return false;
      61             :       }
      62          91 :       Handles.push_back(Handle);
      63             :     } else {
      64             : #ifndef _WIN32
      65         381 :       if (Process) {
      66         123 :         if (CanClose)
      67         123 :           DLClose(Process);
      68         123 :         if (Process == Handle)
      69             :           return false;
      70             :       }
      71             : #endif
      72         258 :       Process = Handle;
      73             :     }
      74             :     return true;
      75             :   }
      76             : 
      77           7 :   void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
      78           7 :     if (Order & SO_LoadOrder) {
      79           0 :       for (void *Handle : Handles) {
      80           0 :         if (void *Ptr = DLSym(Handle, Symbol))
      81             :           return Ptr;
      82             :       }
      83             :     } else {
      84           7 :       for (void *Handle : llvm::reverse(Handles)) {
      85           7 :         if (void *Ptr = DLSym(Handle, Symbol))
      86             :           return Ptr;
      87             :       }
      88             :     }
      89             :     return nullptr;
      90             :   }
      91             : 
      92         279 :   void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
      93             :     assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) &&
      94             :            "Invalid Ordering");
      95             : 
      96         279 :     if (!Process || (Order & SO_LoadedFirst)) {
      97           7 :       if (void *Ptr = LibLookup(Symbol, Order))
      98             :         return Ptr;
      99             :     }
     100         272 :     if (Process) {
     101             :       // Use OS facilities to search the current binary and all loaded libs.
     102         272 :       if (void *Ptr = DLSym(Process, Symbol))
     103             :         return Ptr;
     104             : 
     105             :       // Search any libs that might have been skipped because of RTLD_LOCAL.
     106          35 :       if (Order & SO_LoadedLast) {
     107           0 :         if (void *Ptr = LibLookup(Symbol, Order))
     108           0 :           return Ptr;
     109             :       }
     110             :     }
     111             :     return nullptr;
     112             :   }
     113             : };
     114             : 
     115             : namespace {
     116             : // Collection of symbol name/value pairs to be searched prior to any libraries.
     117             : static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols;
     118             : // Collection of known library handles.
     119             : static llvm::ManagedStatic<DynamicLibrary::HandleSet> OpenedHandles;
     120             : // Lock for ExplicitSymbols and OpenedHandles.
     121             : static llvm::ManagedStatic<llvm::sys::SmartMutex<true>> SymbolsMutex;
     122             : }
     123             : 
     124             : #ifdef _WIN32
     125             : 
     126             : #include "Windows/DynamicLibrary.inc"
     127             : 
     128             : #else
     129             : 
     130             : #include "Unix/DynamicLibrary.inc"
     131             : 
     132             : #endif
     133             : 
     134             : char DynamicLibrary::Invalid;
     135             : DynamicLibrary::SearchOrdering DynamicLibrary::SearchOrder =
     136             :     DynamicLibrary::SO_Linker;
     137             : 
     138             : namespace llvm {
     139          37 : void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
     140          37 :   return DoSearch(SymbolName); // DynamicLibrary.inc
     141             : }
     142             : }
     143             : 
     144           3 : void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {
     145           3 :   SmartScopedLock<true> Lock(*SymbolsMutex);
     146           6 :   (*ExplicitSymbols)[SymbolName] = SymbolValue;
     147           3 : }
     148             : 
     149         472 : DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName,
     150             :                                                    std::string *Err) {
     151             :   // Force OpenedHandles to be added into the ManagedStatic list before any
     152             :   // ManagedStatic can be added from static constructors in HandleSet::DLOpen.
     153         472 :   HandleSet& HS = *OpenedHandles;
     154             : 
     155         472 :   void *Handle = HandleSet::DLOpen(FileName, Err);
     156         472 :   if (Handle != &Invalid) {
     157         472 :     SmartScopedLock<true> Lock(*SymbolsMutex);
     158         472 :     HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
     159             :   }
     160             : 
     161         472 :   return DynamicLibrary(Handle);
     162             : }
     163             : 
     164           0 : DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle,
     165             :                                                    std::string *Err) {
     166           0 :   SmartScopedLock<true> Lock(*SymbolsMutex);
     167             :   // If we've already loaded this library, tell the caller.
     168           0 :   if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false))
     169             :     *Err = "Library already loaded";
     170             : 
     171           0 :   return DynamicLibrary(Handle);
     172             : }
     173             : 
     174          14 : void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
     175          14 :   if (!isValid())
     176             :     return nullptr;
     177          14 :   return HandleSet::DLSym(Data, SymbolName);
     178             : }
     179             : 
     180         283 : void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
     181             :   {
     182         283 :     SmartScopedLock<true> Lock(*SymbolsMutex);
     183             : 
     184             :     // First check symbols added via AddSymbol().
     185         283 :     if (ExplicitSymbols.isConstructed()) {
     186           2 :       StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName);
     187             : 
     188           4 :       if (i != ExplicitSymbols->end())
     189           2 :         return i->second;
     190             :     }
     191             : 
     192             :     // Now search the libraries.
     193         281 :     if (OpenedHandles.isConstructed()) {
     194         279 :       if (void *Ptr = OpenedHandles->Lookup(SymbolName, SearchOrder))
     195             :         return Ptr;
     196             :     }
     197             :   }
     198             : 
     199          37 :   return llvm::SearchForAddressOfSpecialSymbol(SymbolName);
     200             : }
     201             : 
     202             : //===----------------------------------------------------------------------===//
     203             : // C API.
     204             : //===----------------------------------------------------------------------===//
     205             : 
     206           0 : LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {
     207           0 :   return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
     208             : }
     209             : 
     210           0 : void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
     211           0 :   return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
     212             : }
     213             : 
     214           0 : void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
     215           0 :   return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
     216             : }

Generated by: LCOV version 1.13