DynamicLibrary.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. //===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file implements the operating system DynamicLibrary concept.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/Support/DynamicLibrary.h"
  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"
  19. #include "llvm/Support/ManagedStatic.h"
  20. #include "llvm/Support/Mutex.h"
  21. #include <cstdio>
  22. #include <cstring>
  23. #include <vector>
  24. #ifdef __APPLE__
  25. #include <TargetConditionals.h>
  26. #if (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
  27. #include "ios_error.h"
  28. #endif
  29. #endif
  30. using namespace llvm;
  31. using namespace llvm::sys;
  32. // All methods for HandleSet should be used holding SymbolsMutex.
  33. class DynamicLibrary::HandleSet {
  34. typedef std::vector<void *> HandleList;
  35. HandleList Handles;
  36. void *Process;
  37. public:
  38. static void *DLOpen(const char *Filename, std::string *Err);
  39. static void DLClose(void *Handle);
  40. static void *DLSym(void *Handle, const char *Symbol);
  41. HandleSet() : Process(nullptr) {}
  42. ~HandleSet();
  43. HandleList::iterator Find(void *Handle) {
  44. return std::find(Handles.begin(), Handles.end(), Handle);
  45. }
  46. bool Contains(void *Handle) {
  47. return Handle == Process || Find(Handle) != Handles.end();
  48. }
  49. bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) {
  50. #ifdef LLVM_ON_WIN32
  51. assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
  52. #endif
  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 LLVM_ON_WIN32
  62. if (Process) {
  63. if (CanClose)
  64. DLClose(Process);
  65. if (Process == Handle)
  66. return false;
  67. }
  68. #endif
  69. Process = Handle;
  70. }
  71. return true;
  72. }
  73. void *LibLookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
  74. if (1 /* Order & SO_LoadOrder */) {
  75. for (void *Handle : Handles) {
  76. if (void *Ptr = DLSym(Handle, Symbol))
  77. return Ptr;
  78. }
  79. } else {
  80. for (void *Handle : llvm::reverse(Handles)) {
  81. if (void *Ptr = DLSym(Handle, Symbol))
  82. return Ptr;
  83. }
  84. }
  85. return nullptr;
  86. }
  87. void *Lookup(const char *Symbol, DynamicLibrary::SearchOrdering Order) {
  88. assert(!((Order & SO_LoadedFirst) && (Order & SO_LoadedLast)) &&
  89. "Invalid Ordering");
  90. if (1 /* !Process || (Order & SO_LoadedFirst)*/) {
  91. if (void *Ptr = LibLookup(Symbol, Order))
  92. return Ptr;
  93. }
  94. if (Process) {
  95. // Use OS facilities to search the current binary and all loaded libs.
  96. if (void *Ptr = DLSym(Process, Symbol))
  97. return Ptr;
  98. // Search any libs that might have been skipped because of RTLD_LOCAL.
  99. if (Order & SO_LoadedLast) {
  100. if (void *Ptr = LibLookup(Symbol, Order))
  101. return Ptr;
  102. }
  103. }
  104. return nullptr;
  105. }
  106. };
  107. namespace {
  108. // Collection of symbol name/value pairs to be searched prior to any libraries.
  109. static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols;
  110. // Collection of known library handles.
  111. static llvm::ManagedStatic<DynamicLibrary::HandleSet> OpenedHandles;
  112. // Lock for ExplicitSymbols and OpenedHandles.
  113. static llvm::ManagedStatic<llvm::sys::SmartMutex<true>> SymbolsMutex;
  114. }
  115. #ifdef LLVM_ON_WIN32
  116. #include "Windows/DynamicLibrary.inc"
  117. #else
  118. #include "Unix/DynamicLibrary.inc"
  119. #endif
  120. char DynamicLibrary::Invalid;
  121. DynamicLibrary::SearchOrdering DynamicLibrary::SearchOrder =
  122. DynamicLibrary::SO_Linker;
  123. namespace llvm {
  124. void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
  125. return DoSearch(SymbolName); // DynamicLibrary.inc
  126. }
  127. }
  128. void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {
  129. SmartScopedLock<true> Lock(*SymbolsMutex);
  130. (*ExplicitSymbols)[SymbolName] = SymbolValue;
  131. }
  132. DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName,
  133. std::string *Err) {
  134. // Force OpenedHandles to be added into the ManagedStatic list before any
  135. // ManagedStatic can be added from static constructors in HandleSet::DLOpen.
  136. HandleSet& HS = *OpenedHandles;
  137. void *Handle = HandleSet::DLOpen(FileName, Err);
  138. if (Handle != &Invalid) {
  139. SmartScopedLock<true> Lock(*SymbolsMutex);
  140. HS.AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
  141. }
  142. return DynamicLibrary(Handle);
  143. }
  144. DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle,
  145. std::string *Err) {
  146. SmartScopedLock<true> Lock(*SymbolsMutex);
  147. // If we've already loaded this library, tell the caller.
  148. if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false))
  149. *Err = "Library already loaded";
  150. return DynamicLibrary(Handle);
  151. }
  152. void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
  153. if (!isValid())
  154. return nullptr;
  155. return HandleSet::DLSym(Data, SymbolName);
  156. }
  157. void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
  158. {
  159. SmartScopedLock<true> Lock(*SymbolsMutex);
  160. // First check symbols added via AddSymbol().
  161. if (ExplicitSymbols.isConstructed()) {
  162. StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName);
  163. if (i != ExplicitSymbols->end())
  164. return i->second;
  165. // We did not find it. But that may be because of the "^A" or "_" in front:
  166. #if (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
  167. const char* symbolName = SymbolName;
  168. if (symbolName[0] == '\x01') {
  169. symbolName += 1;
  170. i = ExplicitSymbols->find(symbolName);
  171. if (i != ExplicitSymbols->end())
  172. return i->second;
  173. }
  174. if (symbolName[0] == '_') {
  175. symbolName += 1;
  176. i = ExplicitSymbols->find(symbolName);
  177. if (i != ExplicitSymbols->end())
  178. return i->second;
  179. }
  180. #endif
  181. }
  182. // Now search the libraries.
  183. if (OpenedHandles.isConstructed()) {
  184. if (void *Ptr = OpenedHandles->Lookup(SymbolName, SearchOrder ))
  185. return Ptr;
  186. }
  187. }
  188. return llvm::SearchForAddressOfSpecialSymbol(SymbolName);
  189. }
  190. //===----------------------------------------------------------------------===//
  191. // C API.
  192. //===----------------------------------------------------------------------===//
  193. LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {
  194. return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
  195. }
  196. void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
  197. return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  198. }
  199. void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
  200. return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
  201. }