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