LLVM  10.0.0svn
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) {
43  return std::find(Handles.begin(), Handles.end(), Handle);
44  }
45 
46  bool Contains(void *Handle) {
47  return Handle == Process || Find(Handle) != Handles.end();
48  }
49 
50  bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) {
51 #ifdef _WIN32
52  assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
53 #endif
54 
55  if (LLVM_LIKELY(!IsProcess)) {
56  if (Find(Handle) != Handles.end()) {
57  if (CanClose)
58  DLClose(Handle);
59  return false;
60  }
61  Handles.push_back(Handle);
62  } else {
63 #ifndef _WIN32
64  if (Process) {
65  if (CanClose)
66  DLClose(Process);
67  if (Process == Handle)
68  return false;
69  }
70 #endif
71  Process = Handle;
72  }
73  return true;
74  }
75 
76  void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
77  if (Order & SO_LoadOrder) {
78  for (void *Handle : Handles) {
79  if (void *Ptr = DLSym(Handle, Symbol))
80  return Ptr;
81  }
82  } else {
83  for (void *Handle : llvm::reverse(Handles)) {
84  if (void *Ptr = DLSym(Handle, Symbol))
85  return Ptr;
86  }
87  }
88  return nullptr;
89  }
90 
91  void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
92  assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) &&
93  "Invalid Ordering");
94 
95  if (!Process || (Order & SO_LoadedFirst)) {
96  if (void *Ptr = LibLookup(Symbol, Order))
97  return Ptr;
98  }
99  if (Process) {
100  // Use OS facilities to search the current binary and all loaded libs.
101  if (void *Ptr = DLSym(Process, Symbol))
102  return Ptr;
103 
104  // Search any libs that might have been skipped because of RTLD_LOCAL.
105  if (Order & SO_LoadedLast) {
106  if (void *Ptr = LibLookup(Symbol, Order))
107  return Ptr;
108  }
109  }
110  return nullptr;
111  }
112 };
113 
114 namespace {
115 // Collection of symbol name/value pairs to be searched prior to any libraries.
116 static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols;
117 // Collection of known library handles.
119 // Lock for ExplicitSymbols and OpenedHandles.
121 }
122 
123 #ifdef _WIN32
124 
126 
127 #else
128 
129 #include "Unix/DynamicLibrary.inc"
130 
131 #endif
132 
133 char DynamicLibrary::Invalid;
136 
137 namespace llvm {
139  return DoSearch(SymbolName); // DynamicLibrary.inc
140 }
141 }
142 
144  SmartScopedLock<true> Lock(*SymbolsMutex);
145  (*ExplicitSymbols)[SymbolName] = SymbolValue;
146 }
147 
149  std::string *Err) {
150  // Force OpenedHandles to be added into the ManagedStatic list before any
151  // ManagedStatic can be added from static constructors in HandleSet::DLOpen.
152  HandleSet& HS = *OpenedHandles;
153 
154  void *Handle = HandleSet::DLOpen(FileName, Err);
155  if (Handle != &Invalid) {
156  SmartScopedLock<true> Lock(*SymbolsMutex);
157  HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
158  }
159 
160  return DynamicLibrary(Handle);
161 }
162 
164  std::string *Err) {
165  SmartScopedLock<true> Lock(*SymbolsMutex);
166  // If we've already loaded this library, tell the caller.
167  if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false))
168  *Err = "Library already loaded";
169 
170  return DynamicLibrary(Handle);
171 }
172 
174  if (!isValid())
175  return nullptr;
176  return HandleSet::DLSym(Data, SymbolName);
177 }
178 
180  {
181  SmartScopedLock<true> Lock(*SymbolsMutex);
182 
183  // First check symbols added via AddSymbol().
184  if (ExplicitSymbols.isConstructed()) {
185  StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName);
186 
187  if (i != ExplicitSymbols->end())
188  return i->second;
189  }
190 
191  // Now search the libraries.
192  if (OpenedHandles.isConstructed()) {
193  if (void *Ptr = OpenedHandles->Lookup(SymbolName, SearchOrder))
194  return Ptr;
195  }
196  }
197 
198  return llvm::SearchForAddressOfSpecialSymbol(SymbolName);
199 }
200 
201 //===----------------------------------------------------------------------===//
202 // C API.
203 //===----------------------------------------------------------------------===//
204 
205 LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {
207 }
208 
209 void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
211 }
212 
213 void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
214  return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
215 }
void * SearchForAddressOfSpecialSymbol(const char *SymbolName)
static void * SearchForAddressOfSymbol(const char *symbolName)
This function will search through all previously loaded dynamic libraries for the symbol symbolName...
This class represents lattice values for constants.
Definition: AllocatorList.h:23
#define LLVM_LIKELY(EXPR)
Definition: Compiler.h:203
DynamicLibrary(void *data=&Invalid)
static sys::Mutex Lock
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
static void * DLSym(void *Handle, const char *Symbol)
static void * DLOpen(const char *Filename, std::string *Err)
void * getAddressOfSymbol(const char *symbolName)
Searches through the library for the symbol symbolName.
static bool LoadLibraryPermanently(const char *Filename, std::string *ErrMsg=nullptr)
This function permanently loads the dynamic library at the given path.
This class provides a portable interface to dynamic libraries which also might be known as shared lib...
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
Definition: STLExtras.h:261
void * Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order)
void * LLVMSearchForAddressOfSymbol(const char *symbolName)
This function will search through all previously loaded dynamic libraries for the symbol symbolName...
static DynamicLibrary addPermanentLibrary(void *handle, std::string *errMsg=nullptr)
Registers an externally loaded library.
bool isValid() const
Returns true if the object refers to a valid library.
HandleList::iterator Find(void *Handle)
int LLVMBool
Definition: Types.h:29
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1186
static DynamicLibrary getPermanentLibrary(const char *filename, std::string *errMsg=nullptr)
This function permanently loads the dynamic library at the given path.
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. ...
SO_LoadedFirst - Search all loaded libraries, then as SO_Linker would.
SO_LoadedLast - Search as SO_Linker would, then loaded libraries.
std::lock_guard< SmartMutex< mt_only > > SmartScopedLock
Definition: Mutex.h:71
static void DLClose(void *Handle)
A collection of legacy interfaces for querying information about the current executing process...
Definition: Process.h:43
SO_Linker - Search as a call to dlsym(dlopen(NULL)) would when DynamicLibrary::getPermanentLibrary(NU...
static void AddSymbol(StringRef symbolName, void *symbolValue)
This functions permanently adds the symbol symbolName with the value symbolValue. ...
static SearchOrdering SearchOrder
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SO_LoadOrder - Or this in to search libraries in the ordered loaded.
void * LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order)
bool AddLibrary(void *Handle, bool IsProcess=false, bool CanClose=true)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:83