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 // 12a19917daSJordy Rose // FIXME: This file leaks ExplicitSymbols and OpenedHandles! 13447762daSMichael J. Spencer // 14447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 15447762daSMichael J. Spencer 16a19917daSJordy Rose #include "llvm/ADT/StringMap.h" 17a19917daSJordy 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. 25a19917daSJordy 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 39a19917daSJordy Rose 40a19917daSJordy Rose static llvm::sys::SmartMutex<true>& getMutex() { 41a19917daSJordy Rose static llvm::sys::SmartMutex<true> HandlesMutex; 42a19917daSJordy Rose return HandlesMutex; 43a19917daSJordy Rose } 44a19917daSJordy Rose 45a19917daSJordy Rose void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName, 46447762daSMichael J. Spencer void *symbolValue) { 47a19917daSJordy Rose SmartScopedLock<true> lock(getMutex()); 48447762daSMichael J. Spencer if (ExplicitSymbols == 0) 49a19917daSJordy Rose ExplicitSymbols = new llvm::StringMap<void*>(); 50447762daSMichael J. Spencer (*ExplicitSymbols)[symbolName] = symbolValue; 51447762daSMichael J. Spencer } 52447762daSMichael J. Spencer 53*04bc405aSJordy Rose char llvm::sys::DynamicLibrary::Invalid = 0; 54*04bc405aSJordy Rose 55447762daSMichael J. Spencer #ifdef LLVM_ON_WIN32 56447762daSMichael J. Spencer 57447762daSMichael J. Spencer #include "Windows/DynamicLibrary.inc" 58447762daSMichael J. Spencer 59447762daSMichael J. Spencer #else 60447762daSMichael J. Spencer 61447762daSMichael J. Spencer #if HAVE_DLFCN_H 62447762daSMichael J. Spencer #include <dlfcn.h> 63447762daSMichael J. Spencer using namespace llvm; 64447762daSMichael J. Spencer using namespace llvm::sys; 65447762daSMichael J. Spencer 66447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 67447762daSMichael J. Spencer //=== WARNING: Implementation here must contain only TRULY operating system 68447762daSMichael J. Spencer //=== independent code. 69447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 70447762daSMichael J. Spencer 71a19917daSJordy Rose static DenseSet<void *> *OpenedHandles = 0; 72447762daSMichael J. Spencer 73a19917daSJordy Rose DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 74a19917daSJordy Rose std::string *errMsg) { 75a19917daSJordy Rose void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL); 76a19917daSJordy Rose if (handle == 0) { 77a19917daSJordy Rose if (errMsg) *errMsg = dlerror(); 78a19917daSJordy Rose return DynamicLibrary(); 79447762daSMichael J. Spencer } 80447762daSMichael J. Spencer 81447762daSMichael J. Spencer #ifdef __CYGWIN__ 82447762daSMichael J. Spencer // Cygwin searches symbols only in the main 83447762daSMichael J. Spencer // with the handle of dlopen(NULL, RTLD_GLOBAL). 84a19917daSJordy Rose if (filename == NULL) 85a19917daSJordy Rose handle = RTLD_DEFAULT; 86447762daSMichael J. Spencer #endif 87a19917daSJordy Rose 88a19917daSJordy Rose SmartScopedLock<true> lock(getMutex()); 89447762daSMichael J. Spencer if (OpenedHandles == 0) 90a19917daSJordy Rose OpenedHandles = new DenseSet<void *>(); 91a19917daSJordy Rose 92a19917daSJordy Rose // If we've already loaded this library, dlclose() the handle in order to 93a19917daSJordy Rose // keep the internal refcount at +1. 94a19917daSJordy Rose if (!OpenedHandles->insert(handle).second) 95a19917daSJordy Rose dlclose(handle); 96a19917daSJordy Rose 97a19917daSJordy Rose return DynamicLibrary(handle); 98447762daSMichael J. Spencer } 99a19917daSJordy Rose 100a19917daSJordy Rose void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 101a19917daSJordy Rose if (!isValid()) 102a19917daSJordy Rose return NULL; 103a19917daSJordy Rose return dlsym(Data, symbolName); 104a19917daSJordy Rose } 105a19917daSJordy Rose 106447762daSMichael J. Spencer #else 107447762daSMichael J. Spencer 108447762daSMichael J. Spencer using namespace llvm; 109447762daSMichael J. Spencer using namespace llvm::sys; 110447762daSMichael J. Spencer 111a19917daSJordy Rose DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 112a19917daSJordy Rose std::string *errMsg) { 113a19917daSJordy Rose if (errMsg) *errMsg = "dlopen() not supported on this platform"; 114a19917daSJordy Rose return DynamicLibrary(); 115447762daSMichael J. Spencer } 116a19917daSJordy Rose 117a19917daSJordy Rose void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 118a19917daSJordy Rose return NULL; 119a19917daSJordy Rose } 120a19917daSJordy Rose 121447762daSMichael J. Spencer #endif 122447762daSMichael J. Spencer 123447762daSMichael J. Spencer namespace llvm { 124447762daSMichael J. Spencer void *SearchForAddressOfSpecialSymbol(const char* symbolName); 125447762daSMichael J. Spencer } 126447762daSMichael J. Spencer 127447762daSMichael J. Spencer void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { 128a19917daSJordy Rose SmartScopedLock<true> Lock(getMutex()); 129a19917daSJordy Rose 130447762daSMichael J. Spencer // First check symbols added via AddSymbol(). 131447762daSMichael J. Spencer if (ExplicitSymbols) { 132a19917daSJordy Rose StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName); 133447762daSMichael J. Spencer 134a19917daSJordy Rose if (i != ExplicitSymbols->end()) 135a19917daSJordy Rose return i->second; 136447762daSMichael J. Spencer } 137447762daSMichael J. Spencer 138447762daSMichael J. Spencer #if HAVE_DLFCN_H 139447762daSMichael J. Spencer // Now search the libraries. 140447762daSMichael J. Spencer if (OpenedHandles) { 141a19917daSJordy Rose for (DenseSet<void *>::iterator I = OpenedHandles->begin(), 142447762daSMichael J. Spencer E = OpenedHandles->end(); I != E; ++I) { 143447762daSMichael J. Spencer //lt_ptr ptr = lt_dlsym(*I, symbolName); 144447762daSMichael J. Spencer void *ptr = dlsym(*I, symbolName); 145447762daSMichael J. Spencer if (ptr) { 146447762daSMichael J. Spencer return ptr; 147447762daSMichael J. Spencer } 148447762daSMichael J. Spencer } 149447762daSMichael J. Spencer } 150447762daSMichael J. Spencer #endif 151447762daSMichael J. Spencer 152447762daSMichael J. Spencer if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) 153447762daSMichael J. Spencer return Result; 154447762daSMichael J. Spencer 155447762daSMichael J. Spencer // This macro returns the address of a well-known, explicit symbol 156447762daSMichael J. Spencer #define EXPLICIT_SYMBOL(SYM) \ 157447762daSMichael J. Spencer if (!strcmp(symbolName, #SYM)) return &SYM 158447762daSMichael J. Spencer 159447762daSMichael J. Spencer // On linux we have a weird situation. The stderr/out/in symbols are both 160447762daSMichael J. Spencer // macros and global variables because of standards requirements. So, we 161447762daSMichael J. Spencer // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 162447762daSMichael J. Spencer #if defined(__linux__) 163447762daSMichael J. Spencer { 164447762daSMichael J. Spencer EXPLICIT_SYMBOL(stderr); 165447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdout); 166447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdin); 167447762daSMichael J. Spencer } 168447762daSMichael J. Spencer #else 169447762daSMichael J. Spencer // For everything else, we want to check to make sure the symbol isn't defined 170447762daSMichael J. Spencer // as a macro before using EXPLICIT_SYMBOL. 171447762daSMichael J. Spencer { 172447762daSMichael J. Spencer #ifndef stdin 173447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdin); 174447762daSMichael J. Spencer #endif 175447762daSMichael J. Spencer #ifndef stdout 176447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdout); 177447762daSMichael J. Spencer #endif 178447762daSMichael J. Spencer #ifndef stderr 179447762daSMichael J. Spencer EXPLICIT_SYMBOL(stderr); 180447762daSMichael J. Spencer #endif 181447762daSMichael J. Spencer } 182447762daSMichael J. Spencer #endif 183447762daSMichael J. Spencer #undef EXPLICIT_SYMBOL 184447762daSMichael J. Spencer 185447762daSMichael J. Spencer return 0; 186447762daSMichael J. Spencer } 187447762daSMichael J. Spencer 188447762daSMichael J. Spencer #endif // LLVM_ON_WIN32 189