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 HandleSet() : Process(nullptr) {} 41 ~HandleSet(); 42 43 HandleList::iterator Find(void *Handle) { 44 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 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 if (LLVM_LIKELY(!IsProcess)) { 57 if (Find(Handle) != Handles.end()) { 58 if (CanClose) 59 DLClose(Handle); 60 return false; 61 } 62 Handles.push_back(Handle); 63 } else { 64 #ifndef _WIN32 65 if (Process) { 66 if (CanClose) 67 DLClose(Process); 68 if (Process == Handle) 69 return false; 70 } 71 #endif 72 Process = Handle; 73 } 74 return true; 75 } 76 77 void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) { 78 if (Order & SO_LoadOrder) { 79 for (void *Handle : Handles) { 80 if (void *Ptr = DLSym(Handle, Symbol)) 81 return Ptr; 82 } 83 } else { 84 for (void *Handle : llvm::reverse(Handles)) { 85 if (void *Ptr = DLSym(Handle, Symbol)) 86 return Ptr; 87 } 88 } 89 return nullptr; 90 } 91 92 void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) { 93 assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) && 94 "Invalid Ordering"); 95 96 if (!Process || (Order & SO_LoadedFirst)) { 97 if (void *Ptr = LibLookup(Symbol, Order)) 98 return Ptr; 99 } 100 if (Process) { 101 // Use OS facilities to search the current binary and all loaded libs. 102 if (void *Ptr = DLSym(Process, Symbol)) 103 return Ptr; 104 105 // Search any libs that might have been skipped because of RTLD_LOCAL. 106 if (Order & SO_LoadedLast) { 107 if (void *Ptr = LibLookup(Symbol, Order)) 108 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 void *SearchForAddressOfSpecialSymbol(const char *SymbolName) { 140 return DoSearch(SymbolName); // DynamicLibrary.inc 141 } 142 } 143 144 void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) { 145 SmartScopedLock<true> Lock(*SymbolsMutex); 146 (*ExplicitSymbols)[SymbolName] = SymbolValue; 147 } 148 149 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 HandleSet& HS = *OpenedHandles; 154 155 void *Handle = HandleSet::DLOpen(FileName, Err); 156 if (Handle != &Invalid) { 157 SmartScopedLock<true> Lock(*SymbolsMutex); 158 HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr); 159 } 160 161 return DynamicLibrary(Handle); 162 } 163 164 DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle, 165 std::string *Err) { 166 SmartScopedLock<true> Lock(*SymbolsMutex); 167 // If we've already loaded this library, tell the caller. 168 if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false)) 169 *Err = "Library already loaded"; 170 171 return DynamicLibrary(Handle); 172 } 173 174 void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) { 175 if (!isValid()) 176 return nullptr; 177 return HandleSet::DLSym(Data, SymbolName); 178 } 179 180 void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) { 181 { 182 SmartScopedLock<true> Lock(*SymbolsMutex); 183 184 // First check symbols added via AddSymbol(). 185 if (ExplicitSymbols.isConstructed()) { 186 StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName); 187 188 if (i != ExplicitSymbols->end()) 189 return i->second; 190 } 191 192 // Now search the libraries. 193 if (OpenedHandles.isConstructed()) { 194 if (void *Ptr = OpenedHandles->Lookup(SymbolName, SearchOrder)) 195 return Ptr; 196 } 197 } 198 199 return llvm::SearchForAddressOfSpecialSymbol(SymbolName); 200 } 201 202 //===----------------------------------------------------------------------===// 203 // C API. 204 //===----------------------------------------------------------------------===// 205 206 LLVMBool LLVMLoadLibraryPermanently(const char *Filename) { 207 return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename); 208 } 209 210 void *LLVMSearchForAddressOfSymbol(const char *symbolName) { 211 return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName); 212 } 213 214 void LLVMAddSymbol(const char *symbolName, void *symbolValue) { 215 return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue); 216 } 217