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" 17*5fdd2cbaSFrederich Munch #include "llvm/ADT/STLExtras.h" 18ed0881b2SChandler Carruth #include "llvm/ADT/StringMap.h" 19447762daSMichael J. Spencer #include "llvm/Config/config.h" 208a8cd2baSChandler Carruth #include "llvm/Support/ManagedStatic.h" 21ed0881b2SChandler Carruth #include "llvm/Support/Mutex.h" 22447762daSMichael J. Spencer #include <cstdio> 23447762daSMichael J. Spencer #include <cstring> 24c1db8cf9SFrederich Munch #include <vector> 25447762daSMichael J. Spencer 26c1db8cf9SFrederich Munch using namespace llvm; 27c1db8cf9SFrederich Munch using namespace llvm::sys; 28fd96d5e1SFrederich Munch 29c1db8cf9SFrederich Munch // All methods for HandleSet should be used holding SymbolsMutex. 30c1db8cf9SFrederich Munch class DynamicLibrary::HandleSet { 31c1db8cf9SFrederich Munch typedef std::vector<void *> HandleList; 32c1db8cf9SFrederich Munch HandleList Handles; 33c1db8cf9SFrederich Munch void *Process; 34c1db8cf9SFrederich Munch 35c1db8cf9SFrederich Munch public: 36c1db8cf9SFrederich Munch static void *DLOpen(const char *Filename, std::string *Err); 37c1db8cf9SFrederich Munch static void DLClose(void *Handle); 38c1db8cf9SFrederich Munch static void *DLSym(void *Handle, const char *Symbol); 39c1db8cf9SFrederich Munch 40c1db8cf9SFrederich Munch HandleSet() : Process(nullptr) {} 41c1db8cf9SFrederich Munch ~HandleSet(); 42c1db8cf9SFrederich Munch 43c1db8cf9SFrederich Munch HandleList::iterator Find(void *Handle) { 44c1db8cf9SFrederich Munch return std::find(Handles.begin(), Handles.end(), Handle); 4570c377a3SFrederich Munch } 46b8c236a6SFrederich Munch 47c1db8cf9SFrederich Munch bool Contains(void *Handle) { 48c1db8cf9SFrederich Munch return Handle == Process || Find(Handle) != Handles.end(); 49c1db8cf9SFrederich Munch } 50c1db8cf9SFrederich Munch 51c1db8cf9SFrederich Munch bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) { 52c1db8cf9SFrederich Munch #ifdef LLVM_ON_WIN32 53c1db8cf9SFrederich Munch assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle."); 54c1db8cf9SFrederich Munch #endif 55c1db8cf9SFrederich Munch 56c1db8cf9SFrederich Munch if (LLVM_LIKELY(!IsProcess)) { 57c1db8cf9SFrederich Munch if (Find(Handle) != Handles.end()) { 58c1db8cf9SFrederich Munch if (CanClose) 59c1db8cf9SFrederich Munch DLClose(Handle); 60c1db8cf9SFrederich Munch return false; 61c1db8cf9SFrederich Munch } 62c1db8cf9SFrederich Munch Handles.push_back(Handle); 63c1db8cf9SFrederich Munch } else { 64c1db8cf9SFrederich Munch #ifndef LLVM_ON_WIN32 65c1db8cf9SFrederich Munch if (Process) { 66c1db8cf9SFrederich Munch if (CanClose) 67c1db8cf9SFrederich Munch DLClose(Process); 68c1db8cf9SFrederich Munch if (Process == Handle) 69c1db8cf9SFrederich Munch return false; 70c1db8cf9SFrederich Munch } 71c1db8cf9SFrederich Munch #endif 72c1db8cf9SFrederich Munch Process = Handle; 73c1db8cf9SFrederich Munch } 74c1db8cf9SFrederich Munch return true; 75c1db8cf9SFrederich Munch } 76c1db8cf9SFrederich Munch 77*5fdd2cbaSFrederich Munch void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) { 78*5fdd2cbaSFrederich Munch if (Order & SO_LoadOrder) { 79*5fdd2cbaSFrederich Munch for (void *Handle : Handles) { 80*5fdd2cbaSFrederich Munch if (void *Ptr = DLSym(Handle, Symbol)) 81*5fdd2cbaSFrederich Munch return Ptr; 82*5fdd2cbaSFrederich Munch } 83*5fdd2cbaSFrederich Munch } else { 84*5fdd2cbaSFrederich Munch for (void *Handle : llvm::reverse(Handles)) { 85*5fdd2cbaSFrederich Munch if (void *Ptr = DLSym(Handle, Symbol)) 86*5fdd2cbaSFrederich Munch return Ptr; 87*5fdd2cbaSFrederich Munch } 88*5fdd2cbaSFrederich Munch } 89*5fdd2cbaSFrederich Munch return nullptr; 90*5fdd2cbaSFrederich Munch } 91*5fdd2cbaSFrederich Munch 92*5fdd2cbaSFrederich Munch void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) { 93*5fdd2cbaSFrederich Munch assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) && 94*5fdd2cbaSFrederich Munch "Invalid Ordering"); 95*5fdd2cbaSFrederich Munch 96*5fdd2cbaSFrederich Munch if (!Process || (Order & SO_LoadedFirst)) { 97*5fdd2cbaSFrederich Munch if (void *Ptr = LibLookup(Symbol, Order)) 98*5fdd2cbaSFrederich Munch return Ptr; 99*5fdd2cbaSFrederich Munch } 100c1db8cf9SFrederich Munch if (Process) { 101*5fdd2cbaSFrederich Munch // Use OS facilities to search the current binary and all loaded libs. 102c1db8cf9SFrederich Munch if (void *Ptr = DLSym(Process, Symbol)) 103c1db8cf9SFrederich Munch return Ptr; 104*5fdd2cbaSFrederich Munch 105*5fdd2cbaSFrederich Munch // Search any libs that might have been skipped because of RTLD_LOCAL. 106*5fdd2cbaSFrederich Munch if (Order & SO_LoadedLast) { 107*5fdd2cbaSFrederich Munch if (void *Ptr = LibLookup(Symbol, Order)) 108c1db8cf9SFrederich Munch return Ptr; 109c1db8cf9SFrederich Munch } 110c1db8cf9SFrederich Munch } 111c1db8cf9SFrederich Munch return nullptr; 112c1db8cf9SFrederich Munch } 113c1db8cf9SFrederich Munch }; 114c1db8cf9SFrederich Munch 115c1db8cf9SFrederich Munch namespace { 116c1db8cf9SFrederich Munch // Collection of symbol name/value pairs to be searched prior to any libraries. 117c1db8cf9SFrederich Munch static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols; 118c1db8cf9SFrederich Munch // Collection of known library handles. 119c1db8cf9SFrederich Munch static llvm::ManagedStatic<DynamicLibrary::HandleSet> OpenedHandles; 120c1db8cf9SFrederich Munch // Lock for ExplicitSymbols and OpenedHandles. 121c1db8cf9SFrederich Munch static llvm::ManagedStatic<llvm::sys::SmartMutex<true>> SymbolsMutex; 122c1db8cf9SFrederich Munch } 123fd96d5e1SFrederich Munch 124447762daSMichael J. Spencer #ifdef LLVM_ON_WIN32 125447762daSMichael J. Spencer 126447762daSMichael J. Spencer #include "Windows/DynamicLibrary.inc" 127447762daSMichael J. Spencer 128447762daSMichael J. Spencer #else 129447762daSMichael J. Spencer 130c1db8cf9SFrederich Munch #include "Unix/DynamicLibrary.inc" 131a19917daSJordy Rose 132447762daSMichael J. Spencer #endif 133447762daSMichael J. Spencer 134c1db8cf9SFrederich Munch char DynamicLibrary::Invalid; 135*5fdd2cbaSFrederich Munch DynamicLibrary::SearchOrdering DynamicLibrary::SearchOrder = 136*5fdd2cbaSFrederich Munch DynamicLibrary::SO_Linker; 137c1db8cf9SFrederich Munch 138447762daSMichael J. Spencer namespace llvm { 139c1db8cf9SFrederich Munch void *SearchForAddressOfSpecialSymbol(const char *SymbolName) { 140c1db8cf9SFrederich Munch return DoSearch(SymbolName); // DynamicLibrary.inc 141c1db8cf9SFrederich Munch } 142447762daSMichael J. Spencer } 143447762daSMichael J. Spencer 144c1db8cf9SFrederich Munch void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) { 145c1db8cf9SFrederich Munch SmartScopedLock<true> Lock(*SymbolsMutex); 146c1db8cf9SFrederich Munch (*ExplicitSymbols)[SymbolName] = SymbolValue; 147c1db8cf9SFrederich Munch } 148c1db8cf9SFrederich Munch 149c1db8cf9SFrederich Munch DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName, 150c1db8cf9SFrederich Munch std::string *Err) { 1518c3735e5SFrederich Munch // Force OpenedHandles to be added into the ManagedStatic list before any 1528c3735e5SFrederich Munch // ManagedStatic can be added from static constructors in HandleSet::DLOpen. 1538c3735e5SFrederich Munch HandleSet& HS = *OpenedHandles; 1548c3735e5SFrederich Munch 155c1db8cf9SFrederich Munch void *Handle = HandleSet::DLOpen(FileName, Err); 1568c3735e5SFrederich Munch if (Handle != &Invalid) { 1578c3735e5SFrederich Munch SmartScopedLock<true> Lock(*SymbolsMutex); 1588c3735e5SFrederich Munch HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr); 1598c3735e5SFrederich Munch } 160c1db8cf9SFrederich Munch 161c1db8cf9SFrederich Munch return DynamicLibrary(Handle); 162c1db8cf9SFrederich Munch } 163c1db8cf9SFrederich Munch 164c1db8cf9SFrederich Munch DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle, 165c1db8cf9SFrederich Munch std::string *Err) { 166c1db8cf9SFrederich Munch SmartScopedLock<true> Lock(*SymbolsMutex); 167c1db8cf9SFrederich Munch // If we've already loaded this library, tell the caller. 168c1db8cf9SFrederich Munch if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false)) 169c1db8cf9SFrederich Munch *Err = "Library already loaded"; 170c1db8cf9SFrederich Munch 171c1db8cf9SFrederich Munch return DynamicLibrary(Handle); 172c1db8cf9SFrederich Munch } 173c1db8cf9SFrederich Munch 174c1db8cf9SFrederich Munch void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) { 175c1db8cf9SFrederich Munch if (!isValid()) 176c1db8cf9SFrederich Munch return nullptr; 177c1db8cf9SFrederich Munch return HandleSet::DLSym(Data, SymbolName); 178c1db8cf9SFrederich Munch } 179c1db8cf9SFrederich Munch 180c1db8cf9SFrederich Munch void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) { 181c1db8cf9SFrederich Munch { 18257093e88SFilip Pizlo SmartScopedLock<true> Lock(*SymbolsMutex); 183a19917daSJordy Rose 184447762daSMichael J. Spencer // First check symbols added via AddSymbol(). 18557093e88SFilip Pizlo if (ExplicitSymbols.isConstructed()) { 186c1db8cf9SFrederich Munch StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName); 187447762daSMichael J. Spencer 188a19917daSJordy Rose if (i != ExplicitSymbols->end()) 189a19917daSJordy Rose return i->second; 190447762daSMichael J. Spencer } 191447762daSMichael J. Spencer 192447762daSMichael J. Spencer // Now search the libraries. 19359e5a644SVassil Vassilev if (OpenedHandles.isConstructed()) { 194*5fdd2cbaSFrederich Munch if (void *Ptr = OpenedHandles->Lookup(SymbolName, SearchOrder)) 195c1db8cf9SFrederich Munch return Ptr; 196447762daSMichael J. Spencer } 197447762daSMichael J. Spencer } 198447762daSMichael J. Spencer 199c1db8cf9SFrederich Munch return llvm::SearchForAddressOfSpecialSymbol(SymbolName); 200c1db8cf9SFrederich Munch } 20134ddbf1aSPeter Zotov 20234ddbf1aSPeter Zotov //===----------------------------------------------------------------------===// 20334ddbf1aSPeter Zotov // C API. 20434ddbf1aSPeter Zotov //===----------------------------------------------------------------------===// 20534ddbf1aSPeter Zotov 20634ddbf1aSPeter Zotov LLVMBool LLVMLoadLibraryPermanently(const char *Filename) { 207671fe2eeSPeter Zotov return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename); 20834ddbf1aSPeter Zotov } 209af79f3dbSEli Bendersky 210af79f3dbSEli Bendersky void *LLVMSearchForAddressOfSymbol(const char *symbolName) { 211af79f3dbSEli Bendersky return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName); 212af79f3dbSEli Bendersky } 213af79f3dbSEli Bendersky 214af79f3dbSEli Bendersky void LLVMAddSymbol(const char *symbolName, void *symbolValue) { 215af79f3dbSEli Bendersky return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue); 216af79f3dbSEli Bendersky } 217