Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Support/DynamicLibrary.cpp
35232 views
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
13
#include "llvm/Support/DynamicLibrary.h"
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
21
using namespace llvm;
22
using namespace llvm::sys;
23
24
// All methods for HandleSet should be used holding SymbolsMutex.
25
class DynamicLibrary::HandleSet {
26
typedef std::vector<void *> HandleList;
27
HandleList Handles;
28
void *Process = nullptr;
29
30
public:
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;
36
~HandleSet();
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)
63
DLClose(Process);
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
119
namespace {
120
121
struct 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
132
Globals &getGlobals() {
133
static Globals G;
134
return G;
135
}
136
137
} // namespace
138
139
#ifdef _WIN32
140
141
#include "Windows/DynamicLibrary.inc"
142
143
#else
144
145
#include "Unix/DynamicLibrary.inc"
146
147
#endif
148
149
char DynamicLibrary::Invalid;
150
DynamicLibrary::SearchOrdering DynamicLibrary::SearchOrder =
151
DynamicLibrary::SO_Linker;
152
153
namespace llvm {
154
void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
155
return DoSearch(SymbolName); // DynamicLibrary.inc
156
}
157
} // namespace llvm
158
159
void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {
160
auto &G = getGlobals();
161
SmartScopedLock<true> Lock(G.SymbolsMutex);
162
G.ExplicitSymbols[SymbolName] = SymbolValue;
163
}
164
165
DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName,
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
177
DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle,
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
189
DynamicLibrary DynamicLibrary::getLibrary(const char *FileName,
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
203
void DynamicLibrary::closeLibrary(DynamicLibrary &Lib) {
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
212
void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
213
if (!isValid())
214
return nullptr;
215
return HandleSet::DLSym(Data, SymbolName);
216
}
217
218
void *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
243
LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {
244
return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
245
}
246
247
void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
248
return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
249
}
250
251
void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
252
return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
253
}
254
255