DynamicLibrary.inc revision 320970
1317683Sdim//===- Unix/DynamicLibrary.cpp - Unix DL Implementation ---------*- C++ -*-===//
2317683Sdim//
3317683Sdim//                     The LLVM Compiler Infrastructure
4317683Sdim//
5317683Sdim// This file is distributed under the University of Illinois Open Source
6317683Sdim// License. See LICENSE.TXT for details.
7317683Sdim//
8317683Sdim//===----------------------------------------------------------------------===//
9317683Sdim//
10317683Sdim// This file provides the UNIX specific implementation of DynamicLibrary.
11317683Sdim//
12317683Sdim//===----------------------------------------------------------------------===//
13317683Sdim
14317683Sdim#if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)
15317683Sdim#include <dlfcn.h>
16317683Sdim
17317683SdimDynamicLibrary::HandleSet::~HandleSet() {
18319799Sdim  // Close the libraries in reverse order.
19319799Sdim  for (void *Handle : llvm::reverse(Handles))
20317683Sdim    ::dlclose(Handle);
21317683Sdim  if (Process)
22317683Sdim    ::dlclose(Process);
23320970Sdim
24320970Sdim  // llvm_shutdown called, Return to default
25320970Sdim  DynamicLibrary::SearchOrder = DynamicLibrary::SO_Linker;
26317683Sdim}
27317683Sdim
28317683Sdimvoid *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
29317683Sdim  void *Handle = ::dlopen(File, RTLD_LAZY|RTLD_GLOBAL);
30317683Sdim  if (!Handle) {
31317683Sdim    if (Err) *Err = ::dlerror();
32317683Sdim    return &DynamicLibrary::Invalid;
33317683Sdim  }
34317683Sdim
35317683Sdim#ifdef __CYGWIN__
36317683Sdim  // Cygwin searches symbols only in the main
37317683Sdim  // with the handle of dlopen(NULL, RTLD_GLOBAL).
38317969Sdim  if (!File)
39317683Sdim    Handle = RTLD_DEFAULT;
40317683Sdim#endif
41317683Sdim
42317683Sdim  return Handle;
43317683Sdim}
44317683Sdim
45317683Sdimvoid DynamicLibrary::HandleSet::DLClose(void *Handle) {
46317683Sdim  ::dlclose(Handle);
47317683Sdim}
48317683Sdim
49317683Sdimvoid *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
50317683Sdim  return ::dlsym(Handle, Symbol);
51317683Sdim}
52317683Sdim
53317683Sdim#else // !HAVE_DLOPEN
54317683Sdim
55317683SdimDynamicLibrary::HandleSet::~HandleSet() {}
56317683Sdim
57317683Sdimvoid *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
58317683Sdim  if (Err) *Err = "dlopen() not supported on this platform";
59317683Sdim  return &Invalid;
60317683Sdim}
61317683Sdim
62317683Sdimvoid DynamicLibrary::HandleSet::DLClose(void *Handle) {
63317683Sdim}
64317683Sdim
65317683Sdimvoid *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
66317683Sdim  return nullptr;
67317683Sdim}
68317683Sdim
69317683Sdim#endif
70317683Sdim
71317683Sdim// Must declare the symbols in the global namespace.
72317683Sdimstatic void *DoSearch(const char* SymbolName) {
73317683Sdim#define EXPLICIT_SYMBOL(SYM) \
74317683Sdim   extern void *SYM; if (!strcmp(SymbolName, #SYM)) return &SYM
75317683Sdim
76317683Sdim  // If this is darwin, it has some funky issues, try to solve them here.  Some
77317683Sdim  // important symbols are marked 'private external' which doesn't allow
78317683Sdim  // SearchForAddressOfSymbol to find them.  As such, we special case them here,
79317683Sdim  // there is only a small handful of them.
80317683Sdim
81317683Sdim#ifdef __APPLE__
82317683Sdim  {
83317683Sdim    // __eprintf is sometimes used for assert() handling on x86.
84317683Sdim    //
85317683Sdim    // FIXME: Currently disabled when using Clang, as we don't always have our
86317683Sdim    // runtime support libraries available.
87317683Sdim#ifndef __clang__
88317683Sdim#ifdef __i386__
89317683Sdim    EXPLICIT_SYMBOL(__eprintf);
90317683Sdim#endif
91317683Sdim#endif
92317683Sdim  }
93317683Sdim#endif
94317683Sdim
95317683Sdim#ifdef __CYGWIN__
96317683Sdim  {
97317683Sdim    EXPLICIT_SYMBOL(_alloca);
98317683Sdim    EXPLICIT_SYMBOL(__main);
99317683Sdim  }
100317683Sdim#endif
101317683Sdim
102317683Sdim#undef EXPLICIT_SYMBOL
103317683Sdim
104317683Sdim// This macro returns the address of a well-known, explicit symbol
105317683Sdim#define EXPLICIT_SYMBOL(SYM) \
106317683Sdim   if (!strcmp(SymbolName, #SYM)) return &SYM
107317683Sdim
108319799Sdim// Under glibc we have a weird situation. The stderr/out/in symbols are both
109317683Sdim// macros and global variables because of standards requirements. So, we
110317683Sdim// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
111319799Sdim#if defined(__GLIBC__)
112317683Sdim  {
113317683Sdim    EXPLICIT_SYMBOL(stderr);
114317683Sdim    EXPLICIT_SYMBOL(stdout);
115317683Sdim    EXPLICIT_SYMBOL(stdin);
116317683Sdim  }
117317683Sdim#else
118317683Sdim  // For everything else, we want to check to make sure the symbol isn't defined
119317683Sdim  // as a macro before using EXPLICIT_SYMBOL.
120317683Sdim  {
121317683Sdim#ifndef stdin
122317683Sdim    EXPLICIT_SYMBOL(stdin);
123317683Sdim#endif
124317683Sdim#ifndef stdout
125317683Sdim    EXPLICIT_SYMBOL(stdout);
126317683Sdim#endif
127317683Sdim#ifndef stderr
128317683Sdim    EXPLICIT_SYMBOL(stderr);
129317683Sdim#endif
130317683Sdim  }
131317683Sdim#endif
132317683Sdim#undef EXPLICIT_SYMBOL
133317683Sdim
134317683Sdim  return nullptr;
135317683Sdim}
136