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