DynamicLibrary.cpp revision 288943
133965Sjdp//===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===// 233965Sjdp// 333965Sjdp// The LLVM Compiler Infrastructure 433965Sjdp// 533965Sjdp// This file is distributed under the University of Illinois Open Source 633965Sjdp// License. See LICENSE.TXT for details. 733965Sjdp// 833965Sjdp//===----------------------------------------------------------------------===// 933965Sjdp// 1033965Sjdp// This file implements the operating system DynamicLibrary concept. 1133965Sjdp// 1233965Sjdp// FIXME: This file leaks ExplicitSymbols and OpenedHandles! 1333965Sjdp// 1433965Sjdp//===----------------------------------------------------------------------===// 1533965Sjdp 1633965Sjdp#include "llvm/Support/DynamicLibrary.h" 1733965Sjdp#include "llvm-c/Support.h" 1833965Sjdp#include "llvm/ADT/DenseSet.h" 1933965Sjdp#include "llvm/ADT/StringMap.h" 2033965Sjdp#include "llvm/Config/config.h" 2133965Sjdp#include "llvm/Support/ManagedStatic.h" 2233965Sjdp#include "llvm/Support/Mutex.h" 2333965Sjdp#include <cstdio> 2433965Sjdp#include <cstring> 2533965Sjdp 2633965Sjdp// Collection of symbol name/value pairs to be searched prior to any libraries. 2733965Sjdpstatic llvm::ManagedStatic<llvm::StringMap<void *> > ExplicitSymbols; 2833965Sjdpstatic llvm::ManagedStatic<llvm::sys::SmartMutex<true> > SymbolsMutex; 2933965Sjdp 3033965Sjdpvoid llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName, 3133965Sjdp void *symbolValue) { 3233965Sjdp SmartScopedLock<true> lock(*SymbolsMutex); 3333965Sjdp (*ExplicitSymbols)[symbolName] = symbolValue; 3433965Sjdp} 3533965Sjdp 3633965Sjdpchar llvm::sys::DynamicLibrary::Invalid = 0; 3733965Sjdp 3833965Sjdp#ifdef LLVM_ON_WIN32 3933965Sjdp 4033965Sjdp#include "Windows/DynamicLibrary.inc" 4133965Sjdp 4233965Sjdp#else 4333965Sjdp 4433965Sjdp#if HAVE_DLFCN_H 4533965Sjdp#include <dlfcn.h> 4633965Sjdpusing namespace llvm; 4733965Sjdpusing namespace llvm::sys; 4833965Sjdp 4933965Sjdp//===----------------------------------------------------------------------===// 5033965Sjdp//=== WARNING: Implementation here must contain only TRULY operating system 5133965Sjdp//=== independent code. 5233965Sjdp//===----------------------------------------------------------------------===// 5333965Sjdp 5433965Sjdpstatic DenseSet<void *> *OpenedHandles = nullptr; 5533965Sjdp 5633965SjdpDynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 5733965Sjdp std::string *errMsg) { 5833965Sjdp SmartScopedLock<true> lock(*SymbolsMutex); 5933965Sjdp 6033965Sjdp void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL); 6133965Sjdp if (!handle) { 6233965Sjdp if (errMsg) *errMsg = dlerror(); 6333965Sjdp return DynamicLibrary(); 6433965Sjdp } 6533965Sjdp 6633965Sjdp#ifdef __CYGWIN__ 6733965Sjdp // Cygwin searches symbols only in the main 6833965Sjdp // with the handle of dlopen(NULL, RTLD_GLOBAL). 6933965Sjdp if (!filename) 7033965Sjdp handle = RTLD_DEFAULT; 7133965Sjdp#endif 7233965Sjdp 7333965Sjdp if (!OpenedHandles) 7433965Sjdp OpenedHandles = new DenseSet<void *>(); 7533965Sjdp 7633965Sjdp // If we've already loaded this library, dlclose() the handle in order to 7733965Sjdp // keep the internal refcount at +1. 7833965Sjdp if (!OpenedHandles->insert(handle).second) 7933965Sjdp dlclose(handle); 8033965Sjdp 8133965Sjdp return DynamicLibrary(handle); 8233965Sjdp} 8333965Sjdp 8433965Sjdpvoid *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 8533965Sjdp if (!isValid()) 8633965Sjdp return nullptr; 8733965Sjdp return dlsym(Data, symbolName); 8833965Sjdp} 89 90#else 91 92using namespace llvm; 93using namespace llvm::sys; 94 95DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 96 std::string *errMsg) { 97 if (errMsg) *errMsg = "dlopen() not supported on this platform"; 98 return DynamicLibrary(); 99} 100 101void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 102 return NULL; 103} 104 105#endif 106 107namespace llvm { 108void *SearchForAddressOfSpecialSymbol(const char* symbolName); 109} 110 111void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { 112 SmartScopedLock<true> Lock(*SymbolsMutex); 113 114 // First check symbols added via AddSymbol(). 115 if (ExplicitSymbols.isConstructed()) { 116 StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName); 117 118 if (i != ExplicitSymbols->end()) 119 return i->second; 120 } 121 122#if HAVE_DLFCN_H 123 // Now search the libraries. 124 if (OpenedHandles) { 125 for (DenseSet<void *>::iterator I = OpenedHandles->begin(), 126 E = OpenedHandles->end(); I != E; ++I) { 127 //lt_ptr ptr = lt_dlsym(*I, symbolName); 128 void *ptr = dlsym(*I, symbolName); 129 if (ptr) { 130 return ptr; 131 } 132 } 133 } 134#endif 135 136 if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) 137 return Result; 138 139// This macro returns the address of a well-known, explicit symbol 140#define EXPLICIT_SYMBOL(SYM) \ 141 if (!strcmp(symbolName, #SYM)) return &SYM 142 143// On linux we have a weird situation. The stderr/out/in symbols are both 144// macros and global variables because of standards requirements. So, we 145// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 146#if defined(__linux__) and !defined(__ANDROID__) 147 { 148 EXPLICIT_SYMBOL(stderr); 149 EXPLICIT_SYMBOL(stdout); 150 EXPLICIT_SYMBOL(stdin); 151 } 152#else 153 // For everything else, we want to check to make sure the symbol isn't defined 154 // as a macro before using EXPLICIT_SYMBOL. 155 { 156#ifndef stdin 157 EXPLICIT_SYMBOL(stdin); 158#endif 159#ifndef stdout 160 EXPLICIT_SYMBOL(stdout); 161#endif 162#ifndef stderr 163 EXPLICIT_SYMBOL(stderr); 164#endif 165 } 166#endif 167#undef EXPLICIT_SYMBOL 168 169 return nullptr; 170} 171 172#endif // LLVM_ON_WIN32 173 174//===----------------------------------------------------------------------===// 175// C API. 176//===----------------------------------------------------------------------===// 177 178LLVMBool LLVMLoadLibraryPermanently(const char* Filename) { 179 return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename); 180} 181 182void *LLVMSearchForAddressOfSymbol(const char *symbolName) { 183 return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName); 184} 185 186void LLVMAddSymbol(const char *symbolName, void *symbolValue) { 187 return llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolValue); 188} 189 190