LLVM API Documentation
00001 //===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the operating system DynamicLibrary concept. 00011 // 00012 // FIXME: This file leaks ExplicitSymbols and OpenedHandles! 00013 // 00014 //===----------------------------------------------------------------------===// 00015 00016 #include "llvm/Support/DynamicLibrary.h" 00017 #include "llvm-c/Support.h" 00018 #include "llvm/ADT/DenseSet.h" 00019 #include "llvm/ADT/StringMap.h" 00020 #include "llvm/Config/config.h" 00021 #include "llvm/Support/ManagedStatic.h" 00022 #include "llvm/Support/Mutex.h" 00023 #include <cstdio> 00024 #include <cstring> 00025 00026 // Collection of symbol name/value pairs to be searched prior to any libraries. 00027 static llvm::ManagedStatic<llvm::StringMap<void *> > ExplicitSymbols; 00028 static llvm::ManagedStatic<llvm::sys::SmartMutex<true> > SymbolsMutex; 00029 00030 void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName, 00031 void *symbolValue) { 00032 SmartScopedLock<true> lock(*SymbolsMutex); 00033 (*ExplicitSymbols)[symbolName] = symbolValue; 00034 } 00035 00036 char llvm::sys::DynamicLibrary::Invalid = 0; 00037 00038 #ifdef LLVM_ON_WIN32 00039 00040 #include "Windows/DynamicLibrary.inc" 00041 00042 #else 00043 00044 #if HAVE_DLFCN_H 00045 #include <dlfcn.h> 00046 using namespace llvm; 00047 using namespace llvm::sys; 00048 00049 //===----------------------------------------------------------------------===// 00050 //=== WARNING: Implementation here must contain only TRULY operating system 00051 //=== independent code. 00052 //===----------------------------------------------------------------------===// 00053 00054 static DenseSet<void *> *OpenedHandles = nullptr; 00055 00056 DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 00057 std::string *errMsg) { 00058 SmartScopedLock<true> lock(*SymbolsMutex); 00059 00060 void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL); 00061 if (!handle) { 00062 if (errMsg) *errMsg = dlerror(); 00063 return DynamicLibrary(); 00064 } 00065 00066 #ifdef __CYGWIN__ 00067 // Cygwin searches symbols only in the main 00068 // with the handle of dlopen(NULL, RTLD_GLOBAL). 00069 if (!filename) 00070 handle = RTLD_DEFAULT; 00071 #endif 00072 00073 if (!OpenedHandles) 00074 OpenedHandles = new DenseSet<void *>(); 00075 00076 // If we've already loaded this library, dlclose() the handle in order to 00077 // keep the internal refcount at +1. 00078 if (!OpenedHandles->insert(handle).second) 00079 dlclose(handle); 00080 00081 return DynamicLibrary(handle); 00082 } 00083 00084 void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 00085 if (!isValid()) 00086 return nullptr; 00087 return dlsym(Data, symbolName); 00088 } 00089 00090 #else 00091 00092 using namespace llvm; 00093 using namespace llvm::sys; 00094 00095 DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 00096 std::string *errMsg) { 00097 if (errMsg) *errMsg = "dlopen() not supported on this platform"; 00098 return DynamicLibrary(); 00099 } 00100 00101 void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 00102 return NULL; 00103 } 00104 00105 #endif 00106 00107 namespace llvm { 00108 void *SearchForAddressOfSpecialSymbol(const char* symbolName); 00109 } 00110 00111 void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { 00112 SmartScopedLock<true> Lock(*SymbolsMutex); 00113 00114 // First check symbols added via AddSymbol(). 00115 if (ExplicitSymbols.isConstructed()) { 00116 StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName); 00117 00118 if (i != ExplicitSymbols->end()) 00119 return i->second; 00120 } 00121 00122 #if HAVE_DLFCN_H 00123 // Now search the libraries. 00124 if (OpenedHandles) { 00125 for (DenseSet<void *>::iterator I = OpenedHandles->begin(), 00126 E = OpenedHandles->end(); I != E; ++I) { 00127 //lt_ptr ptr = lt_dlsym(*I, symbolName); 00128 void *ptr = dlsym(*I, symbolName); 00129 if (ptr) { 00130 return ptr; 00131 } 00132 } 00133 } 00134 #endif 00135 00136 if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) 00137 return Result; 00138 00139 // This macro returns the address of a well-known, explicit symbol 00140 #define EXPLICIT_SYMBOL(SYM) \ 00141 if (!strcmp(symbolName, #SYM)) return &SYM 00142 00143 // On linux we have a weird situation. The stderr/out/in symbols are both 00144 // macros and global variables because of standards requirements. So, we 00145 // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. 00146 #if defined(__linux__) and !defined(__ANDROID__) 00147 { 00148 EXPLICIT_SYMBOL(stderr); 00149 EXPLICIT_SYMBOL(stdout); 00150 EXPLICIT_SYMBOL(stdin); 00151 } 00152 #else 00153 // For everything else, we want to check to make sure the symbol isn't defined 00154 // as a macro before using EXPLICIT_SYMBOL. 00155 { 00156 #ifndef stdin 00157 EXPLICIT_SYMBOL(stdin); 00158 #endif 00159 #ifndef stdout 00160 EXPLICIT_SYMBOL(stdout); 00161 #endif 00162 #ifndef stderr 00163 EXPLICIT_SYMBOL(stderr); 00164 #endif 00165 } 00166 #endif 00167 #undef EXPLICIT_SYMBOL 00168 00169 return nullptr; 00170 } 00171 00172 #endif // LLVM_ON_WIN32 00173 00174 //===----------------------------------------------------------------------===// 00175 // C API. 00176 //===----------------------------------------------------------------------===// 00177 00178 LLVMBool LLVMLoadLibraryPermanently(const char* Filename) { 00179 return llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename); 00180 }