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// 12226890Sdim// FIXME: This file leaks ExplicitSymbols and OpenedHandles! 13218885Sdim// 14218885Sdim//===----------------------------------------------------------------------===// 15218885Sdim 16252723Sdim#include "llvm/Support/DynamicLibrary.h" 17263509Sdim#include "llvm/Support/ManagedStatic.h" 18252723Sdim#include "llvm/ADT/DenseSet.h" 19226890Sdim#include "llvm/ADT/StringMap.h" 20252723Sdim#include "llvm/Config/config.h" 21218885Sdim#include "llvm/Support/Mutex.h" 22263509Sdim#include "llvm-c/Support.h" 23218885Sdim#include <cstdio> 24218885Sdim#include <cstring> 25218885Sdim 26218885Sdim// Collection of symbol name/value pairs to be searched prior to any libraries. 27263509Sdimstatic llvm::ManagedStatic<llvm::StringMap<void *> > ExplicitSymbols; 28263509Sdimstatic llvm::ManagedStatic<llvm::sys::SmartMutex<true> > SymbolsMutex; 29218885Sdim 30226890Sdimvoid llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName, 31218885Sdim void *symbolValue) { 32263509Sdim SmartScopedLock<true> lock(*SymbolsMutex); 33218885Sdim (*ExplicitSymbols)[symbolName] = symbolValue; 34218885Sdim} 35218885Sdim 36226890Sdimchar llvm::sys::DynamicLibrary::Invalid = 0; 37226890Sdim 38218885Sdim#ifdef LLVM_ON_WIN32 39218885Sdim 40218885Sdim#include "Windows/DynamicLibrary.inc" 41218885Sdim 42218885Sdim#else 43218885Sdim 44218885Sdim#if HAVE_DLFCN_H 45218885Sdim#include <dlfcn.h> 46218885Sdimusing namespace llvm; 47218885Sdimusing namespace llvm::sys; 48218885Sdim 49218885Sdim//===----------------------------------------------------------------------===// 50218885Sdim//=== WARNING: Implementation here must contain only TRULY operating system 51218885Sdim//=== independent code. 52218885Sdim//===----------------------------------------------------------------------===// 53218885Sdim 54226890Sdimstatic DenseSet<void *> *OpenedHandles = 0; 55218885Sdim 56226890SdimDynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 57226890Sdim std::string *errMsg) { 58263509Sdim SmartScopedLock<true> lock(*SymbolsMutex); 59218885Sdim 60226890Sdim void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL); 61226890Sdim if (handle == 0) { 62226890Sdim if (errMsg) *errMsg = dlerror(); 63226890Sdim return DynamicLibrary(); 64226890Sdim } 65218885Sdim 66218885Sdim#ifdef __CYGWIN__ 67218885Sdim // Cygwin searches symbols only in the main 68218885Sdim // with the handle of dlopen(NULL, RTLD_GLOBAL). 69226890Sdim if (filename == NULL) 70226890Sdim handle = RTLD_DEFAULT; 71218885Sdim#endif 72226890Sdim 73218885Sdim if (OpenedHandles == 0) 74226890Sdim OpenedHandles = new DenseSet<void *>(); 75226890Sdim 76226890Sdim // If we've already loaded this library, dlclose() the handle in order to 77226890Sdim // keep the internal refcount at +1. 78226890Sdim if (!OpenedHandles->insert(handle).second) 79226890Sdim dlclose(handle); 80226890Sdim 81226890Sdim return DynamicLibrary(handle); 82218885Sdim} 83226890Sdim 84226890Sdimvoid *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 85226890Sdim if (!isValid()) 86226890Sdim return NULL; 87226890Sdim return dlsym(Data, symbolName); 88226890Sdim} 89226890Sdim 90218885Sdim#else 91218885Sdim 92218885Sdimusing namespace llvm; 93218885Sdimusing namespace llvm::sys; 94218885Sdim 95226890SdimDynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 96226890Sdim std::string *errMsg) { 97226890Sdim if (errMsg) *errMsg = "dlopen() not supported on this platform"; 98226890Sdim return DynamicLibrary(); 99218885Sdim} 100226890Sdim 101226890Sdimvoid *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 102226890Sdim return NULL; 103226890Sdim} 104226890Sdim 105218885Sdim#endif 106218885Sdim 107218885Sdimnamespace llvm { 108218885Sdimvoid *SearchForAddressOfSpecialSymbol(const char* symbolName); 109218885Sdim} 110218885Sdim 111226890Sdimvoid* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { 112263509Sdim SmartScopedLock<true> Lock(*SymbolsMutex); 113226890Sdim 114218885Sdim // First check symbols added via AddSymbol(). 115263509Sdim if (ExplicitSymbols.isConstructed()) { 116226890Sdim StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName); 117218885Sdim 118226890Sdim if (i != ExplicitSymbols->end()) 119226890Sdim return i->second; 120218885Sdim } 121218885Sdim 122218885Sdim#if HAVE_DLFCN_H 123218885Sdim // Now search the libraries. 124218885Sdim if (OpenedHandles) { 125226890Sdim for (DenseSet<void *>::iterator I = OpenedHandles->begin(), 126218885Sdim E = OpenedHandles->end(); I != E; ++I) { 127218885Sdim //lt_ptr ptr = lt_dlsym(*I, symbolName); 128218885Sdim void *ptr = dlsym(*I, symbolName); 129218885Sdim if (ptr) { 130218885Sdim return ptr; 131218885Sdim } 132218885Sdim } 133218885Sdim } 134218885Sdim#endif 135218885Sdim 136218885Sdim if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) 137218885Sdim return Result; 138218885Sdim 139218885Sdim// This macro returns the address of a well-known, explicit symbol 140218885Sdim#define EXPLICIT_SYMBOL(SYM) \ 141218885Sdim if (!strcmp(symbolName, #SYM)) return &SYM 142218885Sdim 143218885Sdim// On linux we have a weird situation. The stderr/out/in symbols are both 144218885Sdim// macros and global variables because of standards requirements. So, we 145218885Sdim// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 146245431Sdim#if defined(__linux__) and !defined(__ANDROID__) 147218885Sdim { 148218885Sdim EXPLICIT_SYMBOL(stderr); 149218885Sdim EXPLICIT_SYMBOL(stdout); 150218885Sdim EXPLICIT_SYMBOL(stdin); 151218885Sdim } 152218885Sdim#else 153218885Sdim // For everything else, we want to check to make sure the symbol isn't defined 154218885Sdim // as a macro before using EXPLICIT_SYMBOL. 155218885Sdim { 156218885Sdim#ifndef stdin 157218885Sdim EXPLICIT_SYMBOL(stdin); 158218885Sdim#endif 159218885Sdim#ifndef stdout 160218885Sdim EXPLICIT_SYMBOL(stdout); 161218885Sdim#endif 162218885Sdim#ifndef stderr 163218885Sdim EXPLICIT_SYMBOL(stderr); 164218885Sdim#endif 165218885Sdim } 166218885Sdim#endif 167218885Sdim#undef EXPLICIT_SYMBOL 168218885Sdim 169218885Sdim return 0; 170218885Sdim} 171218885Sdim 172218885Sdim#endif // LLVM_ON_WIN32 173263509Sdim 174263509Sdim//===----------------------------------------------------------------------===// 175263509Sdim// C API. 176263509Sdim//===----------------------------------------------------------------------===// 177263509Sdim 178263509SdimLLVMBool LLVMLoadLibraryPermanently(const char* Filename) { 179263509Sdim return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename); 180263509Sdim} 181