DynamicLibrary.inc revision 319799
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);
23317683Sdim}
24317683Sdim
25317683Sdimvoid *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
26317683Sdim  void *Handle = ::dlopen(File, RTLD_LAZY|RTLD_GLOBAL);
27317683Sdim  if (!Handle) {
28317683Sdim    if (Err) *Err = ::dlerror();
29317683Sdim    return &DynamicLibrary::Invalid;
30317683Sdim  }
31317683Sdim
32317683Sdim#ifdef __CYGWIN__
33317683Sdim  // Cygwin searches symbols only in the main
34317683Sdim  // with the handle of dlopen(NULL, RTLD_GLOBAL).
35317969Sdim  if (!File)
36317683Sdim    Handle = RTLD_DEFAULT;
37317683Sdim#endif
38317683Sdim
39317683Sdim  return Handle;
40317683Sdim}
41317683Sdim
42317683Sdimvoid DynamicLibrary::HandleSet::DLClose(void *Handle) {
43317683Sdim  ::dlclose(Handle);
44317683Sdim}
45317683Sdim
46317683Sdimvoid *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
47317683Sdim  return ::dlsym(Handle, Symbol);
48317683Sdim}
49317683Sdim
50317683Sdim#else // !HAVE_DLOPEN
51317683Sdim
52317683SdimDynamicLibrary::HandleSet::~HandleSet() {}
53317683Sdim
54317683Sdimvoid *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
55317683Sdim  if (Err) *Err = "dlopen() not supported on this platform";
56317683Sdim  return &Invalid;
57317683Sdim}
58317683Sdim
59317683Sdimvoid DynamicLibrary::HandleSet::DLClose(void *Handle) {
60317683Sdim}
61317683Sdim
62317683Sdimvoid *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
63317683Sdim  return nullptr;
64317683Sdim}
65317683Sdim
66317683Sdim#endif
67317683Sdim
68317683Sdim// Must declare the symbols in the global namespace.
69317683Sdimstatic void *DoSearch(const char* SymbolName) {
70317683Sdim#define EXPLICIT_SYMBOL(SYM) \
71317683Sdim   extern void *SYM; if (!strcmp(SymbolName, #SYM)) return &SYM
72317683Sdim
73317683Sdim  // If this is darwin, it has some funky issues, try to solve them here.  Some
74317683Sdim  // important symbols are marked 'private external' which doesn't allow
75317683Sdim  // SearchForAddressOfSymbol to find them.  As such, we special case them here,
76317683Sdim  // there is only a small handful of them.
77317683Sdim
78317683Sdim#ifdef __APPLE__
79317683Sdim  {
80317683Sdim    // __eprintf is sometimes used for assert() handling on x86.
81317683Sdim    //
82317683Sdim    // FIXME: Currently disabled when using Clang, as we don't always have our
83317683Sdim    // runtime support libraries available.
84317683Sdim#ifndef __clang__
85317683Sdim#ifdef __i386__
86317683Sdim    EXPLICIT_SYMBOL(__eprintf);
87317683Sdim#endif
88317683Sdim#endif
89317683Sdim  }
90317683Sdim#endif
91317683Sdim
92317683Sdim#ifdef __CYGWIN__
93317683Sdim  {
94317683Sdim    EXPLICIT_SYMBOL(_alloca);
95317683Sdim    EXPLICIT_SYMBOL(__main);
96317683Sdim  }
97317683Sdim#endif
98317683Sdim
99317683Sdim#undef EXPLICIT_SYMBOL
100317683Sdim
101317683Sdim// This macro returns the address of a well-known, explicit symbol
102317683Sdim#define EXPLICIT_SYMBOL(SYM) \
103317683Sdim   if (!strcmp(SymbolName, #SYM)) return &SYM
104317683Sdim
105319799Sdim// Under glibc we have a weird situation. The stderr/out/in symbols are both
106317683Sdim// macros and global variables because of standards requirements. So, we
107317683Sdim// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
108319799Sdim#if defined(__GLIBC__)
109317683Sdim  {
110317683Sdim    EXPLICIT_SYMBOL(stderr);
111317683Sdim    EXPLICIT_SYMBOL(stdout);
112317683Sdim    EXPLICIT_SYMBOL(stdin);
113317683Sdim  }
114317683Sdim#else
115317683Sdim  // For everything else, we want to check to make sure the symbol isn't defined
116317683Sdim  // as a macro before using EXPLICIT_SYMBOL.
117317683Sdim  {
118317683Sdim#ifndef stdin
119317683Sdim    EXPLICIT_SYMBOL(stdin);
120317683Sdim#endif
121317683Sdim#ifndef stdout
122317683Sdim    EXPLICIT_SYMBOL(stdout);
123317683Sdim#endif
124317683Sdim#ifndef stderr
125317683Sdim    EXPLICIT_SYMBOL(stderr);
126317683Sdim#endif
127317683Sdim  }
128317683Sdim#endif
129317683Sdim#undef EXPLICIT_SYMBOL
130317683Sdim
131317683Sdim  return nullptr;
132317683Sdim}
133