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> 23*70c377a3SFrederich Munch #include <vector> 24447762daSMichael J. Spencer 25*70c377a3SFrederich Munch using namespace llvm; 26*70c377a3SFrederich Munch using namespace llvm::sys; 27b8c236a6SFrederich Munch 28*70c377a3SFrederich Munch // All methods for HandleSet should be used holding SymbolsMutex. 29*70c377a3SFrederich Munch class DynamicLibrary::HandleSet { 30*70c377a3SFrederich Munch typedef std::vector<void *> HandleList; 31*70c377a3SFrederich Munch HandleList Handles; 32*70c377a3SFrederich Munch void *Process; 33*70c377a3SFrederich Munch 34*70c377a3SFrederich Munch public: 35*70c377a3SFrederich Munch static void *DLOpen(const char *Filename, std::string *Err); 36*70c377a3SFrederich Munch static void DLClose(void *Handle); 37*70c377a3SFrederich Munch static void *DLSym(void *Handle, const char *Symbol); 38*70c377a3SFrederich Munch 39*70c377a3SFrederich Munch HandleSet() : Process(nullptr) {} 40*70c377a3SFrederich Munch ~HandleSet(); 41*70c377a3SFrederich Munch 42*70c377a3SFrederich Munch HandleList::iterator Find(void *Handle) { 43*70c377a3SFrederich Munch return std::find(Handles.begin(), Handles.end(), Handle); 449f40457dSFrederich Munch } 4504bc405aSJordy Rose 46*70c377a3SFrederich Munch bool Contains(void *Handle) { 47*70c377a3SFrederich Munch return Handle == Process || Find(Handle) != Handles.end(); 48*70c377a3SFrederich Munch } 49*70c377a3SFrederich Munch 50*70c377a3SFrederich Munch bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) { 51*70c377a3SFrederich Munch #ifdef LLVM_ON_WIN32 52*70c377a3SFrederich Munch assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle."); 53*70c377a3SFrederich Munch #endif 54*70c377a3SFrederich Munch 55*70c377a3SFrederich Munch if (LLVM_LIKELY(!IsProcess)) { 56*70c377a3SFrederich Munch if (Find(Handle) != Handles.end()) { 57*70c377a3SFrederich Munch if (CanClose) 58*70c377a3SFrederich Munch DLClose(Handle); 59*70c377a3SFrederich Munch return false; 60*70c377a3SFrederich Munch } 61*70c377a3SFrederich Munch Handles.push_back(Handle); 62*70c377a3SFrederich Munch } else { 63*70c377a3SFrederich Munch #ifndef LLVM_ON_WIN32 64*70c377a3SFrederich Munch if (Process) { 65*70c377a3SFrederich Munch if (CanClose) 66*70c377a3SFrederich Munch DLClose(Process); 67*70c377a3SFrederich Munch if (Process == Handle) 68*70c377a3SFrederich Munch return false; 69*70c377a3SFrederich Munch } 70*70c377a3SFrederich Munch #endif 71*70c377a3SFrederich Munch Process = Handle; 72*70c377a3SFrederich Munch } 73*70c377a3SFrederich Munch return true; 74*70c377a3SFrederich Munch } 75*70c377a3SFrederich Munch 76*70c377a3SFrederich Munch void *Lookup(const char *Symbol) { 77*70c377a3SFrederich Munch // Process handle gets first try. 78*70c377a3SFrederich Munch if (Process) { 79*70c377a3SFrederich Munch if (void *Ptr = DLSym(Process, Symbol)) 80*70c377a3SFrederich Munch return Ptr; 81*70c377a3SFrederich Munch #ifndef NDEBUG 82*70c377a3SFrederich Munch for (void *Handle : Handles) 83*70c377a3SFrederich Munch assert(!DLSym(Handle, Symbol) && "Symbol exists in non process handle"); 84*70c377a3SFrederich Munch #endif 85*70c377a3SFrederich Munch } else { 86*70c377a3SFrederich Munch // Iterate in reverse, so newer libraries/symbols override older. 87*70c377a3SFrederich Munch for (auto &&I = Handles.rbegin(), E = Handles.rend(); I != E; ++I) { 88*70c377a3SFrederich Munch if (void *Ptr = DLSym(*I, Symbol)) 89*70c377a3SFrederich Munch return Ptr; 90*70c377a3SFrederich Munch } 91*70c377a3SFrederich Munch } 92*70c377a3SFrederich Munch return nullptr; 93*70c377a3SFrederich Munch } 94*70c377a3SFrederich Munch }; 95*70c377a3SFrederich Munch 96*70c377a3SFrederich Munch namespace { 97*70c377a3SFrederich Munch // Collection of symbol name/value pairs to be searched prior to any libraries. 98*70c377a3SFrederich Munch static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols; 99*70c377a3SFrederich Munch // Collection of known library handles. 100*70c377a3SFrederich Munch static llvm::ManagedStatic<DynamicLibrary::HandleSet> OpenedHandles; 101*70c377a3SFrederich Munch // Lock for ExplicitSymbols and OpenedHandles. 102*70c377a3SFrederich Munch static llvm::ManagedStatic<llvm::sys::SmartMutex<true>> SymbolsMutex; 103*70c377a3SFrederich Munch } 104b8c236a6SFrederich Munch 105447762daSMichael J. Spencer #ifdef LLVM_ON_WIN32 106447762daSMichael J. Spencer 107447762daSMichael J. Spencer #include "Windows/DynamicLibrary.inc" 108447762daSMichael J. Spencer 109447762daSMichael J. Spencer #else 110447762daSMichael J. Spencer 111*70c377a3SFrederich Munch #include "Unix/DynamicLibrary.inc" 112a19917daSJordy Rose 113447762daSMichael J. Spencer #endif 114447762daSMichael J. Spencer 115*70c377a3SFrederich Munch char DynamicLibrary::Invalid; 116*70c377a3SFrederich Munch 117447762daSMichael J. Spencer namespace llvm { 118*70c377a3SFrederich Munch void *SearchForAddressOfSpecialSymbol(const char *SymbolName) { 119*70c377a3SFrederich Munch return DoSearch(SymbolName); // DynamicLibrary.inc 120*70c377a3SFrederich Munch } 121447762daSMichael J. Spencer } 122447762daSMichael J. Spencer 123*70c377a3SFrederich Munch void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) { 124*70c377a3SFrederich Munch SmartScopedLock<true> Lock(*SymbolsMutex); 125*70c377a3SFrederich Munch (*ExplicitSymbols)[SymbolName] = SymbolValue; 126*70c377a3SFrederich Munch } 127*70c377a3SFrederich Munch 128*70c377a3SFrederich Munch DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName, 129*70c377a3SFrederich Munch std::string *Err) { 130*70c377a3SFrederich Munch SmartScopedLock<true> Lock(*SymbolsMutex); 131*70c377a3SFrederich Munch void *Handle = HandleSet::DLOpen(FileName, Err); 132*70c377a3SFrederich Munch if (Handle != &Invalid) 133*70c377a3SFrederich Munch OpenedHandles->AddLibrary(Handle, /*IsProcess*/ FileName == nullptr); 134*70c377a3SFrederich Munch 135*70c377a3SFrederich Munch return DynamicLibrary(Handle); 136*70c377a3SFrederich Munch } 137*70c377a3SFrederich Munch 138*70c377a3SFrederich Munch DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle, 139*70c377a3SFrederich Munch std::string *Err) { 140*70c377a3SFrederich Munch SmartScopedLock<true> Lock(*SymbolsMutex); 141*70c377a3SFrederich Munch // If we've already loaded this library, tell the caller. 142*70c377a3SFrederich Munch if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false)) 143*70c377a3SFrederich Munch *Err = "Library already loaded"; 144*70c377a3SFrederich Munch 145*70c377a3SFrederich Munch return DynamicLibrary(Handle); 146*70c377a3SFrederich Munch } 147*70c377a3SFrederich Munch 148*70c377a3SFrederich Munch void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) { 149*70c377a3SFrederich Munch if (!isValid()) 150*70c377a3SFrederich Munch return nullptr; 151*70c377a3SFrederich Munch return HandleSet::DLSym(Data, SymbolName); 152*70c377a3SFrederich Munch } 153*70c377a3SFrederich Munch 154*70c377a3SFrederich Munch void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) { 155*70c377a3SFrederich Munch { 15657093e88SFilip Pizlo SmartScopedLock<true> Lock(*SymbolsMutex); 157a19917daSJordy Rose 158447762daSMichael J. Spencer // First check symbols added via AddSymbol(). 15957093e88SFilip Pizlo if (ExplicitSymbols.isConstructed()) { 160*70c377a3SFrederich Munch StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName); 161447762daSMichael J. Spencer 162a19917daSJordy Rose if (i != ExplicitSymbols->end()) 163a19917daSJordy Rose return i->second; 164447762daSMichael J. Spencer } 165447762daSMichael J. Spencer 166447762daSMichael J. Spencer // Now search the libraries. 16759e5a644SVassil Vassilev if (OpenedHandles.isConstructed()) { 168*70c377a3SFrederich Munch if (void *Ptr = OpenedHandles->Lookup(SymbolName)) 169*70c377a3SFrederich Munch return Ptr; 170447762daSMichael J. Spencer } 171447762daSMichael J. Spencer } 172447762daSMichael J. Spencer 173*70c377a3SFrederich Munch return llvm::SearchForAddressOfSpecialSymbol(SymbolName); 174*70c377a3SFrederich Munch } 17534ddbf1aSPeter Zotov 17634ddbf1aSPeter Zotov //===----------------------------------------------------------------------===// 17734ddbf1aSPeter Zotov // C API. 17834ddbf1aSPeter Zotov //===----------------------------------------------------------------------===// 17934ddbf1aSPeter Zotov 18034ddbf1aSPeter Zotov LLVMBool LLVMLoadLibraryPermanently(const char *Filename) { 181671fe2eeSPeter Zotov return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename); 18234ddbf1aSPeter Zotov } 183af79f3dbSEli Bendersky 184af79f3dbSEli Bendersky void *LLVMSearchForAddressOfSymbol(const char *symbolName) { 185af79f3dbSEli Bendersky return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName); 186af79f3dbSEli Bendersky } 187af79f3dbSEli Bendersky 188af79f3dbSEli Bendersky void LLVMAddSymbol(const char *symbolName, void *symbolValue) { 189af79f3dbSEli Bendersky return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue); 190af79f3dbSEli Bendersky } 191