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