LLVM API Documentation

DynamicLibrary.cpp

Go to the documentation of this file.
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