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