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 std::vector<void *> *OpenedHandles = 0; 65 66 67 static SmartMutex<true>& getMutex() { 68 static SmartMutex<true> HandlesMutex; 69 return HandlesMutex; 70 } 71 72 73 bool DynamicLibrary::LoadLibraryPermanently(const char *Filename, 74 std::string *ErrMsg) { 75 void *H = dlopen(Filename, RTLD_LAZY|RTLD_GLOBAL); 76 if (H == 0) { 77 if (ErrMsg) *ErrMsg = dlerror(); 78 return true; 79 } 80 #ifdef __CYGWIN__ 81 // Cygwin searches symbols only in the main 82 // with the handle of dlopen(NULL, RTLD_GLOBAL). 83 if (Filename == NULL) 84 H = RTLD_DEFAULT; 85 #endif 86 SmartScopedLock<true> Lock(getMutex()); 87 if (OpenedHandles == 0) 88 OpenedHandles = new std::vector<void *>(); 89 OpenedHandles->push_back(H); 90 return false; 91 } 92 #else 93 94 using namespace llvm; 95 using namespace llvm::sys; 96 97 bool DynamicLibrary::LoadLibraryPermanently(const char *Filename, 98 std::string *ErrMsg) { 99 if (ErrMsg) *ErrMsg = "dlopen() not supported on this platform"; 100 return true; 101 } 102 #endif 103 104 namespace llvm { 105 void *SearchForAddressOfSpecialSymbol(const char* symbolName); 106 } 107 108 void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { 109 // First check symbols added via AddSymbol(). 110 if (ExplicitSymbols) { 111 std::map<std::string, void *>::iterator I = 112 ExplicitSymbols->find(symbolName); 113 std::map<std::string, void *>::iterator E = ExplicitSymbols->end(); 114 115 if (I != E) 116 return I->second; 117 } 118 119 #if HAVE_DLFCN_H 120 // Now search the libraries. 121 SmartScopedLock<true> Lock(getMutex()); 122 if (OpenedHandles) { 123 for (std::vector<void *>::iterator I = OpenedHandles->begin(), 124 E = OpenedHandles->end(); I != E; ++I) { 125 //lt_ptr ptr = lt_dlsym(*I, symbolName); 126 void *ptr = dlsym(*I, symbolName); 127 if (ptr) { 128 return ptr; 129 } 130 } 131 } 132 #endif 133 134 if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) 135 return Result; 136 137 // This macro returns the address of a well-known, explicit symbol 138 #define EXPLICIT_SYMBOL(SYM) \ 139 if (!strcmp(symbolName, #SYM)) return &SYM 140 141 // On linux we have a weird situation. The stderr/out/in symbols are both 142 // macros and global variables because of standards requirements. So, we 143 // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 144 #if defined(__linux__) && !defined(__android__) 145 { 146 EXPLICIT_SYMBOL(stderr); 147 EXPLICIT_SYMBOL(stdout); 148 EXPLICIT_SYMBOL(stdin); 149 } 150 #else 151 // For everything else, we want to check to make sure the symbol isn't defined 152 // as a macro before using EXPLICIT_SYMBOL. 153 { 154 #ifndef stdin 155 EXPLICIT_SYMBOL(stdin); 156 #endif 157 #ifndef stdout 158 EXPLICIT_SYMBOL(stdout); 159 #endif 160 #ifndef stderr 161 EXPLICIT_SYMBOL(stderr); 162 #endif 163 } 164 #endif 165 #undef EXPLICIT_SYMBOL 166 167 return 0; 168 } 169 170 #endif // LLVM_ON_WIN32 171