1 //===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the operating system DynamicLibrary concept.
11 //===----------------------------------------------------------------------===//
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"
22 using namespace llvm::sys
;
24 // All methods for HandleSet should be used holding SymbolsMutex.
25 class DynamicLibrary::HandleSet
{
26 typedef std::vector
<void *> HandleList
;
28 void *Process
= nullptr;
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
);
35 HandleSet() = default;
38 HandleList::iterator
Find(void *Handle
) { return find(Handles
, Handle
); }
40 bool Contains(void *Handle
) {
41 return Handle
== Process
|| Find(Handle
) != Handles
.end();
44 bool AddLibrary(void *Handle
, bool IsProcess
= false, bool CanClose
= true,
45 bool AllowDuplicates
= false) {
47 assert((Handle
== this ? IsProcess
: !IsProcess
) && "Bad Handle.");
49 assert((!AllowDuplicates
|| !CanClose
) &&
50 "CanClose must be false if AllowDuplicates is true.");
52 if (LLVM_LIKELY(!IsProcess
)) {
53 if (!AllowDuplicates
&& Find(Handle
) != Handles
.end()) {
58 Handles
.push_back(Handle
);
64 if (Process
== Handle
)
73 void CloseLibrary(void *Handle
) {
75 HandleList::iterator it
= Find(Handle
);
76 if (it
!= Handles
.end()) {
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
))
88 for (void *Handle
: llvm::reverse(Handles
)) {
89 if (void *Ptr
= DLSym(Handle
, Symbol
))
96 void *Lookup(const char *Symbol
, DynamicLibrary::SearchOrdering Order
) {
97 assert(!((Order
& SO_LoadedFirst
) && (Order
& SO_LoadedLast
)) &&
100 if (!Process
|| (Order
& SO_LoadedFirst
)) {
101 if (void *Ptr
= LibLookup(Symbol
, Order
))
105 // Use OS facilities to search the current binary and all loaded libs.
106 if (void *Ptr
= DLSym(Process
, Symbol
))
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
))
122 // Collection of symbol name/value pairs to be searched prior to any
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
;
132 Globals
&getGlobals() {
141 #include "Windows/DynamicLibrary.inc"
145 #include "Unix/DynamicLibrary.inc"
149 char DynamicLibrary::Invalid
;
150 DynamicLibrary::SearchOrdering
DynamicLibrary::SearchOrder
=
151 DynamicLibrary::SO_Linker
;
154 void *SearchForAddressOfSpecialSymbol(const char *SymbolName
) {
155 return DoSearch(SymbolName
); // DynamicLibrary.inc
159 void DynamicLibrary::AddSymbol(StringRef SymbolName
, void *SymbolValue
) {
160 auto &G
= getGlobals();
161 SmartScopedLock
<true> Lock(G
.SymbolsMutex
);
162 G
.ExplicitSymbols
[SymbolName
] = SymbolValue
;
165 DynamicLibrary
DynamicLibrary::getPermanentLibrary(const char *FileName
,
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);
174 return DynamicLibrary(Handle
);
177 DynamicLibrary
DynamicLibrary::addPermanentLibrary(void *Handle
,
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,
184 *Err
= "Library already loaded";
186 return DynamicLibrary(Handle
);
189 DynamicLibrary
DynamicLibrary::getLibrary(const char *FileName
,
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,
198 /*AllowDuplicates*/ true);
200 return DynamicLibrary(Handle
);
203 void DynamicLibrary::closeLibrary(DynamicLibrary
&Lib
) {
204 auto &G
= getGlobals();
205 SmartScopedLock
<true> Lock(G
.SymbolsMutex
);
207 G
.OpenedTemporaryHandles
.CloseLibrary(Lib
.Data
);
212 void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName
) {
215 return HandleSet::DLSym(Data
, SymbolName
);
218 void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName
) {
220 auto &G
= getGlobals();
221 SmartScopedLock
<true> Lock(G
.SymbolsMutex
);
223 // First check symbols added via AddSymbol().
224 StringMap
<void *>::iterator i
= G
.ExplicitSymbols
.find(SymbolName
);
226 if (i
!= G
.ExplicitSymbols
.end())
229 // Now search the libraries.
230 if (void *Ptr
= G
.OpenedHandles
.Lookup(SymbolName
, SearchOrder
))
232 if (void *Ptr
= G
.OpenedTemporaryHandles
.Lookup(SymbolName
, SearchOrder
))
236 return llvm::SearchForAddressOfSpecialSymbol(SymbolName
);
239 //===----------------------------------------------------------------------===//
241 //===----------------------------------------------------------------------===//
243 LLVMBool
LLVMLoadLibraryPermanently(const char *Filename
) {
244 return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename
);
247 void *LLVMSearchForAddressOfSymbol(const char *symbolName
) {
248 return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName
);
251 void LLVMAddSymbol(const char *symbolName
, void *symbolValue
) {
252 return llvm::sys::DynamicLibrary::AddSymbol(symbolName
, symbolValue
);