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 5304bc405aSJordy Rose char llvm::sys::DynamicLibrary::Invalid = 0; 5404bc405aSJordy 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) { 75*5765f4c2SJordy Rose SmartScopedLock<true> lock(getMutex()); 76*5765f4c2SJordy Rose 77a19917daSJordy Rose void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL); 78a19917daSJordy Rose if (handle == 0) { 79a19917daSJordy Rose if (errMsg) *errMsg = dlerror(); 80a19917daSJordy Rose return DynamicLibrary(); 81447762daSMichael J. Spencer } 82447762daSMichael J. Spencer 83447762daSMichael J. Spencer #ifdef __CYGWIN__ 84447762daSMichael J. Spencer // Cygwin searches symbols only in the main 85447762daSMichael J. Spencer // with the handle of dlopen(NULL, RTLD_GLOBAL). 86a19917daSJordy Rose if (filename == NULL) 87a19917daSJordy Rose handle = RTLD_DEFAULT; 88447762daSMichael J. Spencer #endif 89a19917daSJordy Rose 90447762daSMichael J. Spencer if (OpenedHandles == 0) 91a19917daSJordy Rose OpenedHandles = new DenseSet<void *>(); 92a19917daSJordy Rose 93a19917daSJordy Rose // If we've already loaded this library, dlclose() the handle in order to 94a19917daSJordy Rose // keep the internal refcount at +1. 95a19917daSJordy Rose if (!OpenedHandles->insert(handle).second) 96a19917daSJordy Rose dlclose(handle); 97a19917daSJordy Rose 98a19917daSJordy Rose return DynamicLibrary(handle); 99447762daSMichael J. Spencer } 100a19917daSJordy Rose 101a19917daSJordy Rose void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 102a19917daSJordy Rose if (!isValid()) 103a19917daSJordy Rose return NULL; 104a19917daSJordy Rose return dlsym(Data, symbolName); 105a19917daSJordy Rose } 106a19917daSJordy Rose 107447762daSMichael J. Spencer #else 108447762daSMichael J. Spencer 109447762daSMichael J. Spencer using namespace llvm; 110447762daSMichael J. Spencer using namespace llvm::sys; 111447762daSMichael J. Spencer 112a19917daSJordy Rose DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 113a19917daSJordy Rose std::string *errMsg) { 114a19917daSJordy Rose if (errMsg) *errMsg = "dlopen() not supported on this platform"; 115a19917daSJordy Rose return DynamicLibrary(); 116447762daSMichael J. Spencer } 117a19917daSJordy Rose 118a19917daSJordy Rose void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 119a19917daSJordy Rose return NULL; 120a19917daSJordy Rose } 121a19917daSJordy Rose 122447762daSMichael J. Spencer #endif 123447762daSMichael J. Spencer 124447762daSMichael J. Spencer namespace llvm { 125447762daSMichael J. Spencer void *SearchForAddressOfSpecialSymbol(const char* symbolName); 126447762daSMichael J. Spencer } 127447762daSMichael J. Spencer 128447762daSMichael J. Spencer void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { 129a19917daSJordy Rose SmartScopedLock<true> Lock(getMutex()); 130a19917daSJordy Rose 131447762daSMichael J. Spencer // First check symbols added via AddSymbol(). 132447762daSMichael J. Spencer if (ExplicitSymbols) { 133a19917daSJordy Rose StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName); 134447762daSMichael J. Spencer 135a19917daSJordy Rose if (i != ExplicitSymbols->end()) 136a19917daSJordy Rose return i->second; 137447762daSMichael J. Spencer } 138447762daSMichael J. Spencer 139447762daSMichael J. Spencer #if HAVE_DLFCN_H 140447762daSMichael J. Spencer // Now search the libraries. 141447762daSMichael J. Spencer if (OpenedHandles) { 142a19917daSJordy Rose for (DenseSet<void *>::iterator I = OpenedHandles->begin(), 143447762daSMichael J. Spencer E = OpenedHandles->end(); I != E; ++I) { 144447762daSMichael J. Spencer //lt_ptr ptr = lt_dlsym(*I, symbolName); 145447762daSMichael J. Spencer void *ptr = dlsym(*I, symbolName); 146447762daSMichael J. Spencer if (ptr) { 147447762daSMichael J. Spencer return ptr; 148447762daSMichael J. Spencer } 149447762daSMichael J. Spencer } 150447762daSMichael J. Spencer } 151447762daSMichael J. Spencer #endif 152447762daSMichael J. Spencer 153447762daSMichael J. Spencer if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) 154447762daSMichael J. Spencer return Result; 155447762daSMichael J. Spencer 156447762daSMichael J. Spencer // This macro returns the address of a well-known, explicit symbol 157447762daSMichael J. Spencer #define EXPLICIT_SYMBOL(SYM) \ 158447762daSMichael J. Spencer if (!strcmp(symbolName, #SYM)) return &SYM 159447762daSMichael J. Spencer 160447762daSMichael J. Spencer // On linux we have a weird situation. The stderr/out/in symbols are both 161447762daSMichael J. Spencer // macros and global variables because of standards requirements. So, we 162447762daSMichael J. Spencer // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 163447762daSMichael J. Spencer #if defined(__linux__) 164447762daSMichael J. Spencer { 165447762daSMichael J. Spencer EXPLICIT_SYMBOL(stderr); 166447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdout); 167447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdin); 168447762daSMichael J. Spencer } 169447762daSMichael J. Spencer #else 170447762daSMichael J. Spencer // For everything else, we want to check to make sure the symbol isn't defined 171447762daSMichael J. Spencer // as a macro before using EXPLICIT_SYMBOL. 172447762daSMichael J. Spencer { 173447762daSMichael J. Spencer #ifndef stdin 174447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdin); 175447762daSMichael J. Spencer #endif 176447762daSMichael J. Spencer #ifndef stdout 177447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdout); 178447762daSMichael J. Spencer #endif 179447762daSMichael J. Spencer #ifndef stderr 180447762daSMichael J. Spencer EXPLICIT_SYMBOL(stderr); 181447762daSMichael J. Spencer #endif 182447762daSMichael J. Spencer } 183447762daSMichael J. Spencer #endif 184447762daSMichael J. Spencer #undef EXPLICIT_SYMBOL 185447762daSMichael J. Spencer 186447762daSMichael J. Spencer return 0; 187447762daSMichael J. Spencer } 188447762daSMichael J. Spencer 189447762daSMichael J. Spencer #endif // LLVM_ON_WIN32 190