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