2
0

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. // FIXME: This file leaks ExplicitSymbols and OpenedHandles!
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #include "llvm/Support/DynamicLibrary.h"
  16. #include "llvm-c/Support.h"
  17. #include "llvm/ADT/DenseSet.h"
  18. #include "llvm/ADT/StringMap.h"
  19. #include "llvm/Config/config.h"
  20. #include "llvm/Support/ManagedStatic.h"
  21. #include "llvm/Support/Mutex.h"
  22. #include <cstdio>
  23. #include <cstring>
  24. // Collection of symbol name/value pairs to be searched prior to any libraries.
  25. static llvm::ManagedStatic<llvm::StringMap<void *> > ExplicitSymbols;
  26. static llvm::ManagedStatic<llvm::sys::SmartMutex<true> > SymbolsMutex;
  27. void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName,
  28. void *symbolValue) {
  29. SmartScopedLock<true> lock(*SymbolsMutex);
  30. (*ExplicitSymbols)[symbolName] = symbolValue;
  31. }
  32. char llvm::sys::DynamicLibrary::Invalid = 0;
  33. #ifdef LLVM_ON_WIN32
  34. #include "Windows/DynamicLibrary.inc"
  35. #else
  36. #if HAVE_DLFCN_H
  37. #include <dlfcn.h>
  38. using namespace llvm;
  39. using namespace llvm::sys;
  40. //===----------------------------------------------------------------------===//
  41. //=== WARNING: Implementation here must contain only TRULY operating system
  42. //=== independent code.
  43. //===----------------------------------------------------------------------===//
  44. static DenseSet<void *> *OpenedHandles = nullptr;
  45. DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
  46. std::string *errMsg) {
  47. SmartScopedLock<true> lock(*SymbolsMutex);
  48. void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL);
  49. if (!handle) {
  50. if (errMsg) *errMsg = dlerror();
  51. return DynamicLibrary();
  52. }
  53. #ifdef __CYGWIN__
  54. // Cygwin searches symbols only in the main
  55. // with the handle of dlopen(NULL, RTLD_GLOBAL).
  56. if (!filename)
  57. handle = RTLD_DEFAULT;
  58. #endif
  59. if (!OpenedHandles)
  60. OpenedHandles = new DenseSet<void *>();
  61. // If we've already loaded this library, dlclose() the handle in order to
  62. // keep the internal refcount at +1.
  63. if (!OpenedHandles->insert(handle).second)
  64. dlclose(handle);
  65. return DynamicLibrary(handle);
  66. }
  67. void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
  68. if (!isValid())
  69. return nullptr;
  70. return dlsym(Data, symbolName);
  71. }
  72. #else
  73. using namespace llvm;
  74. using namespace llvm::sys;
  75. DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
  76. std::string *errMsg) {
  77. if (errMsg) *errMsg = "dlopen() not supported on this platform";
  78. return DynamicLibrary();
  79. }
  80. void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
  81. return NULL;
  82. }
  83. #endif
  84. namespace llvm {
  85. void *SearchForAddressOfSpecialSymbol(const char* symbolName);
  86. }
  87. void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) {
  88. SmartScopedLock<true> Lock(*SymbolsMutex);
  89. // First check symbols added via AddSymbol().
  90. if (ExplicitSymbols.isConstructed()) {
  91. StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
  92. if (i != ExplicitSymbols->end())
  93. return i->second;
  94. }
  95. #if HAVE_DLFCN_H
  96. // Now search the libraries.
  97. if (OpenedHandles) {
  98. for (DenseSet<void *>::iterator I = OpenedHandles->begin(),
  99. E = OpenedHandles->end(); I != E; ++I) {
  100. //lt_ptr ptr = lt_dlsym(*I, symbolName);
  101. void *ptr = dlsym(*I, symbolName);
  102. if (ptr) {
  103. return ptr;
  104. }
  105. }
  106. }
  107. #endif
  108. if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName))
  109. return Result;
  110. // This macro returns the address of a well-known, explicit symbol
  111. #define EXPLICIT_SYMBOL(SYM) \
  112. if (!strcmp(symbolName, #SYM)) \
  113. return (void *)&SYM
  114. // On linux we have a weird situation. The stderr/out/in symbols are both
  115. // macros and global variables because of standards requirements. So, we
  116. // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
  117. #if defined(__linux__) and !defined(__ANDROID__)
  118. {
  119. EXPLICIT_SYMBOL(stderr);
  120. EXPLICIT_SYMBOL(stdout);
  121. EXPLICIT_SYMBOL(stdin);
  122. }
  123. #else
  124. // For everything else, we want to check to make sure the symbol isn't defined
  125. // as a macro before using EXPLICIT_SYMBOL.
  126. {
  127. #ifndef stdin
  128. EXPLICIT_SYMBOL(stdin);
  129. #endif
  130. #ifndef stdout
  131. EXPLICIT_SYMBOL(stdout);
  132. #endif
  133. #ifndef stderr
  134. EXPLICIT_SYMBOL(stderr);
  135. #endif
  136. }
  137. #endif
  138. #undef EXPLICIT_SYMBOL
  139. return nullptr;
  140. }
  141. #endif // LLVM_ON_WIN32
  142. //===----------------------------------------------------------------------===//
  143. // C API.
  144. //===----------------------------------------------------------------------===//
  145. LLVMBool LLVMLoadLibraryPermanently(const char* Filename) {
  146. return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename);
  147. }
  148. void *LLVMSearchForAddressOfSymbol(const char *symbolName) {
  149. return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  150. }
  151. void LLVMAddSymbol(const char *symbolName, void *symbolValue) {
  152. return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue);
  153. }