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