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"
155fdd2cbaSFrederich Munch #include "llvm/ADT/STLExtras.h"
16ed0881b2SChandler Carruth #include "llvm/ADT/StringMap.h"
17447762daSMichael J. Spencer #include "llvm/Config/config.h"
188a8cd2baSChandler Carruth #include "llvm/Support/ManagedStatic.h"
19ed0881b2SChandler Carruth #include "llvm/Support/Mutex.h"
20c1db8cf9SFrederich Munch #include <vector>
21447762daSMichael J. Spencer
22c1db8cf9SFrederich Munch using namespace llvm;
23c1db8cf9SFrederich Munch using namespace llvm::sys;
24fd96d5e1SFrederich Munch
25c1db8cf9SFrederich Munch // All methods for HandleSet should be used holding SymbolsMutex.
26c1db8cf9SFrederich Munch class DynamicLibrary::HandleSet {
27c1db8cf9SFrederich Munch typedef std::vector<void *> HandleList;
28c1db8cf9SFrederich Munch HandleList Handles;
29*6c396875SKazu Hirata void *Process = nullptr;
30c1db8cf9SFrederich Munch
31c1db8cf9SFrederich Munch public:
32c1db8cf9SFrederich Munch static void *DLOpen(const char *Filename, std::string *Err);
33c1db8cf9SFrederich Munch static void DLClose(void *Handle);
34c1db8cf9SFrederich Munch static void *DLSym(void *Handle, const char *Symbol);
35c1db8cf9SFrederich Munch
36*6c396875SKazu Hirata HandleSet() = default;
37c1db8cf9SFrederich Munch ~HandleSet();
38c1db8cf9SFrederich Munch
Find(void * Handle)3988572024SKazu Hirata HandleList::iterator Find(void *Handle) { return find(Handles, Handle); }
40b8c236a6SFrederich Munch
Contains(void * Handle)41c1db8cf9SFrederich Munch bool Contains(void *Handle) {
42c1db8cf9SFrederich Munch return Handle == Process || Find(Handle) != Handles.end();
43c1db8cf9SFrederich Munch }
44c1db8cf9SFrederich Munch
AddLibrary(void * Handle,bool IsProcess=false,bool CanClose=true)45c1db8cf9SFrederich Munch bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) {
46712e8d29SNico Weber #ifdef _WIN32
47c1db8cf9SFrederich Munch assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
48c1db8cf9SFrederich Munch #endif
49c1db8cf9SFrederich Munch
50c1db8cf9SFrederich Munch if (LLVM_LIKELY(!IsProcess)) {
51c1db8cf9SFrederich Munch if (Find(Handle) != Handles.end()) {
52c1db8cf9SFrederich Munch if (CanClose)
53c1db8cf9SFrederich Munch DLClose(Handle);
54c1db8cf9SFrederich Munch return false;
55c1db8cf9SFrederich Munch }
56c1db8cf9SFrederich Munch Handles.push_back(Handle);
57c1db8cf9SFrederich Munch } else {
58712e8d29SNico Weber #ifndef _WIN32
59c1db8cf9SFrederich Munch if (Process) {
60c1db8cf9SFrederich Munch if (CanClose)
61c1db8cf9SFrederich Munch DLClose(Process);
62c1db8cf9SFrederich Munch if (Process == Handle)
63c1db8cf9SFrederich Munch return false;
64c1db8cf9SFrederich Munch }
65c1db8cf9SFrederich Munch #endif
66c1db8cf9SFrederich Munch Process = Handle;
67c1db8cf9SFrederich Munch }
68c1db8cf9SFrederich Munch return true;
69c1db8cf9SFrederich Munch }
70c1db8cf9SFrederich Munch
LibLookup(const char * Symbol,DynamicLibrary::SearchOrdering Order)715fdd2cbaSFrederich Munch void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
725fdd2cbaSFrederich Munch if (Order & SO_LoadOrder) {
735fdd2cbaSFrederich Munch for (void *Handle : Handles) {
745fdd2cbaSFrederich Munch if (void *Ptr = DLSym(Handle, Symbol))
755fdd2cbaSFrederich Munch return Ptr;
765fdd2cbaSFrederich Munch }
775fdd2cbaSFrederich Munch } else {
785fdd2cbaSFrederich Munch for (void *Handle : llvm::reverse(Handles)) {
795fdd2cbaSFrederich Munch if (void *Ptr = DLSym(Handle, Symbol))
805fdd2cbaSFrederich Munch return Ptr;
815fdd2cbaSFrederich Munch }
825fdd2cbaSFrederich Munch }
835fdd2cbaSFrederich Munch return nullptr;
845fdd2cbaSFrederich Munch }
855fdd2cbaSFrederich Munch
Lookup(const char * Symbol,DynamicLibrary::SearchOrdering Order)865fdd2cbaSFrederich Munch void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
875fdd2cbaSFrederich Munch assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) &&
885fdd2cbaSFrederich Munch "Invalid Ordering");
895fdd2cbaSFrederich Munch
905fdd2cbaSFrederich Munch if (!Process || (Order & SO_LoadedFirst)) {
915fdd2cbaSFrederich Munch if (void *Ptr = LibLookup(Symbol, Order))
925fdd2cbaSFrederich Munch return Ptr;
935fdd2cbaSFrederich Munch }
94c1db8cf9SFrederich Munch if (Process) {
955fdd2cbaSFrederich Munch // Use OS facilities to search the current binary and all loaded libs.
96c1db8cf9SFrederich Munch if (void *Ptr = DLSym(Process, Symbol))
97c1db8cf9SFrederich Munch return Ptr;
985fdd2cbaSFrederich Munch
995fdd2cbaSFrederich Munch // Search any libs that might have been skipped because of RTLD_LOCAL.
1005fdd2cbaSFrederich Munch if (Order & SO_LoadedLast) {
1015fdd2cbaSFrederich Munch if (void *Ptr = LibLookup(Symbol, Order))
102c1db8cf9SFrederich Munch return Ptr;
103c1db8cf9SFrederich Munch }
104c1db8cf9SFrederich Munch }
105c1db8cf9SFrederich Munch return nullptr;
106c1db8cf9SFrederich Munch }
107c1db8cf9SFrederich Munch };
108c1db8cf9SFrederich Munch
109c1db8cf9SFrederich Munch namespace {
110c1db8cf9SFrederich Munch // Collection of symbol name/value pairs to be searched prior to any libraries.
111c1db8cf9SFrederich Munch static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols;
112c1db8cf9SFrederich Munch // Collection of known library handles.
113c1db8cf9SFrederich Munch static llvm::ManagedStatic<DynamicLibrary::HandleSet> OpenedHandles;
114c1db8cf9SFrederich Munch // Lock for ExplicitSymbols and OpenedHandles.
115c1db8cf9SFrederich Munch static llvm::ManagedStatic<llvm::sys::SmartMutex<true>> SymbolsMutex;
1160164d546SSimon Pilgrim } // namespace
117fd96d5e1SFrederich Munch
118712e8d29SNico Weber #ifdef _WIN32
119447762daSMichael J. Spencer
120447762daSMichael J. Spencer #include "Windows/DynamicLibrary.inc"
121447762daSMichael J. Spencer
122447762daSMichael J. Spencer #else
123447762daSMichael J. Spencer
124c1db8cf9SFrederich Munch #include "Unix/DynamicLibrary.inc"
125a19917daSJordy Rose
126447762daSMichael J. Spencer #endif
127447762daSMichael J. Spencer
128c1db8cf9SFrederich Munch char DynamicLibrary::Invalid;
1295fdd2cbaSFrederich Munch DynamicLibrary::SearchOrdering DynamicLibrary::SearchOrder =
1305fdd2cbaSFrederich Munch DynamicLibrary::SO_Linker;
131c1db8cf9SFrederich Munch
132447762daSMichael J. Spencer namespace llvm {
SearchForAddressOfSpecialSymbol(const char * SymbolName)133c1db8cf9SFrederich Munch void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
134c1db8cf9SFrederich Munch return DoSearch(SymbolName); // DynamicLibrary.inc
135c1db8cf9SFrederich Munch }
1360164d546SSimon Pilgrim } // namespace llvm
137447762daSMichael J. Spencer
AddSymbol(StringRef SymbolName,void * SymbolValue)138c1db8cf9SFrederich Munch void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {
139c1db8cf9SFrederich Munch SmartScopedLock<true> Lock(*SymbolsMutex);
140c1db8cf9SFrederich Munch (*ExplicitSymbols)[SymbolName] = SymbolValue;
141c1db8cf9SFrederich Munch }
142c1db8cf9SFrederich Munch
getPermanentLibrary(const char * FileName,std::string * Err)143c1db8cf9SFrederich Munch DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName,
144c1db8cf9SFrederich Munch std::string *Err) {
1458c3735e5SFrederich Munch // Force OpenedHandles to be added into the ManagedStatic list before any
1468c3735e5SFrederich Munch // ManagedStatic can be added from static constructors in HandleSet::DLOpen.
1478c3735e5SFrederich Munch HandleSet& HS = *OpenedHandles;
1488c3735e5SFrederich Munch
149c1db8cf9SFrederich Munch void *Handle = HandleSet::DLOpen(FileName, Err);
1508c3735e5SFrederich Munch if (Handle != &Invalid) {
1518c3735e5SFrederich Munch SmartScopedLock<true> Lock(*SymbolsMutex);
1528c3735e5SFrederich Munch HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
1538c3735e5SFrederich Munch }
154c1db8cf9SFrederich Munch
155c1db8cf9SFrederich Munch return DynamicLibrary(Handle);
156c1db8cf9SFrederich Munch }
157c1db8cf9SFrederich Munch
addPermanentLibrary(void * Handle,std::string * Err)158c1db8cf9SFrederich Munch DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle,
159c1db8cf9SFrederich Munch std::string *Err) {
160c1db8cf9SFrederich Munch SmartScopedLock<true> Lock(*SymbolsMutex);
161c1db8cf9SFrederich Munch // If we've already loaded this library, tell the caller.
162c1db8cf9SFrederich Munch if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false))
163c1db8cf9SFrederich Munch *Err = "Library already loaded";
164c1db8cf9SFrederich Munch
165c1db8cf9SFrederich Munch return DynamicLibrary(Handle);
166c1db8cf9SFrederich Munch }
167c1db8cf9SFrederich Munch
getAddressOfSymbol(const char * SymbolName)168c1db8cf9SFrederich Munch void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
169c1db8cf9SFrederich Munch if (!isValid())
170c1db8cf9SFrederich Munch return nullptr;
171c1db8cf9SFrederich Munch return HandleSet::DLSym(Data, SymbolName);
172c1db8cf9SFrederich Munch }
173c1db8cf9SFrederich Munch
SearchForAddressOfSymbol(const char * SymbolName)174c1db8cf9SFrederich Munch void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
175c1db8cf9SFrederich Munch {
17657093e88SFilip Pizlo SmartScopedLock<true> Lock(*SymbolsMutex);
177a19917daSJordy Rose
178447762daSMichael J. Spencer // First check symbols added via AddSymbol().
17957093e88SFilip Pizlo if (ExplicitSymbols.isConstructed()) {
180c1db8cf9SFrederich Munch StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName);
181447762daSMichael J. Spencer
182a19917daSJordy Rose if (i != ExplicitSymbols->end())
183a19917daSJordy Rose return i->second;
184447762daSMichael J. Spencer }
185447762daSMichael J. Spencer
186447762daSMichael J. Spencer // Now search the libraries.
18759e5a644SVassil Vassilev if (OpenedHandles.isConstructed()) {
1885fdd2cbaSFrederich Munch if (void *Ptr = OpenedHandles->Lookup(SymbolName, SearchOrder))
189c1db8cf9SFrederich Munch return Ptr;
190447762daSMichael J. Spencer }
191447762daSMichael J. Spencer }
192447762daSMichael J. Spencer
193c1db8cf9SFrederich Munch return llvm::SearchForAddressOfSpecialSymbol(SymbolName);
194c1db8cf9SFrederich Munch }
19534ddbf1aSPeter Zotov
19634ddbf1aSPeter Zotov //===----------------------------------------------------------------------===//
19734ddbf1aSPeter Zotov // C API.
19834ddbf1aSPeter Zotov //===----------------------------------------------------------------------===//
19934ddbf1aSPeter Zotov
LLVMLoadLibraryPermanently(const char * Filename)20034ddbf1aSPeter Zotov LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {
201671fe2eeSPeter Zotov return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
20234ddbf1aSPeter Zotov }
203af79f3dbSEli Bendersky
LLVMSearchForAddressOfSymbol(const char * symbolName)204af79f3dbSEli Bendersky void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
205af79f3dbSEli Bendersky return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
206af79f3dbSEli Bendersky }
207af79f3dbSEli Bendersky
LLVMAddSymbol(const char * symbolName,void * symbolValue)208af79f3dbSEli Bendersky void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
209af79f3dbSEli Bendersky return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
210af79f3dbSEli Bendersky }
211