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