LLVM  14.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/DenseSet.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/Config/config.h"
20 #include "llvm/Support/Mutex.h"
21 #include <cstdio>
22 #include <cstring>
23 #include <vector>
24 
25 using namespace llvm;
26 using namespace llvm::sys;
27 
28 // All methods for HandleSet should be used holding SymbolsMutex.
30  typedef std::vector<void *> HandleList;
31  HandleList Handles;
32  void *Process;
33 
34 public:
35  static void *DLOpen(const char *Filename, std::string *Err);
36  static void DLClose(void *Handle);
37  static void *DLSym(void *Handle, const char *Symbol);
38 
39  HandleSet() : Process(nullptr) {}
40  ~HandleSet();
41 
42  HandleList::iterator Find(void *Handle) { return find(Handles, Handle); }
43 
44  bool Contains(void *Handle) {
45  return Handle == Process || Find(Handle) != Handles.end();
46  }
47 
48  bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) {
49 #ifdef _WIN32
50  assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
51 #endif
52 
53  if (LLVM_LIKELY(!IsProcess)) {
54  if (Find(Handle) != Handles.end()) {
55  if (CanClose)
56  DLClose(Handle);
57  return false;
58  }
59  Handles.push_back(Handle);
60  } else {
61 #ifndef _WIN32
62  if (Process) {
63  if (CanClose)
65  if (Process == Handle)
66  return false;
67  }
68 #endif
69  Process = Handle;
70  }
71  return true;
72  }
73 
74  void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
75  if (Order & SO_LoadOrder) {
76  for (void *Handle : Handles) {
77  if (void *Ptr = DLSym(Handle, Symbol))
78  return Ptr;
79  }
80  } else {
81  for (void *Handle : llvm::reverse(Handles)) {
82  if (void *Ptr = DLSym(Handle, Symbol))
83  return Ptr;
84  }
85  }
86  return nullptr;
87  }
88 
89  void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
90  assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) &&
91  "Invalid Ordering");
92 
93  if (!Process || (Order & SO_LoadedFirst)) {
94  if (void *Ptr = LibLookup(Symbol, Order))
95  return Ptr;
96  }
97  if (Process) {
98  // Use OS facilities to search the current binary and all loaded libs.
99  if (void *Ptr = DLSym(Process, Symbol))
100  return Ptr;
101 
102  // Search any libs that might have been skipped because of RTLD_LOCAL.
103  if (Order & SO_LoadedLast) {
104  if (void *Ptr = LibLookup(Symbol, Order))
105  return Ptr;
106  }
107  }
108  return nullptr;
109  }
110 };
111 
112 namespace {
113 // Collection of symbol name/value pairs to be searched prior to any libraries.
114 static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols;
115 // Collection of known library handles.
117 // Lock for ExplicitSymbols and OpenedHandles.
119 } // namespace
120 
121 #ifdef _WIN32
122 
124 
125 #else
126 
127 #include "Unix/DynamicLibrary.inc"
128 
129 #endif
130 
131 char DynamicLibrary::Invalid;
134 
135 namespace llvm {
137  return DoSearch(SymbolName); // DynamicLibrary.inc
138 }
139 } // namespace llvm
140 
142  SmartScopedLock<true> Lock(*SymbolsMutex);
143  (*ExplicitSymbols)[SymbolName] = SymbolValue;
144 }
145 
147  std::string *Err) {
148  // Force OpenedHandles to be added into the ManagedStatic list before any
149  // ManagedStatic can be added from static constructors in HandleSet::DLOpen.
150  HandleSet& HS = *OpenedHandles;
151 
152  void *Handle = HandleSet::DLOpen(FileName, Err);
153  if (Handle != &Invalid) {
154  SmartScopedLock<true> Lock(*SymbolsMutex);
155  HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
156  }
157 
158  return DynamicLibrary(Handle);
159 }
160 
162  std::string *Err) {
163  SmartScopedLock<true> Lock(*SymbolsMutex);
164  // If we've already loaded this library, tell the caller.
165  if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false))
166  *Err = "Library already loaded";
167 
168  return DynamicLibrary(Handle);
169 }
170 
172  if (!isValid())
173  return nullptr;
174  return HandleSet::DLSym(Data, SymbolName);
175 }
176 
178  {
179  SmartScopedLock<true> Lock(*SymbolsMutex);
180 
181  // First check symbols added via AddSymbol().
182  if (ExplicitSymbols.isConstructed()) {
183  StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName);
184 
185  if (i != ExplicitSymbols->end())
186  return i->second;
187  }
188 
189  // Now search the libraries.
190  if (OpenedHandles.isConstructed()) {
191  if (void *Ptr = OpenedHandles->Lookup(SymbolName, SearchOrder))
192  return Ptr;
193  }
194  }
195 
197 }
198 
199 //===----------------------------------------------------------------------===//
200 // C API.
201 //===----------------------------------------------------------------------===//
202 
203 LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {
205 }
206 
207 void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
209 }
210 
211 void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
212  return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
213 }
i
i
Definition: README.txt:29
llvm::sys::DynamicLibrary::HandleSet::Contains
bool Contains(void *Handle)
Definition: DynamicLibrary.cpp:44
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::sys::DynamicLibrary::getAddressOfSymbol
void * getAddressOfSymbol(const char *symbolName)
Searches through the library for the symbol symbolName.
Definition: DynamicLibrary.cpp:171
llvm::sys::DynamicLibrary::HandleSet::AddLibrary
bool AddLibrary(void *Handle, bool IsProcess=false, bool CanClose=true)
Definition: DynamicLibrary.cpp:48
llvm::sys::DynamicLibrary::AddSymbol
static void AddSymbol(StringRef symbolName, void *symbolValue)
This functions permanently adds the symbol symbolName with the value symbolValue.
Definition: DynamicLibrary.cpp:141
ManagedStatic.h
DynamicLibrary.h
llvm::reverse
auto reverse(ContainerTy &&C, std::enable_if_t< has_rbegin< ContainerTy >::value > *=nullptr)
Definition: STLExtras.h:359
llvm::sys::DynamicLibrary::DynamicLibrary
DynamicLibrary(void *data=&Invalid)
Definition: DynamicLibrary.h:46
llvm::sys::DynamicLibrary::SO_LoadedFirst
@ SO_LoadedFirst
SO_LoadedFirst - Search all loaded libraries, then as SO_Linker would.
Definition: DynamicLibrary.h:96
STLExtras.h
llvm::sys
Definition: Atomic.h:28
DynamicLibrary.inc
llvm::sys::DynamicLibrary::HandleSet::DLSym
static void * DLSym(void *Handle, const char *Symbol)
llvm::sys::DynamicLibrary::HandleSet::~HandleSet
~HandleSet()
llvm::sys::DynamicLibrary::addPermanentLibrary
static DynamicLibrary addPermanentLibrary(void *handle, std::string *errMsg=nullptr)
Registers an externally loaded library.
Definition: DynamicLibrary.cpp:161
llvm::sys::DynamicLibrary
This class provides a portable interface to dynamic libraries which also might be known as shared lib...
Definition: DynamicLibrary.h:36
llvm::sys::Process
A collection of legacy interfaces for querying information about the current executing process.
Definition: Process.h:44
llvm::Lock
static sys::Mutex Lock
Definition: NVPTXUtilities.cpp:39
LLVMAddSymbol
void LLVMAddSymbol(const char *symbolName, void *symbolValue)
This functions permanently adds the symbol symbolName with the value symbolValue.
Definition: DynamicLibrary.cpp:211
llvm::sys::DynamicLibrary::HandleSet::Lookup
void * Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order)
Definition: DynamicLibrary.cpp:89
llvm::sys::DynamicLibrary::getPermanentLibrary
static DynamicLibrary getPermanentLibrary(const char *filename, std::string *errMsg=nullptr)
This function permanently loads the dynamic library at the given path.
Definition: DynamicLibrary.cpp:146
llvm::ManagedStatic
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:83
DenseSet.h
llvm::AArch64CC::HS
@ HS
Definition: AArch64BaseInfo.h:257
llvm::sys::DynamicLibrary::SO_LoadOrder
@ SO_LoadOrder
SO_LoadOrder - Or this in to search libraries in the ordered loaded.
Definition: DynamicLibrary.h:102
StringMap.h
llvm::sys::DynamicLibrary::SearchForAddressOfSymbol
static void * SearchForAddressOfSymbol(const char *symbolName)
This function will search through all previously loaded dynamic libraries for the symbol symbolName.
Definition: DynamicLibrary.cpp:177
llvm::sys::DynamicLibrary::isValid
bool isValid() const
Returns true if the object refers to a valid library.
Definition: DynamicLibrary.h:49
llvm::sys::DynamicLibrary::HandleSet::DLOpen
static void * DLOpen(const char *Filename, std::string *Err)
llvm::sys::DynamicLibrary::SO_LoadedLast
@ SO_LoadedLast
SO_LoadedLast - Search as SO_Linker would, then loaded libraries.
Definition: DynamicLibrary.h:99
DynamicLibrary.inc
llvm::StringMapIterator
Definition: StringMap.h:25
LLVMSearchForAddressOfSymbol
void * LLVMSearchForAddressOfSymbol(const char *symbolName)
This function will search through all previously loaded dynamic libraries for the symbol symbolName.
Definition: DynamicLibrary.cpp:207
llvm::find
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:1601
llvm::sys::DynamicLibrary::HandleSet::Find
HandleList::iterator Find(void *Handle)
Definition: DynamicLibrary.cpp:42
llvm::sys::DynamicLibrary::SO_Linker
@ SO_Linker
SO_Linker - Search as a call to dlsym(dlopen(NULL)) would when DynamicLibrary::getPermanentLibrary(NU...
Definition: DynamicLibrary.h:94
llvm::sys::SmartScopedLock
std::lock_guard< SmartMutex< mt_only > > SmartScopedLock
Definition: Mutex.h:71
llvm::sys::DynamicLibrary::HandleSet
Definition: DynamicLibrary.cpp:29
Support.h
llvm::sys::DynamicLibrary::SearchOrder
static SearchOrdering SearchOrder
Definition: DynamicLibrary.h:104
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::sys::DynamicLibrary::HandleSet::HandleSet
HandleSet()
Definition: DynamicLibrary.cpp:39
llvm::sys::DynamicLibrary::HandleSet::LibLookup
void * LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order)
Definition: DynamicLibrary.cpp:74
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm::SearchForAddressOfSpecialSymbol
void * SearchForAddressOfSpecialSymbol(const char *SymbolName)
Definition: DynamicLibrary.cpp:136
Mutex.h
llvm::AMDGPU::HSAMD::Kernel::Key::SymbolName
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
Definition: AMDGPUMetadata.h:381
LLVMBool
int LLVMBool
Definition: Types.h:28
llvm::sys::DynamicLibrary::HandleSet::DLClose
static void DLClose(void *Handle)
llvm::ARMBuildAttrs::Symbol
@ Symbol
Definition: ARMBuildAttributes.h:79
LLVM_LIKELY
#define LLVM_LIKELY(EXPR)
Definition: Compiler.h:225
llvm::sys::DynamicLibrary::SearchOrdering
SearchOrdering
Definition: DynamicLibrary.h:90
llvm::sys::DynamicLibrary::LoadLibraryPermanently
static bool LoadLibraryPermanently(const char *Filename, std::string *ErrMsg=nullptr)
This function permanently loads the dynamic library at the given path.
Definition: DynamicLibrary.h:85
LLVMLoadLibraryPermanently
LLVMBool LLVMLoadLibraryPermanently(const char *Filename)
This function permanently loads the dynamic library at the given path.
Definition: DynamicLibrary.cpp:203