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,
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)