1218885Sdim//===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This header file implements the operating system DynamicLibrary concept. 11218885Sdim// 12226633Sdim// FIXME: This file leaks ExplicitSymbols and OpenedHandles! 13218885Sdim// 14218885Sdim//===----------------------------------------------------------------------===// 15218885Sdim 16249423Sdim#include "llvm/Support/DynamicLibrary.h" 17249423Sdim#include "llvm/ADT/DenseSet.h" 18226633Sdim#include "llvm/ADT/StringMap.h" 19249423Sdim#include "llvm/Config/config.h" 20218885Sdim#include "llvm/Support/Mutex.h" 21218885Sdim#include <cstdio> 22218885Sdim#include <cstring> 23218885Sdim 24218885Sdim// Collection of symbol name/value pairs to be searched prior to any libraries. 25226633Sdimstatic llvm::StringMap<void *> *ExplicitSymbols = 0; 26218885Sdim 27218885Sdimnamespace { 28218885Sdim 29218885Sdimstruct ExplicitSymbolsDeleter { 30218885Sdim ~ExplicitSymbolsDeleter() { 31226633Sdim delete ExplicitSymbols; 32218885Sdim } 33218885Sdim}; 34218885Sdim 35218885Sdim} 36218885Sdim 37218885Sdimstatic ExplicitSymbolsDeleter Dummy; 38218885Sdim 39226633Sdim 40226633Sdimstatic llvm::sys::SmartMutex<true>& getMutex() { 41226633Sdim static llvm::sys::SmartMutex<true> HandlesMutex; 42226633Sdim return HandlesMutex; 43226633Sdim} 44226633Sdim 45226633Sdimvoid llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName, 46218885Sdim void *symbolValue) { 47226633Sdim SmartScopedLock<true> lock(getMutex()); 48218885Sdim if (ExplicitSymbols == 0) 49249423Sdim ExplicitSymbols = new StringMap<void*>(); 50218885Sdim (*ExplicitSymbols)[symbolName] = symbolValue; 51218885Sdim} 52218885Sdim 53226633Sdimchar llvm::sys::DynamicLibrary::Invalid = 0; 54226633Sdim 55218885Sdim#ifdef LLVM_ON_WIN32 56218885Sdim 57218885Sdim#include "Windows/DynamicLibrary.inc" 58218885Sdim 59218885Sdim#else 60218885Sdim 61218885Sdim#if HAVE_DLFCN_H 62218885Sdim#include <dlfcn.h> 63218885Sdimusing namespace llvm; 64218885Sdimusing namespace llvm::sys; 65218885Sdim 66218885Sdim//===----------------------------------------------------------------------===// 67218885Sdim//=== WARNING: Implementation here must contain only TRULY operating system 68218885Sdim//=== independent code. 69218885Sdim//===----------------------------------------------------------------------===// 70218885Sdim 71226633Sdimstatic DenseSet<void *> *OpenedHandles = 0; 72218885Sdim 73226633SdimDynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 74226633Sdim std::string *errMsg) { 75226633Sdim SmartScopedLock<true> lock(getMutex()); 76218885Sdim 77226633Sdim void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL); 78226633Sdim if (handle == 0) { 79226633Sdim if (errMsg) *errMsg = dlerror(); 80226633Sdim return DynamicLibrary(); 81226633Sdim } 82218885Sdim 83218885Sdim#ifdef __CYGWIN__ 84218885Sdim // Cygwin searches symbols only in the main 85218885Sdim // with the handle of dlopen(NULL, RTLD_GLOBAL). 86226633Sdim if (filename == NULL) 87226633Sdim handle = RTLD_DEFAULT; 88218885Sdim#endif 89226633Sdim 90218885Sdim if (OpenedHandles == 0) 91226633Sdim OpenedHandles = new DenseSet<void *>(); 92226633Sdim 93226633Sdim // If we've already loaded this library, dlclose() the handle in order to 94226633Sdim // keep the internal refcount at +1. 95226633Sdim if (!OpenedHandles->insert(handle).second) 96226633Sdim dlclose(handle); 97226633Sdim 98226633Sdim return DynamicLibrary(handle); 99218885Sdim} 100226633Sdim 101226633Sdimvoid *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 102226633Sdim if (!isValid()) 103226633Sdim return NULL; 104226633Sdim return dlsym(Data, symbolName); 105226633Sdim} 106226633Sdim 107218885Sdim#else 108218885Sdim 109218885Sdimusing namespace llvm; 110218885Sdimusing namespace llvm::sys; 111218885Sdim 112226633SdimDynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 113226633Sdim std::string *errMsg) { 114226633Sdim if (errMsg) *errMsg = "dlopen() not supported on this platform"; 115226633Sdim return DynamicLibrary(); 116218885Sdim} 117226633Sdim 118226633Sdimvoid *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 119226633Sdim return NULL; 120226633Sdim} 121226633Sdim 122218885Sdim#endif 123218885Sdim 124218885Sdimnamespace llvm { 125218885Sdimvoid *SearchForAddressOfSpecialSymbol(const char* symbolName); 126218885Sdim} 127218885Sdim 128226633Sdimvoid* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { 129226633Sdim SmartScopedLock<true> Lock(getMutex()); 130226633Sdim 131218885Sdim // First check symbols added via AddSymbol(). 132218885Sdim if (ExplicitSymbols) { 133226633Sdim StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName); 134218885Sdim 135226633Sdim if (i != ExplicitSymbols->end()) 136226633Sdim return i->second; 137218885Sdim } 138218885Sdim 139218885Sdim#if HAVE_DLFCN_H 140218885Sdim // Now search the libraries. 141218885Sdim if (OpenedHandles) { 142226633Sdim for (DenseSet<void *>::iterator I = OpenedHandles->begin(), 143218885Sdim E = OpenedHandles->end(); I != E; ++I) { 144218885Sdim //lt_ptr ptr = lt_dlsym(*I, symbolName); 145218885Sdim void *ptr = dlsym(*I, symbolName); 146218885Sdim if (ptr) { 147218885Sdim return ptr; 148218885Sdim } 149218885Sdim } 150218885Sdim } 151218885Sdim#endif 152218885Sdim 153218885Sdim if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) 154218885Sdim return Result; 155218885Sdim 156218885Sdim// This macro returns the address of a well-known, explicit symbol 157218885Sdim#define EXPLICIT_SYMBOL(SYM) \ 158218885Sdim if (!strcmp(symbolName, #SYM)) return &SYM 159218885Sdim 160218885Sdim// On linux we have a weird situation. The stderr/out/in symbols are both 161218885Sdim// macros and global variables because of standards requirements. So, we 162218885Sdim// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 163243830Sdim#if defined(__linux__) and !defined(__ANDROID__) 164218885Sdim { 165218885Sdim EXPLICIT_SYMBOL(stderr); 166218885Sdim EXPLICIT_SYMBOL(stdout); 167218885Sdim EXPLICIT_SYMBOL(stdin); 168218885Sdim } 169218885Sdim#else 170218885Sdim // For everything else, we want to check to make sure the symbol isn't defined 171218885Sdim // as a macro before using EXPLICIT_SYMBOL. 172218885Sdim { 173218885Sdim#ifndef stdin 174218885Sdim EXPLICIT_SYMBOL(stdin); 175218885Sdim#endif 176218885Sdim#ifndef stdout 177218885Sdim EXPLICIT_SYMBOL(stdout); 178218885Sdim#endif 179218885Sdim#ifndef stderr 180218885Sdim EXPLICIT_SYMBOL(stderr); 181218885Sdim#endif 182218885Sdim } 183218885Sdim#endif 184218885Sdim#undef EXPLICIT_SYMBOL 185218885Sdim 186218885Sdim return 0; 187218885Sdim} 188218885Sdim 189218885Sdim#endif // LLVM_ON_WIN32 190