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