DynamicLibrary.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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/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) {
  37. return std::find(Handles.begin(), Handles.end(), Handle);
  38. }
  39. bool Contains(void *Handle) {
  40. return Handle == Process || Find(Handle) != Handles.end();
  41. }
  42. bool AddLibrary(void *Handle, bool IsProcess = false, bool CanClose = true) {
  43. #ifdef LLVM_ON_WIN32
  44. assert((Handle == this ? IsProcess : !IsProcess) && "Bad Handle.");
  45. #endif
  46. if (LLVM_LIKELY(!IsProcess)) {
  47. if (Find(Handle) != Handles.end()) {
  48. if (CanClose)
  49. DLClose(Handle);
  50. return false;
  51. }
  52. Handles.push_back(Handle);
  53. } else {
  54. #ifndef LLVM_ON_WIN32
  55. if (Process) {
  56. if (CanClose)
  57. DLClose(Process);
  58. if (Process == Handle)
  59. return false;
  60. }
  61. #endif
  62. Process = Handle;
  63. }
  64. return true;
  65. }
  66. void *Lookup(const char *Symbol) {
  67. // Process handle gets first try.
  68. if (Process) {
  69. if (void *Ptr = DLSym(Process, Symbol))
  70. return Ptr;
  71. #ifndef NDEBUG
  72. for (void *Handle : Handles)
  73. assert(!DLSym(Handle, Symbol) && "Symbol exists in non process handle");
  74. #endif
  75. } else {
  76. // Iterate in reverse, so newer libraries/symbols override older.
  77. for (auto &&I = Handles.rbegin(), E = Handles.rend(); I != E; ++I) {
  78. if (void *Ptr = DLSym(*I, Symbol))
  79. return Ptr;
  80. }
  81. }
  82. return nullptr;
  83. }
  84. };
  85. namespace {
  86. // Collection of symbol name/value pairs to be searched prior to any libraries.
  87. static llvm::ManagedStatic<llvm::StringMap<void *>> ExplicitSymbols;
  88. // Collection of known library handles.
  89. static llvm::ManagedStatic<DynamicLibrary::HandleSet> OpenedHandles;
  90. // Lock for ExplicitSymbols and OpenedHandles.
  91. static llvm::ManagedStatic<llvm::sys::SmartMutex<true>> SymbolsMutex;
  92. }
  93. #ifdef LLVM_ON_WIN32
  94. #include "Windows/DynamicLibrary.inc"
  95. #else
  96. #include "Unix/DynamicLibrary.inc"
  97. #endif
  98. char DynamicLibrary::Invalid;
  99. namespace llvm {
  100. void *SearchForAddressOfSpecialSymbol(const char *SymbolName) {
  101. return DoSearch(SymbolName); // DynamicLibrary.inc
  102. }
  103. }
  104. void DynamicLibrary::AddSymbol(StringRef SymbolName, void *SymbolValue) {
  105. SmartScopedLock<true> Lock(*SymbolsMutex);
  106. (*ExplicitSymbols)[SymbolName] = SymbolValue;
  107. }
  108. DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *FileName,
  109. std::string *Err) {
  110. SmartScopedLock<true> Lock(*SymbolsMutex);
  111. void *Handle = HandleSet::DLOpen(FileName, Err);
  112. if (Handle != &Invalid)
  113. OpenedHandles->AddLibrary(Handle, /*IsProcess*/ FileName == nullptr);
  114. return DynamicLibrary(Handle);
  115. }
  116. DynamicLibrary DynamicLibrary::addPermanentLibrary(void *Handle,
  117. std::string *Err) {
  118. SmartScopedLock<true> Lock(*SymbolsMutex);
  119. // If we've already loaded this library, tell the caller.
  120. if (!OpenedHandles->AddLibrary(Handle, /*IsProcess*/false, /*CanClose*/false))
  121. *Err = "Library already loaded";
  122. return DynamicLibrary(Handle);
  123. }
  124. void *DynamicLibrary::getAddressOfSymbol(const char *SymbolName) {
  125. if (!isValid())
  126. return nullptr;
  127. return HandleSet::DLSym(Data, SymbolName);
  128. }
  129. void *DynamicLibrary::SearchForAddressOfSymbol(const char *SymbolName) {
  130. {
  131. SmartScopedLock<true> Lock(*SymbolsMutex);
  132. // First check symbols added via AddSymbol().
  133. if (ExplicitSymbols.isConstructed()) {
  134. StringMap<void *>::iterator i = ExplicitSymbols->find(SymbolName);
  135. if (i != ExplicitSymbols->end())
  136. return i->second;
  137. }
  138. // Now search the libraries.
  139. if (OpenedHandles.isConstructed()) {
  140. if (void *Ptr = OpenedHandles->Lookup(SymbolName))
  141. return Ptr;
  142. }
  143. }
  144. return llvm::SearchForAddressOfSpecialSymbol(SymbolName);
  145. }
  146. //===----------------------------------------------------------------------===//
  147. // C API.
  148. //===----------------------------------------------------------------------===//
  149. LLVMBool LLVMLoadLibraryPermanently(const char *Filename) {
  150. return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
  151. }
  152. void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
  153. return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  154. }
  155. void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
  156. return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
  157. }