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