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