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