1447762daSMichael J. Spencer //===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===// 2447762daSMichael J. Spencer // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6447762daSMichael J. Spencer // 7447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 8447762daSMichael J. Spencer // 9cfe341f5SHans Wennborg // This file implements the operating system DynamicLibrary concept. 10447762daSMichael J. Spencer // 11447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 12447762daSMichael J. Spencer 13447762daSMichael J. Spencer #include "llvm/Support/DynamicLibrary.h" 148a8cd2baSChandler Carruth #include "llvm-c/Support.h" 15ed0881b2SChandler Carruth #include "llvm/ADT/DenseSet.h" 165fdd2cbaSFrederich Munch #include "llvm/ADT/STLExtras.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> 23c1db8cf9SFrederich Munch #include <vector> 24447762daSMichael J. Spencer 25c1db8cf9SFrederich Munch using namespace llvm; 26c1db8cf9SFrederich Munch using namespace llvm::sys; 27fd96d5e1SFrederich Munch 28c1db8cf9SFrederich Munch // All methods for HandleSet should be used holding SymbolsMutex. 29c1db8cf9SFrederich Munch class DynamicLibrary::HandleSet { 30c1db8cf9SFrederich Munch typedef std::vector<void *> HandleList; 31c1db8cf9SFrederich Munch HandleList Handles; 32c1db8cf9SFrederich Munch void *Process; 33c1db8cf9SFrederich Munch 34c1db8cf9SFrederich Munch public: 35c1db8cf9SFrederich Munch static void *DLOpen(const char *Filename, std::string *Err); 36c1db8cf9SFrederich Munch static void DLClose(void *Handle); 37c1db8cf9SFrederich Munch static void *DLSym(void *Handle, const char *Symbol); 38c1db8cf9SFrederich Munch 39c1db8cf9SFrederich Munch HandleSet() : Process(nullptr) {} 40c1db8cf9SFrederich Munch ~HandleSet(); 41c1db8cf9SFrederich Munch 4288572024SKazu Hirata HandleList::iterator Find(void *Handle) { return find(Handles, Handle); } 43b8c236a6SFrederich Munch 44c1db8cf9SFrederich Munch bool Contains(void *Handle) { 45c1db8cf9SFrederich Munch return Handle == Process || Find(Handle) != Handles.end(); 46c1db8cf9SFrederich Munch } 47c1db8cf9SFrederich Munch 48c1db8cf9SFrederich Munch bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) { 49712e8d29SNico Weber #ifdef _WIN32 50c1db8cf9SFrederich Munch assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle."); 51c1db8cf9SFrederich Munch #endif 52c1db8cf9SFrederich Munch 53c1db8cf9SFrederich Munch if (LLVM_LIKELY(!IsProcess)) { 54c1db8cf9SFrederich Munch if (Find(Handle) != Handles.end()) { 55c1db8cf9SFrederich Munch if (CanClose) 56c1db8cf9SFrederich Munch DLClose(Handle); 57c1db8cf9SFrederich Munch return false; 58c1db8cf9SFrederich Munch } 59c1db8cf9SFrederich Munch Handles.push_back(Handle); 60c1db8cf9SFrederich Munch } else { 61712e8d29SNico Weber #ifndef _WIN32 62c1db8cf9SFrederich Munch if (Process) { 63c1db8cf9SFrederich Munch if (CanClose) 64c1db8cf9SFrederich Munch DLClose(Process); 65c1db8cf9SFrederich Munch if (Process == Handle) 66c1db8cf9SFrederich Munch return false; 67c1db8cf9SFrederich Munch } 68c1db8cf9SFrederich Munch #endif 69c1db8cf9SFrederich Munch Process = Handle; 70c1db8cf9SFrederich Munch } 71c1db8cf9SFrederich Munch return true; 72c1db8cf9SFrederich Munch } 73c1db8cf9SFrederich Munch 745fdd2cbaSFrederich Munch void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) { 755fdd2cbaSFrederich Munch if (Order & SO_LoadOrder) { 765fdd2cbaSFrederich Munch for (void *Handle : Handles) { 775fdd2cbaSFrederich Munch if (void *Ptr = DLSym(Handle, Symbol)) 785fdd2cbaSFrederich Munch return Ptr; 795fdd2cbaSFrederich Munch } 805fdd2cbaSFrederich Munch } else { 815fdd2cbaSFrederich Munch for (void *Handle : llvm::reverse(Handles)) { 825fdd2cbaSFrederich Munch if (void *Ptr = DLSym(Handle, Symbol)) 835fdd2cbaSFrederich Munch return Ptr; 845fdd2cbaSFrederich Munch } 855fdd2cbaSFrederich Munch } 865fdd2cbaSFrederich Munch return nullptr; 875fdd2cbaSFrederich Munch } 885fdd2cbaSFrederich Munch 895fdd2cbaSFrederich Munch void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) { 905fdd2cbaSFrederich Munch assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) && 915fdd2cbaSFrederich Munch "Invalid Ordering"); 925fdd2cbaSFrederich Munch 935fdd2cbaSFrederich Munch if (!Process || (Order & SO_LoadedFirst)) { 945fdd2cbaSFrederich Munch if (void *Ptr = LibLookup(Symbol, Order)) 955fdd2cbaSFrederich Munch return Ptr; 965fdd2cbaSFrederich Munch } 97c1db8cf9SFrederich Munch if (Process) { 985fdd2cbaSFrederich Munch // Use OS facilities to search the current binary and all loaded libs. 99c1db8cf9SFrederich Munch if (void *Ptr = DLSym(Process, Symbol)) 100c1db8cf9SFrederich Munch return Ptr; 1015fdd2cbaSFrederich Munch 1025fdd2cbaSFrederich Munch // Search any libs that might have been skipped because of RTLD_LOCAL. 1035fdd2cbaSFrederich Munch if (Order & SO_LoadedLast) { 1045fdd2cbaSFrederich Munch if (void *Ptr = LibLookup(Symbol, Order)) 105c1db8cf9SFrederich Munch return Ptr; 106c1db8cf9SFrederich Munch } 107c1db8cf9SFrederich Munch } 108c1db8cf9SFrederich Munch return nullptr; 109c1db8cf9SFrederich Munch } 110c1db8cf9SFrederich Munch }; 111c1db8cf9SFrederich Munch 112c1db8cf9SFrederich Munch namespace { 113c1db8cf9SFrederich Munch // Collection of symbol name/value pairs to be searched prior to any libraries. 114c1db8cf9SFrederich Munch static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols; 115c1db8cf9SFrederich Munch // Collection of known library handles. 116c1db8cf9SFrederich Munch static llvm::ManagedStatic<DynamicLibrary::HandleSet> OpenedHandles; 117c1db8cf9SFrederich Munch // Lock for ExplicitSymbols and OpenedHandles. 118c1db8cf9SFrederich Munch static llvm::ManagedStatic<llvm::sys::SmartMutex<true>> SymbolsMutex; 119*0164d546SSimon Pilgrim } // namespace 120fd96d5e1SFrederich Munch 121712e8d29SNico Weber #ifdef _WIN32 122447762daSMichael J. Spencer 123447762daSMichael J. Spencer #include "Windows/DynamicLibrary.inc" 124447762daSMichael J. Spencer 125447762daSMichael J. Spencer #else 126447762daSMichael J. Spencer 127c1db8cf9SFrederich Munch #include "Unix/DynamicLibrary.inc" 128a19917daSJordy Rose 129447762daSMichael J. Spencer #endif 130447762daSMichael J. Spencer 131c1db8cf9SFrederich Munch char DynamicLibrary::Invalid; 1325fdd2cbaSFrederich Munch DynamicLibrary::SearchOrdering DynamicLibrary::SearchOrder = 1335fdd2cbaSFrederich Munch DynamicLibrary::SO_Linker; 134c1db8cf9SFrederich Munch 135447762daSMichael J. Spencer namespace llvm { 136c1db8cf9SFrederich Munch void *SearchForAddressOfSpecialSymbol(const char *SymbolName) { 137c1db8cf9SFrederich Munch return DoSearch(SymbolName); // DynamicLibrary.inc 138c1db8cf9SFrederich Munch } 139*0164d546SSimon Pilgrim } // namespace llvm 140447762daSMichael J. Spencer 141c1db8cf9SFrederich Munch void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) { 142c1db8cf9SFrederich Munch SmartScopedLock<true> Lock(*SymbolsMutex); 143c1db8cf9SFrederich Munch (*ExplicitSymbols)[SymbolName] = SymbolValue; 144c1db8cf9SFrederich Munch } 145c1db8cf9SFrederich Munch 146c1db8cf9SFrederich Munch DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName, 147c1db8cf9SFrederich Munch std::string *Err) { 1488c3735e5SFrederich Munch // Force OpenedHandles to be added into the ManagedStatic list before any 1498c3735e5SFrederich Munch // ManagedStatic can be added from static constructors in HandleSet::DLOpen. 1508c3735e5SFrederich Munch HandleSet& HS = *OpenedHandles; 1518c3735e5SFrederich Munch 152c1db8cf9SFrederich Munch void *Handle = HandleSet::DLOpen(FileName, Err); 1538c3735e5SFrederich Munch if (Handle != &Invalid) { 1548c3735e5SFrederich Munch SmartScopedLock<true> Lock(*SymbolsMutex); 1558c3735e5SFrederich Munch HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr); 1568c3735e5SFrederich Munch } 157c1db8cf9SFrederich Munch 158c1db8cf9SFrederich Munch return DynamicLibrary(Handle); 159c1db8cf9SFrederich Munch } 160c1db8cf9SFrederich Munch 161c1db8cf9SFrederich Munch DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle, 162c1db8cf9SFrederich Munch std::string *Err) { 163c1db8cf9SFrederich Munch SmartScopedLock<true> Lock(*SymbolsMutex); 164c1db8cf9SFrederich Munch // If we've already loaded this library, tell the caller. 165c1db8cf9SFrederich Munch if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false)) 166c1db8cf9SFrederich Munch *Err = "Library already loaded"; 167c1db8cf9SFrederich Munch 168c1db8cf9SFrederich Munch return DynamicLibrary(Handle); 169c1db8cf9SFrederich Munch } 170c1db8cf9SFrederich Munch 171c1db8cf9SFrederich Munch void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) { 172c1db8cf9SFrederich Munch if (!isValid()) 173c1db8cf9SFrederich Munch return nullptr; 174c1db8cf9SFrederich Munch return HandleSet::DLSym(Data, SymbolName); 175c1db8cf9SFrederich Munch } 176c1db8cf9SFrederich Munch 177c1db8cf9SFrederich Munch void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) { 178c1db8cf9SFrederich Munch { 17957093e88SFilip Pizlo SmartScopedLock<true> Lock(*SymbolsMutex); 180a19917daSJordy Rose 181447762daSMichael J. Spencer // First check symbols added via AddSymbol(). 18257093e88SFilip Pizlo if (ExplicitSymbols.isConstructed()) { 183c1db8cf9SFrederich Munch StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName); 184447762daSMichael J. Spencer 185a19917daSJordy Rose if (i != ExplicitSymbols->end()) 186a19917daSJordy Rose return i->second; 187447762daSMichael J. Spencer } 188447762daSMichael J. Spencer 189447762daSMichael J. Spencer // Now search the libraries. 19059e5a644SVassil Vassilev if (OpenedHandles.isConstructed()) { 1915fdd2cbaSFrederich Munch if (void *Ptr = OpenedHandles->Lookup(SymbolName, SearchOrder)) 192c1db8cf9SFrederich Munch return Ptr; 193447762daSMichael J. Spencer } 194447762daSMichael J. Spencer } 195447762daSMichael J. Spencer 196c1db8cf9SFrederich Munch return llvm::SearchForAddressOfSpecialSymbol(SymbolName); 197c1db8cf9SFrederich Munch } 19834ddbf1aSPeter Zotov 19934ddbf1aSPeter Zotov //===----------------------------------------------------------------------===// 20034ddbf1aSPeter Zotov // C API. 20134ddbf1aSPeter Zotov //===----------------------------------------------------------------------===// 20234ddbf1aSPeter Zotov 20334ddbf1aSPeter Zotov LLVMBool LLVMLoadLibraryPermanently(const char *Filename) { 204671fe2eeSPeter Zotov return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename); 20534ddbf1aSPeter Zotov } 206af79f3dbSEli Bendersky 207af79f3dbSEli Bendersky void *LLVMSearchForAddressOfSymbol(const char *symbolName) { 208af79f3dbSEli Bendersky return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName); 209af79f3dbSEli Bendersky } 210af79f3dbSEli Bendersky 211af79f3dbSEli Bendersky void LLVMAddSymbol(const char *symbolName, void *symbolValue) { 212af79f3dbSEli Bendersky return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue); 213af79f3dbSEli Bendersky } 214