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