DynamicLibrary.cpp 6.3 KB

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