DynamicLibrary.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  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. #include "llvm/Support/DynamicLibrary.h"
  13. #include "llvm-c/Support.h"
  14. #include "llvm/ADT/STLExtras.h"
  15. #include "llvm/ADT/StringMap.h"
  16. #include "llvm/Config/config.h"
  17. #include "llvm/Support/Mutex.h"
  18. #include <vector>
  19. using namespace llvm;
  20. using namespace llvm::sys;
  21. // All methods for HandleSet should be used holding SymbolsMutex.
  22. class DynamicLibrary::HandleSet {
  23. typedef std::vector<void *> HandleList;
  24. HandleList Handles;
  25. void *Process = nullptr;
  26. public:
  27. static void *DLOpen(const char *Filename, std::string *Err);
  28. static void DLClose(void *Handle);
  29. static void *DLSym(void *Handle, const char *Symbol);
  30. HandleSet() = default;
  31. ~HandleSet();
  32. HandleList::iterator Find(void *Handle) { return find(Handles, Handle); }
  33. bool Contains(void *Handle) {
  34. return Handle == Process || Find(Handle) != Handles.end();
  35. }
  36. bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true,
  37. bool AllowDuplicates = false) {
  38. #ifdef _WIN32
  39. assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
  40. #endif
  41. assert((!AllowDuplicates || !CanClose) &&
  42. "CanClose must be false if AllowDuplicates is true.");
  43. if (LLVM_LIKELY(!IsProcess)) {
  44. if (!AllowDuplicates && Find(Handle) != Handles.end()) {
  45. if (CanClose)
  46. DLClose(Handle);
  47. return false;
  48. }
  49. Handles.push_back(Handle);
  50. } else {
  51. #ifndef _WIN32
  52. if (Process) {
  53. if (CanClose)
  54. DLClose(Process);
  55. if (Process == Handle)
  56. return false;
  57. }
  58. #endif
  59. Process = Handle;
  60. }
  61. return true;
  62. }
  63. void CloseLibrary(void *Handle) {
  64. DLClose(Handle);
  65. HandleList::iterator it = Find(Handle);
  66. if (it != Handles.end()) {
  67. Handles.erase(it);
  68. }
  69. }
  70. void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
  71. if (Order & SO_LoadOrder) {
  72. for (void *Handle : Handles) {
  73. if (void *Ptr = DLSym(Handle, Symbol))
  74. return Ptr;
  75. }
  76. } else {
  77. for (void *Handle : llvm::reverse(Handles)) {
  78. if (void *Ptr = DLSym(Handle, Symbol))
  79. return Ptr;
  80. }
  81. }
  82. return nullptr;
  83. }
  84. void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
  85. assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) &&
  86. "Invalid Ordering");
  87. if (!Process || (Order & SO_LoadedFirst)) {
  88. if (void *Ptr = LibLookup(Symbol, Order))
  89. return Ptr;
  90. }
  91. if (Process) {
  92. // Use OS facilities to search the current binary and all loaded libs.
  93. if (void *Ptr = DLSym(Process, Symbol))
  94. return Ptr;
  95. // Search any libs that might have been skipped because of RTLD_LOCAL.
  96. if (Order & SO_LoadedLast) {
  97. if (void *Ptr = LibLookup(Symbol, Order))
  98. return Ptr;
  99. }
  100. }
  101. return nullptr;
  102. }
  103. };
  104. namespace {
  105. struct Globals {
  106. // Collection of symbol name/value pairs to be searched prior to any
  107. // libraries.
  108. llvm::StringMap<void *> ExplicitSymbols;
  109. // Collections of known library handles.
  110. DynamicLibrary::HandleSet OpenedHandles;
  111. DynamicLibrary::HandleSet OpenedTemporaryHandles;
  112. // Lock for ExplicitSymbols, OpenedHandles, and OpenedTemporaryHandles.
  113. llvm::sys::SmartMutex<true> SymbolsMutex;
  114. };
  115. Globals &getGlobals() {
  116. static Globals G;
  117. return G;
  118. }
  119. } // namespace
  120. #ifdef _WIN32
  121. #include "Windows/DynamicLibrary.inc"
  122. #else
  123. #include "Unix/DynamicLibrary.inc"
  124. #endif
  125. char DynamicLibrary::Invalid;
  126. DynamicLibrary::SearchOrdering DynamicLibrary::SearchOrder =
  127. DynamicLibrary::SO_Linker;
  128. namespace llvm {
  129. void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
  130. return DoSearch(SymbolName); // DynamicLibrary.inc
  131. }
  132. } // namespace llvm
  133. void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {
  134. auto &G = getGlobals();
  135. SmartScopedLock<true> Lock(G.SymbolsMutex);
  136. G.ExplicitSymbols[SymbolName] = SymbolValue;
  137. }
  138. DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName,
  139. std::string *Err) {
  140. auto &G = getGlobals();
  141. void *Handle = HandleSet::DLOpen(FileName, Err);
  142. if (Handle != &Invalid) {
  143. SmartScopedLock<true> Lock(G.SymbolsMutex);
  144. G.OpenedHandles.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
  145. }
  146. return DynamicLibrary(Handle);
  147. }
  148. DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle,
  149. std::string *Err) {
  150. auto &G = getGlobals();
  151. SmartScopedLock<true> Lock(G.SymbolsMutex);
  152. // If we've already loaded this library, tell the caller.
  153. if (!G.OpenedHandles.AddLibrary(Handle, /*IsProcess*/ false,
  154. /*CanClose*/ false))
  155. *Err = "Library already loaded";
  156. return DynamicLibrary(Handle);
  157. }
  158. DynamicLibrary DynamicLibrary::getLibrary(const char *FileName,
  159. std::string *Err) {
  160. assert(FileName && "Use getPermanentLibrary() for opening process handle");
  161. void *Handle = HandleSet::DLOpen(FileName, Err);
  162. if (Handle != &Invalid) {
  163. auto &G = getGlobals();
  164. SmartScopedLock<true> Lock(G.SymbolsMutex);
  165. G.OpenedTemporaryHandles.AddLibrary(Handle, /*IsProcess*/ false,
  166. /*CanClose*/ false,
  167. /*AllowDuplicates*/ true);
  168. }
  169. return DynamicLibrary(Handle);
  170. }
  171. void DynamicLibrary::closeLibrary(DynamicLibrary &Lib) {
  172. auto &G = getGlobals();
  173. SmartScopedLock<true> Lock(G.SymbolsMutex);
  174. if (Lib.isValid()) {
  175. G.OpenedTemporaryHandles.CloseLibrary(Lib.Data);
  176. Lib.Data = &Invalid;
  177. }
  178. }
  179. void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
  180. if (!isValid())
  181. return nullptr;
  182. return HandleSet::DLSym(Data, SymbolName);
  183. }
  184. void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
  185. {
  186. auto &G = getGlobals();
  187. SmartScopedLock<true> Lock(G.SymbolsMutex);
  188. // First check symbols added via AddSymbol().
  189. StringMap<void *>::iterator i = G.ExplicitSymbols.find(SymbolName);
  190. if (i != G.ExplicitSymbols.end())
  191. return i->second;
  192. // Now search the libraries.
  193. if (void *Ptr = G.OpenedHandles.Lookup(SymbolName, SearchOrder))
  194. return Ptr;
  195. if (void *Ptr = G.OpenedTemporaryHandles.Lookup(SymbolName, SearchOrder))
  196. return Ptr;
  197. }
  198. return llvm::SearchForAddressOfSpecialSymbol(SymbolName);
  199. }
  200. //===----------------------------------------------------------------------===//
  201. // C API.
  202. //===----------------------------------------------------------------------===//
  203. LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {
  204. return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
  205. }
  206. void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
  207. return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  208. }
  209. void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
  210. return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
  211. }