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 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 //===----------------------------------------------------------------------===//
00013 
00014 #include "llvm/System/DynamicLibrary.h"
00015 #include "llvm/Config/config.h"
00016 #include <cstdio>
00017 #include <cstring>
00018 #include <map>
00019 
00020 // Collection of symbol name/value pairs to be searched prior to any libraries.
00021 std::map<std::string, void *> &g_symbols() {
00022   static std::map<std::string, void *> symbols;
00023   return symbols;
00024 }
00025 
00026 void llvm::sys::DynamicLibrary::AddSymbol(const char* symbolName,
00027                                           void *symbolValue) {
00028   g_symbols()[symbolName] = symbolValue;
00029 }
00030 
00031 // It is not possible to use ltdl.c on VC++ builds as the terms of its LGPL
00032 // license and special exception would cause all of LLVM to be placed under
00033 // the LGPL.  This is because the exception applies only when libtool is
00034 // used, and obviously libtool is not used with Visual Studio.  An entirely
00035 // separate implementation is provided in win32/DynamicLibrary.cpp.
00036 
00037 #ifdef LLVM_ON_WIN32
00038 
00039 #include "Win32/DynamicLibrary.inc"
00040 
00041 #else
00042 
00043 //#include "ltdl.h"
00044 #include <dlfcn.h>
00045 #include <cassert>
00046 using namespace llvm;
00047 using namespace llvm::sys;
00048 
00049 //===----------------------------------------------------------------------===//
00050 //=== WARNING: Implementation here must contain only TRULY operating system
00051 //===          independent code.
00052 //===----------------------------------------------------------------------===//
00053 
00054 //static std::vector<lt_dlhandle> OpenedHandles;
00055 static std::vector<void *> OpenedHandles;
00056 
00057 DynamicLibrary::DynamicLibrary() {}
00058 
00059 DynamicLibrary::~DynamicLibrary() {
00060   while(!OpenedHandles.empty()) {
00061     void *H = OpenedHandles.back();   OpenedHandles.pop_back(); 
00062     dlclose(H);
00063   }
00064 }
00065 
00066 bool DynamicLibrary::LoadLibraryPermanently(const char *Filename,
00067                                             std::string *ErrMsg) {
00068   void *H = dlopen(Filename, RTLD_LAZY|RTLD_GLOBAL);
00069   if (H == 0) {
00070     if (ErrMsg)
00071       *ErrMsg = dlerror();
00072     return true;
00073   }
00074   OpenedHandles.push_back(H);
00075   return false;
00076 }
00077 
00078 void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
00079   //  check_ltdl_initialization();
00080 
00081   // First check symbols added via AddSymbol().
00082   std::map<std::string, void *>::iterator I = g_symbols().find(symbolName);
00083   if (I != g_symbols().end())
00084     return I->second;
00085 
00086   // Now search the libraries.
00087   for (std::vector<void *>::iterator I = OpenedHandles.begin(),
00088        E = OpenedHandles.end(); I != E; ++I) {
00089     //lt_ptr ptr = lt_dlsym(*I, symbolName);
00090     void *ptr = dlsym(*I, symbolName);
00091     if (ptr)
00092       return ptr;
00093   }
00094 
00095 #define EXPLICIT_SYMBOL(SYM) \
00096    extern void *SYM; if (!strcmp(symbolName, #SYM)) return &SYM
00097 
00098   // If this is darwin, it has some funky issues, try to solve them here.  Some
00099   // important symbols are marked 'private external' which doesn't allow
00100   // SearchForAddressOfSymbol to find them.  As such, we special case them here,
00101   // there is only a small handful of them.
00102 
00103 #ifdef __APPLE__
00104   {
00105     EXPLICIT_SYMBOL(__ashldi3);
00106     EXPLICIT_SYMBOL(__ashrdi3);
00107     EXPLICIT_SYMBOL(__cmpdi2);
00108     EXPLICIT_SYMBOL(__divdi3);
00109     EXPLICIT_SYMBOL(__eprintf);
00110     EXPLICIT_SYMBOL(__fixdfdi);
00111     EXPLICIT_SYMBOL(__fixsfdi);
00112     EXPLICIT_SYMBOL(__fixunsdfdi);
00113     EXPLICIT_SYMBOL(__fixunssfdi);
00114     EXPLICIT_SYMBOL(__floatdidf);
00115     EXPLICIT_SYMBOL(__floatdisf);
00116     EXPLICIT_SYMBOL(__lshrdi3);
00117     EXPLICIT_SYMBOL(__moddi3);
00118     EXPLICIT_SYMBOL(__udivdi3);
00119     EXPLICIT_SYMBOL(__umoddi3);
00120   }
00121 #endif
00122 
00123 #ifdef __CYGWIN__
00124   {
00125     EXPLICIT_SYMBOL(_alloca);
00126     EXPLICIT_SYMBOL(__main);
00127   }
00128 #endif
00129 
00130 #undef EXPLICIT_SYMBOL
00131 
00132 // This macro returns the address of a well-known, explicit symbol
00133 #define EXPLICIT_SYMBOL(SYM) \
00134    if (!strcmp(symbolName, #SYM)) return &SYM
00135 
00136 // On linux we have a weird situation. The stderr/out/in symbols are both
00137 // macros and global variables because of standards requirements. So, we 
00138 // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
00139 #if defined(__linux__)
00140   {
00141     EXPLICIT_SYMBOL(stderr);
00142     EXPLICIT_SYMBOL(stdout);
00143     EXPLICIT_SYMBOL(stdin);
00144   }
00145 #else
00146   // For everything else, we want to check to make sure the symbol isn't defined
00147   // as a macro before using EXPLICIT_SYMBOL.
00148   {
00149 #ifndef stdin
00150     EXPLICIT_SYMBOL(stdin);
00151 #endif
00152 #ifndef stdout
00153     EXPLICIT_SYMBOL(stdout);
00154 #endif
00155 #ifndef stderr
00156     EXPLICIT_SYMBOL(stderr);
00157 #endif
00158   }
00159 #endif
00160 #undef EXPLICIT_SYMBOL
00161 
00162   return 0;
00163 }
00164 
00165 #endif // LLVM_ON_WIN32