LLVM 19.0.0git
DynamicLibrary.cpp
Go to the documentation of this file.
1//===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the operating system DynamicLibrary concept.
10//
11//===----------------------------------------------------------------------===//
12
14#include "llvm-c/Support.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/StringMap.h"
17#include "llvm/Config/config.h"
18#include "llvm/Support/Mutex.h"
19#include <vector>
20
21using namespace llvm;
22using namespace llvm::sys;
23
24// All methods for HandleSet should be used holding SymbolsMutex.
26 typedef std::vector<void *> HandleList;
27 HandleList Handles;
28 void *Process = nullptr;
29
30public:
31 static void *DLOpen(const char *Filename, std::string *Err);
32 static void DLClose(void *Handle);
33 static void *DLSym(void *Handle, const char *Symbol);
34
35 HandleSet() = default;
37
38 HandleList::iterator Find(void *Handle) { return find(Handles, Handle); }
39
40 bool Contains(void *Handle) {
41 return Handle == Process || Find(Handle) != Handles.end();
42 }
43
44 bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true,
45 bool AllowDuplicates = false) {
46#ifdef _WIN32
47 assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
48#endif
49 assert((!AllowDuplicates || !CanClose) &&
50 "CanClose must be false if AllowDuplicates is true.");
51
52 if (LLVM_LIKELY(!IsProcess)) {
53 if (!AllowDuplicates && Find(Handle) != Handles.end()) {
54 if (CanClose)
55 DLClose(Handle);
56 return false;
57 }
58 Handles.push_back(Handle);
59 } else {
60#ifndef _WIN32
61 if (Process) {
62 if (CanClose)
64 if (Process == Handle)
65 return false;
66 }
67#endif
68 Process = Handle;
69 }
70 return true;
71 }
72
73 void CloseLibrary(void *Handle) {
74 DLClose(Handle);
75 HandleList::iterator it = Find(Handle);
76 if (it != Handles.end()) {
77 Handles.erase(it);
78 }
79 }
80
81 void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
82 if (Order & SO_LoadOrder) {
83 for (void *Handle : Handles) {
84 if (void *Ptr = DLSym(Handle, Symbol))
85 return Ptr;
86 }
87 } else {
88 for (void *Handle : llvm::reverse(Handles)) {
89 if (void *Ptr = DLSym(Handle, Symbol))
90 return Ptr;
91 }
92 }
93 return nullptr;
94 }
95
96 void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
97 assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) &&
98 "Invalid Ordering");
99
100 if (!Process || (Order & SO_LoadedFirst)) {
101 if (void *Ptr = LibLookup(Symbol, Order))
102 return Ptr;
103 }
104 if (Process) {
105 // Use OS facilities to search the current binary and all loaded libs.
106 if (void *Ptr = DLSym(Process, Symbol))
107 return Ptr;
108
109 // Search any libs that might have been skipped because of RTLD_LOCAL.
110 if (Order & SO_LoadedLast) {
111 if (void *Ptr = LibLookup(Symbol, Order))
112 return Ptr;
113 }
114 }
115 return nullptr;
116 }
117};
118
119namespace {
120
121struct Globals {
122 // Collection of symbol name/value pairs to be searched prior to any
123 // libraries.
124 llvm::StringMap<void *> ExplicitSymbols;
125 // Collections of known library handles.
126 DynamicLibrary::HandleSet OpenedHandles;
127 DynamicLibrary::HandleSet OpenedTemporaryHandles;
128 // Lock for ExplicitSymbols, OpenedHandles, and OpenedTemporaryHandles.
129 llvm::sys::SmartMutex<true> SymbolsMutex;
130};
131
132Globals &getGlobals() {
133 static Globals G;
134 return G;
135}
136
137} // namespace
138
139#ifdef _WIN32
140
142
143#else
144
146
147#endif
148
149char DynamicLibrary::Invalid;
152
153namespace llvm {
154void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
155 return DoSearch(SymbolName); // DynamicLibrary.inc
156}
157} // namespace llvm
158
159void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {
160 auto &G = getGlobals();
161 SmartScopedLock<true> Lock(G.SymbolsMutex);
162 G.ExplicitSymbols[SymbolName] = SymbolValue;
163}
164
166 std::string *Err) {
167 auto &G = getGlobals();
168 void *Handle = HandleSet::DLOpen(FileName, Err);
169 if (Handle != &Invalid) {
170 SmartScopedLock<true> Lock(G.SymbolsMutex);
171 G.OpenedHandles.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
172 }
173
174 return DynamicLibrary(Handle);
175}
176
178 std::string *Err) {
179 auto &G = getGlobals();
180 SmartScopedLock<true> Lock(G.SymbolsMutex);
181 // If we've already loaded this library, tell the caller.
182 if (!G.OpenedHandles.AddLibrary(Handle, /*IsProcess*/ false,
183 /*CanClose*/ false))
184 *Err = "Library already loaded";
185
186 return DynamicLibrary(Handle);
187}
188
190 std::string *Err) {
191 assert(FileName && "Use getPermanentLibrary() for opening process handle");
192 void *Handle = HandleSet::DLOpen(FileName, Err);
193 if (Handle != &Invalid) {
194 auto &G = getGlobals();
195 SmartScopedLock<true> Lock(G.SymbolsMutex);
196 G.OpenedTemporaryHandles.AddLibrary(Handle, /*IsProcess*/ false,
197 /*CanClose*/ false,
198 /*AllowDuplicates*/ true);
199 }
200 return DynamicLibrary(Handle);
201}
202
204 auto &G = getGlobals();
205 SmartScopedLock<true> Lock(G.SymbolsMutex);
206 if (Lib.isValid()) {
207 G.OpenedTemporaryHandles.CloseLibrary(Lib.Data);
208 Lib.Data = &Invalid;
209 }
210}
211
212void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
213 if (!isValid())
214 return nullptr;
215 return HandleSet::DLSym(Data, SymbolName);
216}
217
218void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
219 {
220 auto &G = getGlobals();
221 SmartScopedLock<true> Lock(G.SymbolsMutex);
222
223 // First check symbols added via AddSymbol().
224 StringMap<void *>::iterator i = G.ExplicitSymbols.find(SymbolName);
225
226 if (i != G.ExplicitSymbols.end())
227 return i->second;
228
229 // Now search the libraries.
230 if (void *Ptr = G.OpenedHandles.Lookup(SymbolName, SearchOrder))
231 return Ptr;
232 if (void *Ptr = G.OpenedTemporaryHandles.Lookup(SymbolName, SearchOrder))
233 return Ptr;
234 }
235
236 return llvm::SearchForAddressOfSpecialSymbol(SymbolName);
237}
238
239//===----------------------------------------------------------------------===//
240// C API.
241//===----------------------------------------------------------------------===//
242
245}
246
247void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
249}
250
251void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
252 return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
253}
This file defines the StringMap class.
#define LLVM_LIKELY(EXPR)
Definition: Compiler.h:240
#define G(x, y, z)
Definition: MD5.cpp:56
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
bool AddLibrary(void *Handle, bool IsProcess=false, bool CanClose=true, bool AllowDuplicates=false)
void * Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order)
HandleList::iterator Find(void *Handle)
static void * DLOpen(const char *Filename, std::string *Err)
void * LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order)
static void * DLSym(void *Handle, const char *Symbol)
static void DLClose(void *Handle)
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:128
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
This class provides a portable interface to dynamic libraries which also might be known as shared lib...
static DynamicLibrary getLibrary(const char *FileName, std::string *Err=nullptr)
This function loads the dynamic library at the given path, using the library load operation from the ...
static DynamicLibrary addPermanentLibrary(void *handle, std::string *errMsg=nullptr)
Registers an externally loaded library.
static void AddSymbol(StringRef symbolName, void *symbolValue)
This functions permanently adds the symbol symbolName with the value symbolValue.
static bool LoadLibraryPermanently(const char *Filename, std::string *ErrMsg=nullptr)
This function permanently loads the dynamic library at the given path.
@ SO_LoadedLast
SO_LoadedLast - Search as SO_Linker would, then loaded libraries.
@ SO_LoadOrder
SO_LoadOrder - Or this in to search libraries in the ordered loaded.
@ SO_Linker
SO_Linker - Search as a call to dlsym(dlopen(NULL)) would when DynamicLibrary::getPermanentLibrary(NU...
@ SO_LoadedFirst
SO_LoadedFirst - Search all loaded libraries, then as SO_Linker would.
static DynamicLibrary getPermanentLibrary(const char *filename, std::string *errMsg=nullptr)
This function permanently loads the dynamic library at the given path using the library load operatio...
static SearchOrdering SearchOrder
void * getAddressOfSymbol(const char *symbolName)
Searches through the library for the symbol symbolName.
bool isValid() const
Returns true if the object refers to a valid library.
static void * SearchForAddressOfSymbol(const char *symbolName)
This function will search through all previously loaded dynamic libraries for the symbol symbolName.
static void closeLibrary(DynamicLibrary &Lib)
This function closes the dynamic library at the given path, using the library close operation of the ...
A collection of legacy interfaces for querying information about the current executing process.
Definition: Process.h:43
SmartMutex - A mutex with a compile time constant parameter that indicates whether this mutex should ...
Definition: Mutex.h:28
LLVMBool LLVMLoadLibraryPermanently(const char *Filename)
This function permanently loads the dynamic library at the given path.
void LLVMAddSymbol(const char *symbolName, void *symbolValue)
This functions permanently adds the symbol symbolName with the value symbolValue.
void * LLVMSearchForAddressOfSymbol(const char *symbolName)
This function will search through all previously loaded dynamic libraries for the symbol symbolName.
int LLVMBool
Definition: Types.h:28
std::lock_guard< SmartMutex< mt_only > > SmartScopedLock
Definition: Mutex.h:69
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1751
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:428
void * SearchForAddressOfSpecialSymbol(const char *SymbolName)