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 // If we've already loaded this library, dlclose() the handle in order to 72 // keep the internal refcount at +1. 73 if (!OpenedHandles->insert(handle).second) 74 dlclose(handle); 75 76 return DynamicLibrary(handle); 77 } 78 79 DynamicLibrary DynamicLibrary::addPermanentLibrary(void *handle, 80 std::string *errMsg) { 81 SmartScopedLock<true> lock(*SymbolsMutex); 82 // If we've already loaded this library, tell the caller. 83 if (!OpenedHandles->insert(handle).second) { 84 if (errMsg) *errMsg = "Library already loaded"; 85 return DynamicLibrary(); 86 } 87 88 return DynamicLibrary(handle); 89 } 90 91 void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 92 if (!isValid()) 93 return nullptr; 94 return dlsym(Data, symbolName); 95 } 96 97 #else 98 99 using namespace llvm; 100 using namespace llvm::sys; 101 102 DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 103 std::string *errMsg) { 104 if (errMsg) *errMsg = "dlopen() not supported on this platform"; 105 return DynamicLibrary(); 106 } 107 108 void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 109 return NULL; 110 } 111 112 #endif 113 114 namespace llvm { 115 void *SearchForAddressOfSpecialSymbol(const char* symbolName); 116 } 117 118 void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { 119 SmartScopedLock<true> Lock(*SymbolsMutex); 120 121 // First check symbols added via AddSymbol(). 122 if (ExplicitSymbols.isConstructed()) { 123 StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName); 124 125 if (i != ExplicitSymbols->end()) 126 return i->second; 127 } 128 129 #if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN) 130 // Now search the libraries. 131 if (OpenedHandles.isConstructed()) { 132 for (DenseSet<void *>::iterator I = OpenedHandles->begin(), 133 E = OpenedHandles->end(); I != E; ++I) { 134 //lt_ptr ptr = lt_dlsym(*I, symbolName); 135 void *ptr = dlsym(*I, symbolName); 136 if (ptr) { 137 return ptr; 138 } 139 } 140 } 141 #endif 142 143 if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) 144 return Result; 145 146 // This macro returns the address of a well-known, explicit symbol 147 #define EXPLICIT_SYMBOL(SYM) \ 148 if (!strcmp(symbolName, #SYM)) return &SYM 149 150 // On linux we have a weird situation. The stderr/out/in symbols are both 151 // macros and global variables because of standards requirements. So, we 152 // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 153 #if defined(__linux__) and !defined(__ANDROID__) 154 { 155 EXPLICIT_SYMBOL(stderr); 156 EXPLICIT_SYMBOL(stdout); 157 EXPLICIT_SYMBOL(stdin); 158 } 159 #else 160 // For everything else, we want to check to make sure the symbol isn't defined 161 // as a macro before using EXPLICIT_SYMBOL. 162 { 163 #ifndef stdin 164 EXPLICIT_SYMBOL(stdin); 165 #endif 166 #ifndef stdout 167 EXPLICIT_SYMBOL(stdout); 168 #endif 169 #ifndef stderr 170 EXPLICIT_SYMBOL(stderr); 171 #endif 172 } 173 #endif 174 #undef EXPLICIT_SYMBOL 175 176 return nullptr; 177 } 178 179 #endif // LLVM_ON_WIN32 180 181 //===----------------------------------------------------------------------===// 182 // C API. 183 //===----------------------------------------------------------------------===// 184 185 LLVMBool LLVMLoadLibraryPermanently(const char* Filename) { 186 return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename); 187 } 188 189 void *LLVMSearchForAddressOfSymbol(const char *symbolName) { 190 return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName); 191 } 192 193 void LLVMAddSymbol(const char *symbolName, void *symbolValue) { 194 return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue); 195 } 196 197