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