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 16447762daSMichael J. Spencer #include "llvm/Support/DynamicLibrary.h" 17*8a8cd2baSChandler Carruth #include "llvm-c/Support.h" 18ed0881b2SChandler Carruth #include "llvm/ADT/DenseSet.h" 19ed0881b2SChandler Carruth #include "llvm/ADT/StringMap.h" 20447762daSMichael J. Spencer #include "llvm/Config/config.h" 21*8a8cd2baSChandler Carruth #include "llvm/Support/ManagedStatic.h" 22ed0881b2SChandler Carruth #include "llvm/Support/Mutex.h" 23447762daSMichael J. Spencer #include <cstdio> 24447762daSMichael J. Spencer #include <cstring> 25447762daSMichael J. Spencer 26447762daSMichael J. Spencer // Collection of symbol name/value pairs to be searched prior to any libraries. 2757093e88SFilip Pizlo static llvm::ManagedStatic<llvm::StringMap<void *> > ExplicitSymbols; 2857093e88SFilip Pizlo static llvm::ManagedStatic<llvm::sys::SmartMutex<true> > SymbolsMutex; 29a19917daSJordy Rose 30a19917daSJordy Rose void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName, 31447762daSMichael J. Spencer void *symbolValue) { 3257093e88SFilip Pizlo SmartScopedLock<true> lock(*SymbolsMutex); 33447762daSMichael J. Spencer (*ExplicitSymbols)[symbolName] = symbolValue; 34447762daSMichael J. Spencer } 35447762daSMichael J. Spencer 3604bc405aSJordy Rose char llvm::sys::DynamicLibrary::Invalid = 0; 3704bc405aSJordy Rose 38447762daSMichael J. Spencer #ifdef LLVM_ON_WIN32 39447762daSMichael J. Spencer 40447762daSMichael J. Spencer #include "Windows/DynamicLibrary.inc" 41447762daSMichael J. Spencer 42447762daSMichael J. Spencer #else 43447762daSMichael J. Spencer 44447762daSMichael J. Spencer #if HAVE_DLFCN_H 45447762daSMichael J. Spencer #include <dlfcn.h> 46447762daSMichael J. Spencer using namespace llvm; 47447762daSMichael J. Spencer using namespace llvm::sys; 48447762daSMichael J. Spencer 49447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 50447762daSMichael J. Spencer //=== WARNING: Implementation here must contain only TRULY operating system 51447762daSMichael J. Spencer //=== independent code. 52447762daSMichael J. Spencer //===----------------------------------------------------------------------===// 53447762daSMichael J. Spencer 54a19917daSJordy Rose static DenseSet<void *> *OpenedHandles = 0; 55447762daSMichael J. Spencer 56a19917daSJordy Rose DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 57a19917daSJordy Rose std::string *errMsg) { 5857093e88SFilip Pizlo SmartScopedLock<true> lock(*SymbolsMutex); 595765f4c2SJordy Rose 60a19917daSJordy Rose void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL); 61a19917daSJordy Rose if (handle == 0) { 62a19917daSJordy Rose if (errMsg) *errMsg = dlerror(); 63a19917daSJordy Rose return DynamicLibrary(); 64447762daSMichael J. Spencer } 65447762daSMichael J. Spencer 66447762daSMichael J. Spencer #ifdef __CYGWIN__ 67447762daSMichael J. Spencer // Cygwin searches symbols only in the main 68447762daSMichael J. Spencer // with the handle of dlopen(NULL, RTLD_GLOBAL). 69a19917daSJordy Rose if (filename == NULL) 70a19917daSJordy Rose handle = RTLD_DEFAULT; 71447762daSMichael J. Spencer #endif 72a19917daSJordy Rose 73447762daSMichael J. Spencer if (OpenedHandles == 0) 74a19917daSJordy Rose OpenedHandles = new DenseSet<void *>(); 75a19917daSJordy Rose 76a19917daSJordy Rose // If we've already loaded this library, dlclose() the handle in order to 77a19917daSJordy Rose // keep the internal refcount at +1. 78a19917daSJordy Rose if (!OpenedHandles->insert(handle).second) 79a19917daSJordy Rose dlclose(handle); 80a19917daSJordy Rose 81a19917daSJordy Rose return DynamicLibrary(handle); 82447762daSMichael J. Spencer } 83a19917daSJordy Rose 84a19917daSJordy Rose void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 85a19917daSJordy Rose if (!isValid()) 86a19917daSJordy Rose return NULL; 87a19917daSJordy Rose return dlsym(Data, symbolName); 88a19917daSJordy Rose } 89a19917daSJordy Rose 90447762daSMichael J. Spencer #else 91447762daSMichael J. Spencer 92447762daSMichael J. Spencer using namespace llvm; 93447762daSMichael J. Spencer using namespace llvm::sys; 94447762daSMichael J. Spencer 95a19917daSJordy Rose DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 96a19917daSJordy Rose std::string *errMsg) { 97a19917daSJordy Rose if (errMsg) *errMsg = "dlopen() not supported on this platform"; 98a19917daSJordy Rose return DynamicLibrary(); 99447762daSMichael J. Spencer } 100a19917daSJordy Rose 101a19917daSJordy Rose void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 102a19917daSJordy Rose return NULL; 103a19917daSJordy Rose } 104a19917daSJordy Rose 105447762daSMichael J. Spencer #endif 106447762daSMichael J. Spencer 107447762daSMichael J. Spencer namespace llvm { 108447762daSMichael J. Spencer void *SearchForAddressOfSpecialSymbol(const char* symbolName); 109447762daSMichael J. Spencer } 110447762daSMichael J. Spencer 111447762daSMichael J. Spencer void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { 11257093e88SFilip Pizlo SmartScopedLock<true> Lock(*SymbolsMutex); 113a19917daSJordy Rose 114447762daSMichael J. Spencer // First check symbols added via AddSymbol(). 11557093e88SFilip Pizlo if (ExplicitSymbols.isConstructed()) { 116a19917daSJordy Rose StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName); 117447762daSMichael J. Spencer 118a19917daSJordy Rose if (i != ExplicitSymbols->end()) 119a19917daSJordy Rose return i->second; 120447762daSMichael J. Spencer } 121447762daSMichael J. Spencer 122447762daSMichael J. Spencer #if HAVE_DLFCN_H 123447762daSMichael J. Spencer // Now search the libraries. 124447762daSMichael J. Spencer if (OpenedHandles) { 125a19917daSJordy Rose for (DenseSet<void *>::iterator I = OpenedHandles->begin(), 126447762daSMichael J. Spencer E = OpenedHandles->end(); I != E; ++I) { 127447762daSMichael J. Spencer //lt_ptr ptr = lt_dlsym(*I, symbolName); 128447762daSMichael J. Spencer void *ptr = dlsym(*I, symbolName); 129447762daSMichael J. Spencer if (ptr) { 130447762daSMichael J. Spencer return ptr; 131447762daSMichael J. Spencer } 132447762daSMichael J. Spencer } 133447762daSMichael J. Spencer } 134447762daSMichael J. Spencer #endif 135447762daSMichael J. Spencer 136447762daSMichael J. Spencer if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) 137447762daSMichael J. Spencer return Result; 138447762daSMichael J. Spencer 139447762daSMichael J. Spencer // This macro returns the address of a well-known, explicit symbol 140447762daSMichael J. Spencer #define EXPLICIT_SYMBOL(SYM) \ 141447762daSMichael J. Spencer if (!strcmp(symbolName, #SYM)) return &SYM 142447762daSMichael J. Spencer 143447762daSMichael J. Spencer // On linux we have a weird situation. The stderr/out/in symbols are both 144447762daSMichael J. Spencer // macros and global variables because of standards requirements. So, we 145447762daSMichael J. Spencer // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 146c439a426SEvgeniy Stepanov #if defined(__linux__) and !defined(__ANDROID__) 147447762daSMichael J. Spencer { 148447762daSMichael J. Spencer EXPLICIT_SYMBOL(stderr); 149447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdout); 150447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdin); 151447762daSMichael J. Spencer } 152447762daSMichael J. Spencer #else 153447762daSMichael J. Spencer // For everything else, we want to check to make sure the symbol isn't defined 154447762daSMichael J. Spencer // as a macro before using EXPLICIT_SYMBOL. 155447762daSMichael J. Spencer { 156447762daSMichael J. Spencer #ifndef stdin 157447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdin); 158447762daSMichael J. Spencer #endif 159447762daSMichael J. Spencer #ifndef stdout 160447762daSMichael J. Spencer EXPLICIT_SYMBOL(stdout); 161447762daSMichael J. Spencer #endif 162447762daSMichael J. Spencer #ifndef stderr 163447762daSMichael J. Spencer EXPLICIT_SYMBOL(stderr); 164447762daSMichael J. Spencer #endif 165447762daSMichael J. Spencer } 166447762daSMichael J. Spencer #endif 167447762daSMichael J. Spencer #undef EXPLICIT_SYMBOL 168447762daSMichael J. Spencer 169447762daSMichael J. Spencer return 0; 170447762daSMichael J. Spencer } 171447762daSMichael J. Spencer 172447762daSMichael J. Spencer #endif // LLVM_ON_WIN32 17334ddbf1aSPeter Zotov 17434ddbf1aSPeter Zotov //===----------------------------------------------------------------------===// 17534ddbf1aSPeter Zotov // C API. 17634ddbf1aSPeter Zotov //===----------------------------------------------------------------------===// 17734ddbf1aSPeter Zotov 17834ddbf1aSPeter Zotov LLVMBool LLVMLoadLibraryPermanently(const char* Filename) { 179671fe2eeSPeter Zotov return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename); 18034ddbf1aSPeter Zotov } 181