1447762daSMichael J. Spencer //===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===// 2447762daSMichael J. Spencer // 3447762daSMichael J. Spencer // The LLVM Compiler Infrastructure 4447762daSMichael J. Spencer // 5447762daSMichael J. Spencer // This file is distributed under the University of Illinois Open Source 6447762daSMichael J. Spencer // License. See LICENSE.TXT for details. 7447762daSMichael J. Spencer // 8447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 9447762daSMichael J. Spencer // 10cfe341f5SHans Wennborg // This file implements the operating system DynamicLibrary concept. 11447762daSMichael J. Spencer // 12447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 13447762daSMichael J. Spencer 14447762daSMichael J. Spencer #include "llvm/Support/DynamicLibrary.h" 158a8cd2baSChandler Carruth #include "llvm-c/Support.h" 16ed0881b2SChandler Carruth #include "llvm/ADT/DenseSet.h" 17ed0881b2SChandler Carruth #include "llvm/ADT/StringMap.h" 18447762daSMichael J. Spencer #include "llvm/Config/config.h" 198a8cd2baSChandler Carruth #include "llvm/Support/ManagedStatic.h" 20ed0881b2SChandler Carruth #include "llvm/Support/Mutex.h" 21447762daSMichael J. Spencer #include <cstdio> 22447762daSMichael J. Spencer #include <cstring> 23447762daSMichael J. Spencer 2470c377a3SFrederich Munch // Collection of symbol name/value pairs to be searched prior to any libraries. 2570c377a3SFrederich Munch static llvm::ManagedStatic<llvm::StringMap<void *> > ExplicitSymbols; 2670c377a3SFrederich Munch static llvm::ManagedStatic<llvm::sys::SmartMutex<true> > SymbolsMutex; 27*fd96d5e1SFrederich Munch 28*fd96d5e1SFrederich Munch void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName, 29*fd96d5e1SFrederich Munch void *symbolValue) { 30*fd96d5e1SFrederich Munch SmartScopedLock<true> lock(*SymbolsMutex); 31*fd96d5e1SFrederich Munch (*ExplicitSymbols)[symbolName] = symbolValue; 3270c377a3SFrederich Munch } 33b8c236a6SFrederich Munch 34*fd96d5e1SFrederich Munch char llvm::sys::DynamicLibrary::Invalid = 0; 35*fd96d5e1SFrederich Munch 36447762daSMichael J. Spencer #ifdef LLVM_ON_WIN32 37447762daSMichael J. Spencer 38447762daSMichael J. Spencer #include "Windows/DynamicLibrary.inc" 39447762daSMichael J. Spencer 40447762daSMichael J. Spencer #else 41447762daSMichael J. Spencer 42*fd96d5e1SFrederich Munch #if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN) 43*fd96d5e1SFrederich Munch #include <dlfcn.h> 44*fd96d5e1SFrederich Munch using namespace llvm; 45*fd96d5e1SFrederich Munch using namespace llvm::sys; 46*fd96d5e1SFrederich Munch 47*fd96d5e1SFrederich Munch //===----------------------------------------------------------------------===// 48*fd96d5e1SFrederich Munch //=== WARNING: Implementation here must contain only TRULY operating system 49*fd96d5e1SFrederich Munch //=== independent code. 50*fd96d5e1SFrederich Munch //===----------------------------------------------------------------------===// 51*fd96d5e1SFrederich Munch 52*fd96d5e1SFrederich Munch static llvm::ManagedStatic<DenseSet<void *> > OpenedHandles; 53*fd96d5e1SFrederich Munch 54*fd96d5e1SFrederich Munch DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 55*fd96d5e1SFrederich Munch std::string *errMsg) { 56*fd96d5e1SFrederich Munch SmartScopedLock<true> lock(*SymbolsMutex); 57*fd96d5e1SFrederich Munch 58*fd96d5e1SFrederich Munch void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL); 59*fd96d5e1SFrederich Munch if (!handle) { 60*fd96d5e1SFrederich Munch if (errMsg) *errMsg = dlerror(); 61*fd96d5e1SFrederich Munch return DynamicLibrary(); 62*fd96d5e1SFrederich Munch } 63*fd96d5e1SFrederich Munch 64*fd96d5e1SFrederich Munch #ifdef __CYGWIN__ 65*fd96d5e1SFrederich Munch // Cygwin searches symbols only in the main 66*fd96d5e1SFrederich Munch // with the handle of dlopen(NULL, RTLD_GLOBAL). 67*fd96d5e1SFrederich Munch if (!filename) 68*fd96d5e1SFrederich Munch handle = RTLD_DEFAULT; 69*fd96d5e1SFrederich Munch #endif 70*fd96d5e1SFrederich Munch 71*fd96d5e1SFrederich Munch // If we've already loaded this library, dlclose() the handle in order to 72*fd96d5e1SFrederich Munch // keep the internal refcount at +1. 73*fd96d5e1SFrederich Munch if (!OpenedHandles->insert(handle).second) 74*fd96d5e1SFrederich Munch dlclose(handle); 75*fd96d5e1SFrederich Munch 76*fd96d5e1SFrederich Munch return DynamicLibrary(handle); 77*fd96d5e1SFrederich Munch } 78*fd96d5e1SFrederich Munch 79*fd96d5e1SFrederich Munch DynamicLibrary DynamicLibrary::addPermanentLibrary(void *handle, 80*fd96d5e1SFrederich Munch std::string *errMsg) { 81*fd96d5e1SFrederich Munch SmartScopedLock<true> lock(*SymbolsMutex); 82*fd96d5e1SFrederich Munch // If we've already loaded this library, tell the caller. 83*fd96d5e1SFrederich Munch if (!OpenedHandles->insert(handle).second) { 84*fd96d5e1SFrederich Munch if (errMsg) *errMsg = "Library already loaded"; 85*fd96d5e1SFrederich Munch return DynamicLibrary(); 86*fd96d5e1SFrederich Munch } 87*fd96d5e1SFrederich Munch 88*fd96d5e1SFrederich Munch return DynamicLibrary(handle); 89*fd96d5e1SFrederich Munch } 90*fd96d5e1SFrederich Munch 91*fd96d5e1SFrederich Munch void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 92*fd96d5e1SFrederich Munch if (!isValid()) 93*fd96d5e1SFrederich Munch return nullptr; 94*fd96d5e1SFrederich Munch return dlsym(Data, symbolName); 95*fd96d5e1SFrederich Munch } 96*fd96d5e1SFrederich Munch 97*fd96d5e1SFrederich Munch #else 98*fd96d5e1SFrederich Munch 99*fd96d5e1SFrederich Munch using namespace llvm; 100*fd96d5e1SFrederich Munch using namespace llvm::sys; 101*fd96d5e1SFrederich Munch 102*fd96d5e1SFrederich Munch DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 103*fd96d5e1SFrederich Munch std::string *errMsg) { 104*fd96d5e1SFrederich Munch if (errMsg) *errMsg = "dlopen() not supported on this platform"; 105*fd96d5e1SFrederich Munch return DynamicLibrary(); 106*fd96d5e1SFrederich Munch } 107*fd96d5e1SFrederich Munch 108*fd96d5e1SFrederich Munch void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 109*fd96d5e1SFrederich Munch return NULL; 110*fd96d5e1SFrederich Munch } 111a19917daSJordy Rose 112447762daSMichael J. Spencer #endif 113447762daSMichael J. Spencer 114447762daSMichael J. Spencer namespace llvm { 115*fd96d5e1SFrederich Munch void *SearchForAddressOfSpecialSymbol(const char* symbolName); 116447762daSMichael J. Spencer } 117447762daSMichael J. Spencer 118*fd96d5e1SFrederich Munch void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { 11957093e88SFilip Pizlo SmartScopedLock<true> Lock(*SymbolsMutex); 120a19917daSJordy Rose 121447762daSMichael J. Spencer // First check symbols added via AddSymbol(). 12257093e88SFilip Pizlo if (ExplicitSymbols.isConstructed()) { 123*fd96d5e1SFrederich Munch StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName); 124447762daSMichael J. Spencer 125a19917daSJordy Rose if (i != ExplicitSymbols->end()) 126a19917daSJordy Rose return i->second; 127447762daSMichael J. Spencer } 128447762daSMichael J. Spencer 129*fd96d5e1SFrederich Munch #if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN) 130447762daSMichael J. Spencer // Now search the libraries. 13159e5a644SVassil Vassilev if (OpenedHandles.isConstructed()) { 132*fd96d5e1SFrederich Munch for (DenseSet<void *>::iterator I = OpenedHandles->begin(), 133*fd96d5e1SFrederich Munch E = OpenedHandles->end(); I != E; ++I) { 134*fd96d5e1SFrederich Munch //lt_ptr ptr = lt_dlsym(*I, symbolName); 135*fd96d5e1SFrederich Munch void *ptr = dlsym(*I, symbolName); 136*fd96d5e1SFrederich Munch if (ptr) { 137*fd96d5e1SFrederich Munch return ptr; 138447762daSMichael J. Spencer } 139447762daSMichael J. Spencer } 140*fd96d5e1SFrederich Munch } 141*fd96d5e1SFrederich Munch #endif 142*fd96d5e1SFrederich Munch 143*fd96d5e1SFrederich Munch if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) 144*fd96d5e1SFrederich Munch return Result; 145*fd96d5e1SFrederich Munch 146*fd96d5e1SFrederich Munch // This macro returns the address of a well-known, explicit symbol 147*fd96d5e1SFrederich Munch #define EXPLICIT_SYMBOL(SYM) \ 148*fd96d5e1SFrederich Munch if (!strcmp(symbolName, #SYM)) return &SYM 149*fd96d5e1SFrederich Munch 150*fd96d5e1SFrederich Munch // On linux we have a weird situation. The stderr/out/in symbols are both 151*fd96d5e1SFrederich Munch // macros and global variables because of standards requirements. So, we 152*fd96d5e1SFrederich Munch // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 153*fd96d5e1SFrederich Munch #if defined(__linux__) and !defined(__ANDROID__) 154*fd96d5e1SFrederich Munch { 155*fd96d5e1SFrederich Munch EXPLICIT_SYMBOL(stderr); 156*fd96d5e1SFrederich Munch EXPLICIT_SYMBOL(stdout); 157*fd96d5e1SFrederich Munch EXPLICIT_SYMBOL(stdin); 158*fd96d5e1SFrederich Munch } 159*fd96d5e1SFrederich Munch #else 160*fd96d5e1SFrederich Munch // For everything else, we want to check to make sure the symbol isn't defined 161*fd96d5e1SFrederich Munch // as a macro before using EXPLICIT_SYMBOL. 162*fd96d5e1SFrederich Munch { 163*fd96d5e1SFrederich Munch #ifndef stdin 164*fd96d5e1SFrederich Munch EXPLICIT_SYMBOL(stdin); 165*fd96d5e1SFrederich Munch #endif 166*fd96d5e1SFrederich Munch #ifndef stdout 167*fd96d5e1SFrederich Munch EXPLICIT_SYMBOL(stdout); 168*fd96d5e1SFrederich Munch #endif 169*fd96d5e1SFrederich Munch #ifndef stderr 170*fd96d5e1SFrederich Munch EXPLICIT_SYMBOL(stderr); 171*fd96d5e1SFrederich Munch #endif 172*fd96d5e1SFrederich Munch } 173*fd96d5e1SFrederich Munch #endif 174*fd96d5e1SFrederich Munch #undef EXPLICIT_SYMBOL 175*fd96d5e1SFrederich Munch 176*fd96d5e1SFrederich Munch return nullptr; 177*fd96d5e1SFrederich Munch } 178447762daSMichael J. Spencer 179*fd96d5e1SFrederich Munch #endif // LLVM_ON_WIN32 18034ddbf1aSPeter Zotov 18134ddbf1aSPeter Zotov //===----------------------------------------------------------------------===// 18234ddbf1aSPeter Zotov // C API. 18334ddbf1aSPeter Zotov //===----------------------------------------------------------------------===// 18434ddbf1aSPeter Zotov 18534ddbf1aSPeter Zotov LLVMBool LLVMLoadLibraryPermanently(const char* Filename) { 186671fe2eeSPeter Zotov return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename); 18734ddbf1aSPeter Zotov } 188af79f3dbSEli Bendersky 189af79f3dbSEli Bendersky void *LLVMSearchForAddressOfSymbol(const char *symbolName) { 190af79f3dbSEli Bendersky return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName); 191af79f3dbSEli Bendersky } 192af79f3dbSEli Bendersky 193af79f3dbSEli Bendersky void LLVMAddSymbol(const char *symbolName, void *symbolValue) { 194af79f3dbSEli Bendersky return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue); 195af79f3dbSEli Bendersky } 196