LLVM API Documentation
00001 //===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by Reid Spencer and is distributed under the 00006 // University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This header file implements the operating system DynamicLibrary concept. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/System/DynamicLibrary.h" 00015 #include "llvm/Config/config.h" 00016 #include <map> 00017 00018 // Collection of symbol name/value pairs to be searched prior to any libraries. 00019 static std::map<std::string, void *> g_symbols; 00020 00021 void llvm::sys::DynamicLibrary::AddSymbol(const char* symbolName, 00022 void *symbolValue) { 00023 g_symbols[symbolName] = symbolValue; 00024 } 00025 00026 // It is not possible to use ltdl.c on VC++ builds as the terms of its LGPL 00027 // license and special exception would cause all of LLVM to be placed under 00028 // the LGPL. This is because the exception applies only when libtool is 00029 // used, and obviously libtool is not used with Visual Studio. An entirely 00030 // separate implementation is provided in win32/DynamicLibrary.cpp. 00031 00032 #ifdef LLVM_ON_WIN32 00033 00034 #include "Win32/DynamicLibrary.inc" 00035 00036 #else 00037 00038 #include "ltdl.h" 00039 #include <cassert> 00040 using namespace llvm; 00041 using namespace llvm::sys; 00042 00043 //===----------------------------------------------------------------------===// 00044 //=== WARNING: Implementation here must contain only TRULY operating system 00045 //=== independent code. 00046 //===----------------------------------------------------------------------===// 00047 00048 static bool did_initialize_ltdl = false; 00049 00050 static inline void check_ltdl_initialization() { 00051 if (!did_initialize_ltdl) { 00052 if (0 != lt_dlinit()) 00053 throw std::string(lt_dlerror()); 00054 did_initialize_ltdl = true; 00055 } 00056 } 00057 00058 static std::vector<lt_dlhandle> OpenedHandles; 00059 00060 DynamicLibrary::DynamicLibrary() : handle(0) { 00061 check_ltdl_initialization(); 00062 00063 lt_dlhandle a_handle = lt_dlopen(0); 00064 00065 if (a_handle == 0) 00066 throw std::string("Can't open program as dynamic library"); 00067 00068 handle = a_handle; 00069 OpenedHandles.push_back(a_handle); 00070 } 00071 00072 DynamicLibrary::DynamicLibrary(const char*filename) : handle(0) { 00073 check_ltdl_initialization(); 00074 00075 lt_dlhandle a_handle = lt_dlopen(filename); 00076 00077 if (a_handle == 0) 00078 a_handle = lt_dlopenext(filename); 00079 00080 if (a_handle == 0) 00081 throw std::string("Can't open :") + filename + ": " + lt_dlerror(); 00082 00083 handle = a_handle; 00084 OpenedHandles.push_back(a_handle); 00085 } 00086 00087 DynamicLibrary::~DynamicLibrary() { 00088 lt_dlhandle a_handle = (lt_dlhandle) handle; 00089 if (a_handle) { 00090 lt_dlclose(a_handle); 00091 00092 for (std::vector<lt_dlhandle>::iterator I = OpenedHandles.begin(), 00093 E = OpenedHandles.end(); I != E; ++I) { 00094 if (*I == a_handle) { 00095 // Note: don't use the swap/pop_back trick here. Order is important. 00096 OpenedHandles.erase(I); 00097 return; 00098 } 00099 } 00100 } 00101 } 00102 00103 bool DynamicLibrary::LoadLibraryPermanently(const char *Filename, 00104 std::string *ErrMsg) { 00105 check_ltdl_initialization(); 00106 lt_dlhandle a_handle = lt_dlopen(Filename); 00107 00108 if (a_handle == 0) 00109 a_handle = lt_dlopenext(Filename); 00110 00111 if (a_handle == 0) { 00112 if (ErrMsg) 00113 *ErrMsg = std::string("Can't open :") + 00114 (Filename ? Filename : "<current process>") + ": " + lt_dlerror(); 00115 return true; 00116 } 00117 00118 lt_dlmakeresident(a_handle); 00119 00120 OpenedHandles.push_back(a_handle); 00121 return false; 00122 } 00123 00124 void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { 00125 check_ltdl_initialization(); 00126 00127 // First check symbols added via AddSymbol(). 00128 std::map<std::string, void *>::iterator I = g_symbols.find(symbolName); 00129 if (I != g_symbols.end()) 00130 return I->second; 00131 00132 // Now search the libraries. 00133 for (std::vector<lt_dlhandle>::iterator I = OpenedHandles.begin(), 00134 E = OpenedHandles.end(); I != E; ++I) { 00135 lt_ptr ptr = lt_dlsym(*I, symbolName); 00136 if (ptr) 00137 return ptr; 00138 } 00139 00140 // If this is darwin, it has some funky issues, try to solve them here. Some 00141 // important symbols are marked 'private external' which doesn't allow 00142 // SearchForAddressOfSymbol to find them. As such, we special case them here, 00143 // there is only a small handful of them. 00144 #ifdef __APPLE__ 00145 { 00146 #define EXPLICIT_SYMBOL(SYM) \ 00147 extern void *SYM; if (!strcmp(symbolName, #SYM)) return &SYM 00148 EXPLICIT_SYMBOL(__ashldi3); 00149 EXPLICIT_SYMBOL(__ashrdi3); 00150 EXPLICIT_SYMBOL(__cmpdi2); 00151 EXPLICIT_SYMBOL(__divdi3); 00152 EXPLICIT_SYMBOL(__eprintf); 00153 EXPLICIT_SYMBOL(__fixdfdi); 00154 EXPLICIT_SYMBOL(__fixsfdi); 00155 EXPLICIT_SYMBOL(__fixunsdfdi); 00156 EXPLICIT_SYMBOL(__fixunssfdi); 00157 EXPLICIT_SYMBOL(__floatdidf); 00158 EXPLICIT_SYMBOL(__floatdisf); 00159 EXPLICIT_SYMBOL(__lshrdi3); 00160 EXPLICIT_SYMBOL(__moddi3); 00161 EXPLICIT_SYMBOL(__udivdi3); 00162 EXPLICIT_SYMBOL(__umoddi3); 00163 #undef EXPLICIT_SYMBOL 00164 } 00165 #endif 00166 00167 return 0; 00168 } 00169 00170 void *DynamicLibrary::GetAddressOfSymbol(const char *symbolName) { 00171 assert(handle != 0 && "Invalid DynamicLibrary handle"); 00172 return lt_dlsym((lt_dlhandle) handle, symbolName); 00173 } 00174 00175 #endif // LLVM_ON_WIN32 00176 00177 DEFINING_FILE_FOR(SystemDynamicLibrary)