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