DynamicLibrary.inc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. //===- Unix/DynamicLibrary.cpp - Unix DL Implementation ---------*- 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 provides the UNIX specific implementation of DynamicLibrary.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
  13. #include <dlfcn.h>
  14. DynamicLibrary::HandleSet::~HandleSet() {
  15. // Close the libraries in reverse order.
  16. for (void *Handle : llvm::reverse(Handles))
  17. ::dlclose(Handle);
  18. if (Process)
  19. ::dlclose(Process);
  20. // llvm_shutdown called, Return to default
  21. DynamicLibrary::SearchOrder = DynamicLibrary::SO_Linker;
  22. }
  23. void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
  24. void *Handle = ::dlopen(File, RTLD_LAZY | RTLD_GLOBAL);
  25. if (!Handle) {
  26. if (Err)
  27. *Err = ::dlerror();
  28. return &DynamicLibrary::Invalid;
  29. }
  30. #ifdef __CYGWIN__
  31. // Cygwin searches symbols only in the main
  32. // with the handle of dlopen(NULL, RTLD_GLOBAL).
  33. if (!File)
  34. Handle = RTLD_DEFAULT;
  35. #endif
  36. return Handle;
  37. }
  38. void DynamicLibrary::HandleSet::DLClose(void *Handle) { ::dlclose(Handle); }
  39. void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
  40. return ::dlsym(Handle, Symbol);
  41. }
  42. #else // !HAVE_DLOPEN
  43. DynamicLibrary::HandleSet::~HandleSet() {}
  44. void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
  45. if (Err)
  46. *Err = "dlopen() not supported on this platform";
  47. return &Invalid;
  48. }
  49. void DynamicLibrary::HandleSet::DLClose(void *Handle) {}
  50. void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
  51. return nullptr;
  52. }
  53. #endif
  54. // Must declare the symbols in the global namespace.
  55. static void *DoSearch(const char *SymbolName) {
  56. #define EXPLICIT_SYMBOL(SYM) \
  57. extern void *SYM; \
  58. if (!strcmp(SymbolName, #SYM)) \
  59. return (void *)&SYM
  60. // If this is darwin, it has some funky issues, try to solve them here. Some
  61. // important symbols are marked 'private external' which doesn't allow
  62. // SearchForAddressOfSymbol to find them. As such, we special case them here,
  63. // there is only a small handful of them.
  64. #ifdef __APPLE__
  65. {
  66. // __eprintf is sometimes used for assert() handling on x86.
  67. //
  68. // FIXME: Currently disabled when using Clang, as we don't always have our
  69. // runtime support libraries available.
  70. #ifndef __clang__
  71. #ifdef __i386__
  72. EXPLICIT_SYMBOL(__eprintf);
  73. #endif
  74. #endif
  75. }
  76. #endif
  77. #ifdef __CYGWIN__
  78. {
  79. EXPLICIT_SYMBOL(_alloca);
  80. EXPLICIT_SYMBOL(__main);
  81. }
  82. #endif
  83. #undef EXPLICIT_SYMBOL
  84. // This macro returns the address of a well-known, explicit symbol
  85. #define EXPLICIT_SYMBOL(SYM) \
  86. if (!strcmp(SymbolName, #SYM)) \
  87. return &SYM
  88. // Under glibc we have a weird situation. The stderr/out/in symbols are both
  89. // macros and global variables because of standards requirements. So, we
  90. // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
  91. #if defined(__GLIBC__)
  92. {
  93. EXPLICIT_SYMBOL(stderr);
  94. EXPLICIT_SYMBOL(stdout);
  95. EXPLICIT_SYMBOL(stdin);
  96. }
  97. #else
  98. // For everything else, we want to check to make sure the symbol isn't defined
  99. // as a macro before using EXPLICIT_SYMBOL.
  100. {
  101. #ifndef stdin
  102. EXPLICIT_SYMBOL(stdin);
  103. #endif
  104. #ifndef stdout
  105. EXPLICIT_SYMBOL(stdout);
  106. #endif
  107. #ifndef stderr
  108. EXPLICIT_SYMBOL(stderr);
  109. #endif
  110. }
  111. #endif
  112. #undef EXPLICIT_SYMBOL
  113. return nullptr;
  114. }