10b57cec5SDimitry Andric//===- Unix/DynamicLibrary.cpp - Unix DL Implementation ---------*- C++ -*-===// 20b57cec5SDimitry Andric// 30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric// 70b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric// 90b57cec5SDimitry Andric// This file provides the UNIX specific implementation of DynamicLibrary. 100b57cec5SDimitry Andric// 110b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric#if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN) 140b57cec5SDimitry Andric#include <dlfcn.h> 150b57cec5SDimitry Andric 160b57cec5SDimitry AndricDynamicLibrary::HandleSet::~HandleSet() { 170b57cec5SDimitry Andric // Close the libraries in reverse order. 180b57cec5SDimitry Andric for (void *Handle : llvm::reverse(Handles)) 190b57cec5SDimitry Andric ::dlclose(Handle); 200b57cec5SDimitry Andric if (Process) 210b57cec5SDimitry Andric ::dlclose(Process); 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric // llvm_shutdown called, Return to default 240b57cec5SDimitry Andric DynamicLibrary::SearchOrder = DynamicLibrary::SO_Linker; 250b57cec5SDimitry Andric} 260b57cec5SDimitry Andric 270b57cec5SDimitry Andricvoid *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) { 280b57cec5SDimitry Andric void *Handle = ::dlopen(File, RTLD_LAZY | RTLD_GLOBAL); 290b57cec5SDimitry Andric if (!Handle) { 30*bdd1243dSDimitry Andric if (Err) 31*bdd1243dSDimitry Andric *Err = ::dlerror(); 320b57cec5SDimitry Andric return &DynamicLibrary::Invalid; 330b57cec5SDimitry Andric } 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric#ifdef __CYGWIN__ 360b57cec5SDimitry Andric // Cygwin searches symbols only in the main 370b57cec5SDimitry Andric // with the handle of dlopen(NULL, RTLD_GLOBAL). 380b57cec5SDimitry Andric if (!File) 390b57cec5SDimitry Andric Handle = RTLD_DEFAULT; 400b57cec5SDimitry Andric#endif 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric return Handle; 430b57cec5SDimitry Andric} 440b57cec5SDimitry Andric 45*bdd1243dSDimitry Andricvoid DynamicLibrary::HandleSet::DLClose(void *Handle) { ::dlclose(Handle); } 460b57cec5SDimitry Andric 470b57cec5SDimitry Andricvoid *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) { 480b57cec5SDimitry Andric return ::dlsym(Handle, Symbol); 490b57cec5SDimitry Andric} 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric#else // !HAVE_DLOPEN 520b57cec5SDimitry Andric 530b57cec5SDimitry AndricDynamicLibrary::HandleSet::~HandleSet() {} 540b57cec5SDimitry Andric 550b57cec5SDimitry Andricvoid *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) { 56*bdd1243dSDimitry Andric if (Err) 57*bdd1243dSDimitry Andric *Err = "dlopen() not supported on this platform"; 580b57cec5SDimitry Andric return &Invalid; 590b57cec5SDimitry Andric} 600b57cec5SDimitry Andric 61*bdd1243dSDimitry Andricvoid DynamicLibrary::HandleSet::DLClose(void *Handle) {} 620b57cec5SDimitry Andric 630b57cec5SDimitry Andricvoid *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) { 640b57cec5SDimitry Andric return nullptr; 650b57cec5SDimitry Andric} 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric#endif 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric// Must declare the symbols in the global namespace. 700b57cec5SDimitry Andricstatic void *DoSearch(const char *SymbolName) { 710b57cec5SDimitry Andric#define EXPLICIT_SYMBOL(SYM) \ 72*bdd1243dSDimitry Andric extern void *SYM; \ 73*bdd1243dSDimitry Andric if (!strcmp(SymbolName, #SYM)) \ 74*bdd1243dSDimitry Andric return (void *)&SYM 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric // If this is darwin, it has some funky issues, try to solve them here. Some 770b57cec5SDimitry Andric // important symbols are marked 'private external' which doesn't allow 780b57cec5SDimitry Andric // SearchForAddressOfSymbol to find them. As such, we special case them here, 790b57cec5SDimitry Andric // there is only a small handful of them. 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric#ifdef __APPLE__ 820b57cec5SDimitry Andric { 830b57cec5SDimitry Andric // __eprintf is sometimes used for assert() handling on x86. 840b57cec5SDimitry Andric // 850b57cec5SDimitry Andric // FIXME: Currently disabled when using Clang, as we don't always have our 860b57cec5SDimitry Andric // runtime support libraries available. 870b57cec5SDimitry Andric#ifndef __clang__ 880b57cec5SDimitry Andric#ifdef __i386__ 890b57cec5SDimitry Andric EXPLICIT_SYMBOL(__eprintf); 900b57cec5SDimitry Andric#endif 910b57cec5SDimitry Andric#endif 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric#endif 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric#ifdef __CYGWIN__ 960b57cec5SDimitry Andric { 970b57cec5SDimitry Andric EXPLICIT_SYMBOL(_alloca); 980b57cec5SDimitry Andric EXPLICIT_SYMBOL(__main); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric#endif 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric#undef EXPLICIT_SYMBOL 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric// This macro returns the address of a well-known, explicit symbol 1050b57cec5SDimitry Andric#define EXPLICIT_SYMBOL(SYM) \ 106*bdd1243dSDimitry Andric if (!strcmp(SymbolName, #SYM)) \ 107*bdd1243dSDimitry Andric return &SYM 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric// Under glibc we have a weird situation. The stderr/out/in symbols are both 1100b57cec5SDimitry Andric// macros and global variables because of standards requirements. So, we 1110b57cec5SDimitry Andric// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 1120b57cec5SDimitry Andric#if defined(__GLIBC__) 1130b57cec5SDimitry Andric { 1140b57cec5SDimitry Andric EXPLICIT_SYMBOL(stderr); 1150b57cec5SDimitry Andric EXPLICIT_SYMBOL(stdout); 1160b57cec5SDimitry Andric EXPLICIT_SYMBOL(stdin); 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric#else 1190b57cec5SDimitry Andric // For everything else, we want to check to make sure the symbol isn't defined 1200b57cec5SDimitry Andric // as a macro before using EXPLICIT_SYMBOL. 1210b57cec5SDimitry Andric { 1220b57cec5SDimitry Andric#ifndef stdin 1230b57cec5SDimitry Andric EXPLICIT_SYMBOL(stdin); 1240b57cec5SDimitry Andric#endif 1250b57cec5SDimitry Andric#ifndef stdout 1260b57cec5SDimitry Andric EXPLICIT_SYMBOL(stdout); 1270b57cec5SDimitry Andric#endif 1280b57cec5SDimitry Andric#ifndef stderr 1290b57cec5SDimitry Andric EXPLICIT_SYMBOL(stderr); 1300b57cec5SDimitry Andric#endif 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric#endif 1330b57cec5SDimitry Andric#undef EXPLICIT_SYMBOL 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric return nullptr; 1360b57cec5SDimitry Andric} 137