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 24447762daSMichael J. Spencer // Collection of symbol name/value pairs to be searched prior to any libraries. 2557093e88SFilip Pizlo static llvm::ManagedStatic<llvm::StringMap<void *> > ExplicitSymbols; 2657093e88SFilip Pizlo static llvm::ManagedStatic<llvm::sys::SmartMutex<true> > SymbolsMutex; 27a19917daSJordy Rose 28a19917daSJordy Rose void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName, 29447762daSMichael J. Spencer void *symbolValue) { 3057093e88SFilip Pizlo SmartScopedLock<true> lock(*SymbolsMutex); 31447762daSMichael J. Spencer (*ExplicitSymbols)[symbolName] = symbolValue; 32447762daSMichael J. Spencer } 33447762daSMichael J. Spencer 3404bc405aSJordy Rose char llvm::sys::DynamicLibrary::Invalid = 0; 3504bc405aSJordy Rose 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 425d92bc5bSPavel Labath #if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN) 43447762daSMichael J. Spencer #include <dlfcn.h> 44447762daSMichael J. Spencer using namespace llvm; 45447762daSMichael J. Spencer using namespace llvm::sys; 46447762daSMichael J. Spencer 47447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 48447762daSMichael J. Spencer //=== WARNING: Implementation here must contain only TRULY operating system 49447762daSMichael J. Spencer //=== independent code. 50447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 51447762daSMichael J. Spencer 52*59e5a644SVassil Vassilev static llvm::ManagedStatic<DenseSet<void *> > OpenedHandles; 53447762daSMichael J. Spencer 54a19917daSJordy Rose DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 55a19917daSJordy Rose std::string *errMsg) { 5657093e88SFilip Pizlo SmartScopedLock<true> lock(*SymbolsMutex); 5774a46c24SZachary Turner 5874a46c24SZachary Turner void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL); 598d399f87SCraig Topper if (!handle) { 60a19917daSJordy Rose if (errMsg) *errMsg = dlerror(); 61a19917daSJordy Rose return DynamicLibrary(); 62447762daSMichael J. Spencer } 63447762daSMichael J. Spencer 64447762daSMichael J. Spencer #ifdef __CYGWIN__ 65447762daSMichael J. Spencer // Cygwin searches symbols only in the main 66447762daSMichael J. Spencer // with the handle of dlopen(NULL, RTLD_GLOBAL). 678d399f87SCraig Topper if (!filename) 68a19917daSJordy Rose handle = RTLD_DEFAULT; 69447762daSMichael J. Spencer #endif 70a19917daSJordy Rose 71a19917daSJordy Rose // If we've already loaded this library, dlclose() the handle in order to 72a19917daSJordy Rose // keep the internal refcount at +1. 73a19917daSJordy Rose if (!OpenedHandles->insert(handle).second) 74a19917daSJordy Rose dlclose(handle); 75a19917daSJordy Rose 76a19917daSJordy Rose return DynamicLibrary(handle); 77447762daSMichael J. Spencer } 78a19917daSJordy Rose 79a19917daSJordy Rose void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 80a19917daSJordy Rose if (!isValid()) 81c10719f5SCraig Topper return nullptr; 82a19917daSJordy Rose return dlsym(Data, symbolName); 83a19917daSJordy Rose } 84a19917daSJordy Rose 85447762daSMichael J. Spencer #else 86447762daSMichael J. Spencer 87447762daSMichael J. Spencer using namespace llvm; 88447762daSMichael J. Spencer using namespace llvm::sys; 89447762daSMichael J. Spencer 90a19917daSJordy Rose DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 91a19917daSJordy Rose std::string *errMsg) { 92a19917daSJordy Rose if (errMsg) *errMsg = "dlopen() not supported on this platform"; 93a19917daSJordy Rose return DynamicLibrary(); 94447762daSMichael J. Spencer } 95a19917daSJordy Rose 96a19917daSJordy Rose void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 97a19917daSJordy Rose return NULL; 98a19917daSJordy Rose } 99a19917daSJordy Rose 100447762daSMichael J. Spencer #endif 101447762daSMichael J. Spencer 102447762daSMichael J. Spencer namespace llvm { 103447762daSMichael J. Spencer void *SearchForAddressOfSpecialSymbol(const char* symbolName); 104447762daSMichael J. Spencer } 105447762daSMichael J. Spencer 106447762daSMichael J. Spencer void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { 10757093e88SFilip Pizlo SmartScopedLock<true> Lock(*SymbolsMutex); 108a19917daSJordy Rose 109447762daSMichael J. Spencer // First check symbols added via AddSymbol(). 11057093e88SFilip Pizlo if (ExplicitSymbols.isConstructed()) { 111a19917daSJordy Rose StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName); 112447762daSMichael J. Spencer 113a19917daSJordy Rose if (i != ExplicitSymbols->end()) 114a19917daSJordy Rose return i->second; 115447762daSMichael J. Spencer } 116447762daSMichael J. Spencer 1175d92bc5bSPavel Labath #if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN) 118447762daSMichael J. Spencer // Now search the libraries. 119*59e5a644SVassil Vassilev if (OpenedHandles.isConstructed()) { 120a19917daSJordy Rose for (DenseSet<void *>::iterator I = OpenedHandles->begin(), 121447762daSMichael J. Spencer E = OpenedHandles->end(); I != E; ++I) { 122447762daSMichael J. Spencer //lt_ptr ptr = lt_dlsym(*I, symbolName); 123447762daSMichael J. Spencer void *ptr = dlsym(*I, symbolName); 124447762daSMichael J. Spencer if (ptr) { 125447762daSMichael J. Spencer return ptr; 126447762daSMichael J. Spencer } 127447762daSMichael J. Spencer } 128447762daSMichael J. Spencer } 129447762daSMichael J. Spencer #endif 130447762daSMichael J. Spencer 131447762daSMichael J. Spencer if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) 132447762daSMichael J. Spencer return Result; 133447762daSMichael J. Spencer 134447762daSMichael J. Spencer // This macro returns the address of a well-known, explicit symbol 135447762daSMichael J. Spencer #define EXPLICIT_SYMBOL(SYM) \ 136447762daSMichael J. Spencer if (!strcmp(symbolName, #SYM)) return &SYM 137447762daSMichael J. Spencer 138447762daSMichael J. Spencer // On linux we have a weird situation. The stderr/out/in symbols are both 139447762daSMichael J. Spencer // macros and global variables because of standards requirements. So, we 140447762daSMichael J. Spencer // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 141c439a426SEvgeniy Stepanov #if defined(__linux__) and !defined(__ANDROID__) 142447762daSMichael J. Spencer { 143447762daSMichael J. Spencer EXPLICIT_SYMBOL(stderr); 144447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdout); 145447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdin); 146447762daSMichael J. Spencer } 147447762daSMichael J. Spencer #else 148447762daSMichael J. Spencer // For everything else, we want to check to make sure the symbol isn't defined 149447762daSMichael J. Spencer // as a macro before using EXPLICIT_SYMBOL. 150447762daSMichael J. Spencer { 151447762daSMichael J. Spencer #ifndef stdin 152447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdin); 153447762daSMichael J. Spencer #endif 154447762daSMichael J. Spencer #ifndef stdout 155447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdout); 156447762daSMichael J. Spencer #endif 157447762daSMichael J. Spencer #ifndef stderr 158447762daSMichael J. Spencer EXPLICIT_SYMBOL(stderr); 159447762daSMichael J. Spencer #endif 160447762daSMichael J. Spencer } 161447762daSMichael J. Spencer #endif 162447762daSMichael J. Spencer #undef EXPLICIT_SYMBOL 163447762daSMichael J. Spencer 164c10719f5SCraig Topper return nullptr; 165447762daSMichael J. Spencer } 166447762daSMichael J. Spencer 167447762daSMichael J. Spencer #endif // LLVM_ON_WIN32 16834ddbf1aSPeter Zotov 16934ddbf1aSPeter Zotov //===----------------------------------------------------------------------===// 17034ddbf1aSPeter Zotov // C API. 17134ddbf1aSPeter Zotov //===----------------------------------------------------------------------===// 17234ddbf1aSPeter Zotov 17334ddbf1aSPeter Zotov LLVMBool LLVMLoadLibraryPermanently(const char* Filename) { 174671fe2eeSPeter Zotov return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename); 17534ddbf1aSPeter Zotov } 176af79f3dbSEli Bendersky 177af79f3dbSEli Bendersky void *LLVMSearchForAddressOfSymbol(const char *symbolName) { 178af79f3dbSEli Bendersky return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName); 179af79f3dbSEli Bendersky } 180af79f3dbSEli Bendersky 181af79f3dbSEli Bendersky void LLVMAddSymbol(const char *symbolName, void *symbolValue) { 182af79f3dbSEli Bendersky return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue); 183af79f3dbSEli Bendersky } 184af79f3dbSEli Bendersky 185