DynamicLibrary.cpp revision 008a5f515aca0412db4eb9c572c6a9aef956f39e
1//===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This header file implements the operating system DynamicLibrary concept. 11// 12// FIXME: This file leaks ExplicitSymbols and OpenedHandles! 13// 14//===----------------------------------------------------------------------===// 15 16#include "llvm/ADT/StringMap.h" 17#include "llvm/ADT/DenseSet.h" 18#include "llvm/Support/DynamicLibrary.h" 19#include "llvm/Support/Mutex.h" 20#include "llvm/Config/config.h" 21#include <cstdio> 22#include <cstring> 23 24// Collection of symbol name/value pairs to be searched prior to any libraries. 25static llvm::StringMap<void *> *ExplicitSymbols = 0; 26 27namespace { 28 29struct ExplicitSymbolsDeleter { 30 ~ExplicitSymbolsDeleter() { 31 delete ExplicitSymbols; 32 } 33}; 34 35} 36 37static ExplicitSymbolsDeleter Dummy; 38 39 40static llvm::sys::SmartMutex<true>& getMutex() { 41 static llvm::sys::SmartMutex<true> HandlesMutex; 42 return HandlesMutex; 43} 44 45void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName, 46 void *symbolValue) { 47 SmartScopedLock<true> lock(getMutex()); 48 if (ExplicitSymbols == 0) 49 ExplicitSymbols = new llvm::StringMap<void*>(); 50 (*ExplicitSymbols)[symbolName] = symbolValue; 51} 52 53char llvm::sys::DynamicLibrary::Invalid = 0; 54 55#ifdef LLVM_ON_WIN32 56 57#include "Windows/DynamicLibrary.inc" 58 59#else 60 61#if HAVE_DLFCN_H 62#include <dlfcn.h> 63using namespace llvm; 64using namespace llvm::sys; 65 66//===----------------------------------------------------------------------===// 67//=== WARNING: Implementation here must contain only TRULY operating system 68//=== independent code. 69//===----------------------------------------------------------------------===// 70 71static DenseSet<void *> *OpenedHandles = 0; 72 73DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 74 std::string *errMsg) { 75 void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL); 76 if (handle == 0) { 77 if (errMsg) *errMsg = dlerror(); 78 return DynamicLibrary(); 79 } 80 81#ifdef __CYGWIN__ 82 // Cygwin searches symbols only in the main 83 // with the handle of dlopen(NULL, RTLD_GLOBAL). 84 if (filename == NULL) 85 handle = RTLD_DEFAULT; 86#endif 87 88 SmartScopedLock<true> lock(getMutex()); 89 if (OpenedHandles == 0) 90 OpenedHandles = new DenseSet<void *>(); 91 92 // If we've already loaded this library, dlclose() the handle in order to 93 // keep the internal refcount at +1. 94 if (!OpenedHandles->insert(handle).second) 95 dlclose(handle); 96 97 return DynamicLibrary(handle); 98} 99 100void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 101 if (!isValid()) 102 return NULL; 103 return dlsym(Data, symbolName); 104} 105 106#else 107 108using namespace llvm; 109using namespace llvm::sys; 110 111DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 112 std::string *errMsg) { 113 if (errMsg) *errMsg = "dlopen() not supported on this platform"; 114 return DynamicLibrary(); 115} 116 117void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 118 return NULL; 119} 120 121#endif 122 123namespace llvm { 124void *SearchForAddressOfSpecialSymbol(const char* symbolName); 125} 126 127void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { 128 SmartScopedLock<true> Lock(getMutex()); 129 130 // First check symbols added via AddSymbol(). 131 if (ExplicitSymbols) { 132 StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName); 133 134 if (i != ExplicitSymbols->end()) 135 return i->second; 136 } 137 138#if HAVE_DLFCN_H 139 // Now search the libraries. 140 if (OpenedHandles) { 141 for (DenseSet<void *>::iterator I = OpenedHandles->begin(), 142 E = OpenedHandles->end(); I != E; ++I) { 143 //lt_ptr ptr = lt_dlsym(*I, symbolName); 144 void *ptr = dlsym(*I, symbolName); 145 if (ptr) { 146 return ptr; 147 } 148 } 149 } 150#endif 151 152 if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) 153 return Result; 154 155// This macro returns the address of a well-known, explicit symbol 156#define EXPLICIT_SYMBOL(SYM) \ 157 if (!strcmp(symbolName, #SYM)) return &SYM 158 159// On linux we have a weird situation. The stderr/out/in symbols are both 160// macros and global variables because of standards requirements. So, we 161// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 162#if defined(__linux__) 163 { 164 EXPLICIT_SYMBOL(stderr); 165 EXPLICIT_SYMBOL(stdout); 166 EXPLICIT_SYMBOL(stdin); 167 } 168#else 169 // For everything else, we want to check to make sure the symbol isn't defined 170 // as a macro before using EXPLICIT_SYMBOL. 171 { 172#ifndef stdin 173 EXPLICIT_SYMBOL(stdin); 174#endif 175#ifndef stdout 176 EXPLICIT_SYMBOL(stdout); 177#endif 178#ifndef stderr 179 EXPLICIT_SYMBOL(stderr); 180#endif 181 } 182#endif 183#undef EXPLICIT_SYMBOL 184 185 return 0; 186} 187 188#endif // LLVM_ON_WIN32 189