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