1447762daSMichael J. Spencer //===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===// 2447762daSMichael J. Spencer // 3447762daSMichael J. Spencer // The LLVM Compiler Infrastructure 4447762daSMichael J. Spencer // 5447762daSMichael J. Spencer // This file is distributed under the University of Illinois Open Source 6447762daSMichael J. Spencer // License. See LICENSE.TXT for details. 7447762daSMichael J. Spencer // 8447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 9447762daSMichael J. Spencer // 10447762daSMichael J. Spencer // This header file implements the operating system DynamicLibrary concept. 11447762daSMichael J. Spencer // 12*a19917daSJordy Rose // FIXME: This file leaks ExplicitSymbols and OpenedHandles! 13447762daSMichael J. Spencer // 14447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 15447762daSMichael J. Spencer 16*a19917daSJordy Rose #include "llvm/ADT/StringMap.h" 17*a19917daSJordy Rose #include "llvm/ADT/DenseSet.h" 18447762daSMichael J. Spencer #include "llvm/Support/DynamicLibrary.h" 19447762daSMichael J. Spencer #include "llvm/Support/Mutex.h" 20447762daSMichael J. Spencer #include "llvm/Config/config.h" 21447762daSMichael J. Spencer #include <cstdio> 22447762daSMichael J. Spencer #include <cstring> 23447762daSMichael J. Spencer 24447762daSMichael J. Spencer // Collection of symbol name/value pairs to be searched prior to any libraries. 25*a19917daSJordy Rose static llvm::StringMap<void *> *ExplicitSymbols = 0; 26447762daSMichael J. Spencer 27447762daSMichael J. Spencer namespace { 28447762daSMichael J. Spencer 29447762daSMichael J. Spencer struct ExplicitSymbolsDeleter { 30447762daSMichael J. Spencer ~ExplicitSymbolsDeleter() { 31447762daSMichael J. Spencer delete ExplicitSymbols; 32447762daSMichael J. Spencer } 33447762daSMichael J. Spencer }; 34447762daSMichael J. Spencer 35447762daSMichael J. Spencer } 36447762daSMichael J. Spencer 37447762daSMichael J. Spencer static ExplicitSymbolsDeleter Dummy; 38447762daSMichael J. Spencer 39*a19917daSJordy Rose 40*a19917daSJordy Rose static llvm::sys::SmartMutex<true>& getMutex() { 41*a19917daSJordy Rose static llvm::sys::SmartMutex<true> HandlesMutex; 42*a19917daSJordy Rose return HandlesMutex; 43*a19917daSJordy Rose } 44*a19917daSJordy Rose 45*a19917daSJordy Rose void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName, 46447762daSMichael J. Spencer void *symbolValue) { 47*a19917daSJordy Rose SmartScopedLock<true> lock(getMutex()); 48447762daSMichael J. Spencer if (ExplicitSymbols == 0) 49*a19917daSJordy Rose ExplicitSymbols = new llvm::StringMap<void*>(); 50447762daSMichael J. Spencer (*ExplicitSymbols)[symbolName] = symbolValue; 51447762daSMichael J. Spencer } 52447762daSMichael J. Spencer 53447762daSMichael J. Spencer #ifdef LLVM_ON_WIN32 54447762daSMichael J. Spencer 55447762daSMichael J. Spencer #include "Windows/DynamicLibrary.inc" 56447762daSMichael J. Spencer 57447762daSMichael J. Spencer #else 58447762daSMichael J. Spencer 59447762daSMichael J. Spencer #if HAVE_DLFCN_H 60447762daSMichael J. Spencer #include <dlfcn.h> 61447762daSMichael J. Spencer using namespace llvm; 62447762daSMichael J. Spencer using namespace llvm::sys; 63447762daSMichael J. Spencer 64447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 65447762daSMichael J. Spencer //=== WARNING: Implementation here must contain only TRULY operating system 66447762daSMichael J. Spencer //=== independent code. 67447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 68447762daSMichael J. Spencer 69*a19917daSJordy Rose static DenseSet<void *> *OpenedHandles = 0; 70447762daSMichael J. Spencer 71*a19917daSJordy Rose DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 72*a19917daSJordy Rose std::string *errMsg) { 73*a19917daSJordy Rose void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL); 74*a19917daSJordy Rose if (handle == 0) { 75*a19917daSJordy Rose if (errMsg) *errMsg = dlerror(); 76*a19917daSJordy Rose return DynamicLibrary(); 77447762daSMichael J. Spencer } 78447762daSMichael J. Spencer 79447762daSMichael J. Spencer #ifdef __CYGWIN__ 80447762daSMichael J. Spencer // Cygwin searches symbols only in the main 81447762daSMichael J. Spencer // with the handle of dlopen(NULL, RTLD_GLOBAL). 82*a19917daSJordy Rose if (filename == NULL) 83*a19917daSJordy Rose handle = RTLD_DEFAULT; 84447762daSMichael J. Spencer #endif 85*a19917daSJordy Rose 86*a19917daSJordy Rose SmartScopedLock<true> lock(getMutex()); 87447762daSMichael J. Spencer if (OpenedHandles == 0) 88*a19917daSJordy Rose OpenedHandles = new DenseSet<void *>(); 89*a19917daSJordy Rose 90*a19917daSJordy Rose // If we've already loaded this library, dlclose() the handle in order to 91*a19917daSJordy Rose // keep the internal refcount at +1. 92*a19917daSJordy Rose if (!OpenedHandles->insert(handle).second) 93*a19917daSJordy Rose dlclose(handle); 94*a19917daSJordy Rose 95*a19917daSJordy Rose return DynamicLibrary(handle); 96447762daSMichael J. Spencer } 97*a19917daSJordy Rose 98*a19917daSJordy Rose void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 99*a19917daSJordy Rose if (!isValid()) 100*a19917daSJordy Rose return NULL; 101*a19917daSJordy Rose return dlsym(Data, symbolName); 102*a19917daSJordy Rose } 103*a19917daSJordy Rose 104447762daSMichael J. Spencer #else 105447762daSMichael J. Spencer 106447762daSMichael J. Spencer using namespace llvm; 107447762daSMichael J. Spencer using namespace llvm::sys; 108447762daSMichael J. Spencer 109*a19917daSJordy Rose DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 110*a19917daSJordy Rose std::string *errMsg) { 111*a19917daSJordy Rose if (errMsg) *errMsg = "dlopen() not supported on this platform"; 112*a19917daSJordy Rose return DynamicLibrary(); 113447762daSMichael J. Spencer } 114*a19917daSJordy Rose 115*a19917daSJordy Rose void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 116*a19917daSJordy Rose return NULL; 117*a19917daSJordy Rose } 118*a19917daSJordy Rose 119447762daSMichael J. Spencer #endif 120447762daSMichael J. Spencer 121447762daSMichael J. Spencer namespace llvm { 122447762daSMichael J. Spencer void *SearchForAddressOfSpecialSymbol(const char* symbolName); 123447762daSMichael J. Spencer } 124447762daSMichael J. Spencer 125447762daSMichael J. Spencer void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { 126*a19917daSJordy Rose SmartScopedLock<true> Lock(getMutex()); 127*a19917daSJordy Rose 128447762daSMichael J. Spencer // First check symbols added via AddSymbol(). 129447762daSMichael J. Spencer if (ExplicitSymbols) { 130*a19917daSJordy Rose StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName); 131447762daSMichael J. Spencer 132*a19917daSJordy Rose if (i != ExplicitSymbols->end()) 133*a19917daSJordy Rose return i->second; 134447762daSMichael J. Spencer } 135447762daSMichael J. Spencer 136447762daSMichael J. Spencer #if HAVE_DLFCN_H 137447762daSMichael J. Spencer // Now search the libraries. 138447762daSMichael J. Spencer if (OpenedHandles) { 139*a19917daSJordy Rose for (DenseSet<void *>::iterator I = OpenedHandles->begin(), 140447762daSMichael J. Spencer E = OpenedHandles->end(); I != E; ++I) { 141447762daSMichael J. Spencer //lt_ptr ptr = lt_dlsym(*I, symbolName); 142447762daSMichael J. Spencer void *ptr = dlsym(*I, symbolName); 143447762daSMichael J. Spencer if (ptr) { 144447762daSMichael J. Spencer return ptr; 145447762daSMichael J. Spencer } 146447762daSMichael J. Spencer } 147447762daSMichael J. Spencer } 148447762daSMichael J. Spencer #endif 149447762daSMichael J. Spencer 150447762daSMichael J. Spencer if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) 151447762daSMichael J. Spencer return Result; 152447762daSMichael J. Spencer 153447762daSMichael J. Spencer // This macro returns the address of a well-known, explicit symbol 154447762daSMichael J. Spencer #define EXPLICIT_SYMBOL(SYM) \ 155447762daSMichael J. Spencer if (!strcmp(symbolName, #SYM)) return &SYM 156447762daSMichael J. Spencer 157447762daSMichael J. Spencer // On linux we have a weird situation. The stderr/out/in symbols are both 158447762daSMichael J. Spencer // macros and global variables because of standards requirements. So, we 159447762daSMichael J. Spencer // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 160447762daSMichael J. Spencer #if defined(__linux__) 161447762daSMichael J. Spencer { 162447762daSMichael J. Spencer EXPLICIT_SYMBOL(stderr); 163447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdout); 164447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdin); 165447762daSMichael J. Spencer } 166447762daSMichael J. Spencer #else 167447762daSMichael J. Spencer // For everything else, we want to check to make sure the symbol isn't defined 168447762daSMichael J. Spencer // as a macro before using EXPLICIT_SYMBOL. 169447762daSMichael J. Spencer { 170447762daSMichael J. Spencer #ifndef stdin 171447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdin); 172447762daSMichael J. Spencer #endif 173447762daSMichael J. Spencer #ifndef stdout 174447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdout); 175447762daSMichael J. Spencer #endif 176447762daSMichael J. Spencer #ifndef stderr 177447762daSMichael J. Spencer EXPLICIT_SYMBOL(stderr); 178447762daSMichael J. Spencer #endif 179447762daSMichael J. Spencer } 180447762daSMichael J. Spencer #endif 181447762daSMichael J. Spencer #undef EXPLICIT_SYMBOL 182447762daSMichael J. Spencer 183447762daSMichael J. Spencer return 0; 184447762daSMichael J. Spencer } 185447762daSMichael J. Spencer 186447762daSMichael J. Spencer #endif // LLVM_ON_WIN32 187