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