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/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 24 // Collection of symbol name/value pairs to be searched prior to any libraries. 25 static llvm::ManagedStatic<llvm::StringMap<void *> > ExplicitSymbols; 26 static llvm::ManagedStatic<llvm::sys::SmartMutex<true> > SymbolsMutex; 27 28 void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName, 29 void *symbolValue) { 30 SmartScopedLock<true> lock(*SymbolsMutex); 31 (*ExplicitSymbols)[symbolName] = symbolValue; 32 } 33 34 char llvm::sys::DynamicLibrary::Invalid = 0; 35 36 #ifdef LLVM_ON_WIN32 37 38 #include "Windows/DynamicLibrary.inc" 39 40 #else 41 42 #if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN) 43 #include <dlfcn.h> 44 using namespace llvm; 45 using namespace llvm::sys; 46 47 //===----------------------------------------------------------------------===// 48 //=== WARNING: Implementation here must contain only TRULY operating system 49 //=== independent code. 50 //===----------------------------------------------------------------------===// 51 52 static llvm::ManagedStatic<DenseSet<void *> > OpenedHandles; 53 54 DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 55 std::string *errMsg) { 56 SmartScopedLock<true> lock(*SymbolsMutex); 57 58 void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL); 59 if (!handle) { 60 if (errMsg) *errMsg = dlerror(); 61 return DynamicLibrary(); 62 } 63 64 #ifdef __CYGWIN__ 65 // Cygwin searches symbols only in the main 66 // with the handle of dlopen(NULL, RTLD_GLOBAL). 67 if (!filename) 68 handle = RTLD_DEFAULT; 69 #endif 70 71 DynamicLibrary dyLib = addPermanentLibraryWithLock(handle, lock, !filename); 72 73 // If we've already loaded this library, dlclose() the handle in order to 74 // keep the internal refcount at +1. 75 if (!dyLib.isValid()) { 76 if (errMsg) 77 *errMsg = (filename) ? std::string(filename) : std::string() + 78 ": Library already loaded"; 79 dlclose(handle); 80 } 81 82 return dyLib; 83 } 84 85 DynamicLibrary DynamicLibrary::addPermanentLibrary(void *handle) { 86 SmartScopedLock<true> lock(*SymbolsMutex); 87 return addPermanentLibraryWithLock(handle, lock, false); 88 } 89 90 DynamicLibrary DynamicLibrary::addPermanentLibraryWithLock(void *handle, 91 sys::SmartScopedLock<true> &, 92 bool isMainExec) { 93 // If we've already loaded this library, tell the caller. 94 // FIXME: Note that multiple requests for adding the main executable is not 95 // considered as an error. If we don't want to treat the main executable as a 96 // special case we need to do a cleanup in the MCJIT tests and API. 97 if (!OpenedHandles->insert(handle).second && !isMainExec) 98 return DynamicLibrary(); 99 100 return DynamicLibrary(handle); 101 } 102 103 void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 104 if (!isValid()) 105 return nullptr; 106 return dlsym(Data, symbolName); 107 } 108 109 #else 110 111 using namespace llvm; 112 using namespace llvm::sys; 113 114 DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 115 std::string *errMsg) { 116 if (errMsg) *errMsg = "dlopen() not supported on this platform"; 117 return DynamicLibrary(); 118 } 119 120 void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 121 return NULL; 122 } 123 124 #endif 125 126 namespace llvm { 127 void *SearchForAddressOfSpecialSymbol(const char* symbolName); 128 } 129 130 void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { 131 SmartScopedLock<true> Lock(*SymbolsMutex); 132 133 // First check symbols added via AddSymbol(). 134 if (ExplicitSymbols.isConstructed()) { 135 StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName); 136 137 if (i != ExplicitSymbols->end()) 138 return i->second; 139 } 140 141 #if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN) 142 // Now search the libraries. 143 if (OpenedHandles.isConstructed()) { 144 for (DenseSet<void *>::iterator I = OpenedHandles->begin(), 145 E = OpenedHandles->end(); I != E; ++I) { 146 //lt_ptr ptr = lt_dlsym(*I, symbolName); 147 void *ptr = dlsym(*I, symbolName); 148 if (ptr) { 149 return ptr; 150 } 151 } 152 } 153 #endif 154 155 if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) 156 return Result; 157 158 // This macro returns the address of a well-known, explicit symbol 159 #define EXPLICIT_SYMBOL(SYM) \ 160 if (!strcmp(symbolName, #SYM)) return &SYM 161 162 // On linux we have a weird situation. The stderr/out/in symbols are both 163 // macros and global variables because of standards requirements. So, we 164 // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 165 #if defined(__linux__) and !defined(__ANDROID__) 166 { 167 EXPLICIT_SYMBOL(stderr); 168 EXPLICIT_SYMBOL(stdout); 169 EXPLICIT_SYMBOL(stdin); 170 } 171 #else 172 // For everything else, we want to check to make sure the symbol isn't defined 173 // as a macro before using EXPLICIT_SYMBOL. 174 { 175 #ifndef stdin 176 EXPLICIT_SYMBOL(stdin); 177 #endif 178 #ifndef stdout 179 EXPLICIT_SYMBOL(stdout); 180 #endif 181 #ifndef stderr 182 EXPLICIT_SYMBOL(stderr); 183 #endif 184 } 185 #endif 186 #undef EXPLICIT_SYMBOL 187 188 return nullptr; 189 } 190 191 #endif // LLVM_ON_WIN32 192 193 //===----------------------------------------------------------------------===// 194 // C API. 195 //===----------------------------------------------------------------------===// 196 197 LLVMBool LLVMLoadLibraryPermanently(const char* Filename) { 198 return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename); 199 } 200 201 void *LLVMSearchForAddressOfSymbol(const char *symbolName) { 202 return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName); 203 } 204 205 void LLVMAddSymbol(const char *symbolName, void *symbolValue) { 206 return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue); 207 } 208 209