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 // FIXME: This file leaks ExplicitSymbols and OpenedHandles!
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #include "llvm/ADT/StringMap.h"
00017 #include "llvm/ADT/DenseSet.h"
00018 #include "llvm/Support/DynamicLibrary.h"
00019 #include "llvm/Support/Mutex.h"
00020 #include "llvm/Config/config.h"
00021 #include <cstdio>
00022 #include <cstring>
00023 
00024 // Collection of symbol name/value pairs to be searched prior to any libraries.
00025 static llvm::StringMap<void *> *ExplicitSymbols = 0;
00026 
00027 namespace {
00028 
00029 struct ExplicitSymbolsDeleter {
00030   ~ExplicitSymbolsDeleter() {
00031     delete ExplicitSymbols;
00032   }
00033 };
00034 
00035 }
00036 
00037 static ExplicitSymbolsDeleter Dummy;
00038 
00039 
00040 static llvm::sys::SmartMutex<true>& getMutex() {
00041   static llvm::sys::SmartMutex<true> HandlesMutex;
00042   return HandlesMutex;
00043 }
00044 
00045 void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName,
00046                                           void *symbolValue) {
00047   SmartScopedLock<true> lock(getMutex());
00048   if (ExplicitSymbols == 0)
00049     ExplicitSymbols = new llvm::StringMap<void*>();
00050   (*ExplicitSymbols)[symbolName] = symbolValue;
00051 }
00052 
00053 char llvm::sys::DynamicLibrary::Invalid = 0;
00054 
00055 #ifdef LLVM_ON_WIN32
00056 
00057 #include "Windows/DynamicLibrary.inc"
00058 
00059 #else
00060 
00061 #if HAVE_DLFCN_H
00062 #include <dlfcn.h>
00063 using namespace llvm;
00064 using namespace llvm::sys;
00065 
00066 //===----------------------------------------------------------------------===//
00067 //=== WARNING: Implementation here must contain only TRULY operating system
00068 //===          independent code.
00069 //===----------------------------------------------------------------------===//
00070 
00071 static DenseSet<void *> *OpenedHandles = 0;
00072 
00073 DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
00074                                                    std::string *errMsg) {
00075   SmartScopedLock<true> lock(getMutex());
00076 
00077   void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL);
00078   if (handle == 0) {
00079     if (errMsg) *errMsg = dlerror();
00080     return DynamicLibrary();
00081   }
00082 
00083 #ifdef __CYGWIN__
00084   // Cygwin searches symbols only in the main
00085   // with the handle of dlopen(NULL, RTLD_GLOBAL).
00086   if (filename == NULL)
00087     handle = RTLD_DEFAULT;
00088 #endif
00089 
00090   if (OpenedHandles == 0)
00091     OpenedHandles = new DenseSet<void *>();
00092 
00093   // If we've already loaded this library, dlclose() the handle in order to
00094   // keep the internal refcount at +1.
00095   if (!OpenedHandles->insert(handle).second)
00096     dlclose(handle);
00097 
00098   return DynamicLibrary(handle);
00099 }
00100 
00101 void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
00102   if (!isValid())
00103     return NULL;
00104   return dlsym(Data, symbolName);
00105 }
00106 
00107 #else
00108 
00109 using namespace llvm;
00110 using namespace llvm::sys;
00111 
00112 DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
00113                                                    std::string *errMsg) {
00114   if (errMsg) *errMsg = "dlopen() not supported on this platform";
00115   return DynamicLibrary();
00116 }
00117 
00118 void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
00119   return NULL;
00120 }
00121 
00122 #endif
00123 
00124 namespace llvm {
00125 void *SearchForAddressOfSpecialSymbol(const char* symbolName);
00126 }
00127 
00128 void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) {
00129   SmartScopedLock<true> Lock(getMutex());
00130 
00131   // First check symbols added via AddSymbol().
00132   if (ExplicitSymbols) {
00133     StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
00134 
00135     if (i != ExplicitSymbols->end())
00136       return i->second;
00137   }
00138 
00139 #if HAVE_DLFCN_H
00140   // Now search the libraries.
00141   if (OpenedHandles) {
00142     for (DenseSet<void *>::iterator I = OpenedHandles->begin(),
00143          E = OpenedHandles->end(); I != E; ++I) {
00144       //lt_ptr ptr = lt_dlsym(*I, symbolName);
00145       void *ptr = dlsym(*I, symbolName);
00146       if (ptr) {
00147         return ptr;
00148       }
00149     }
00150   }
00151 #endif
00152 
00153   if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName))
00154     return Result;
00155 
00156 // This macro returns the address of a well-known, explicit symbol
00157 #define EXPLICIT_SYMBOL(SYM) \
00158    if (!strcmp(symbolName, #SYM)) return &SYM
00159 
00160 // On linux we have a weird situation. The stderr/out/in symbols are both
00161 // macros and global variables because of standards requirements. So, we
00162 // boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
00163 #if defined(__linux__)
00164   {
00165     EXPLICIT_SYMBOL(stderr);
00166     EXPLICIT_SYMBOL(stdout);
00167     EXPLICIT_SYMBOL(stdin);
00168   }
00169 #else
00170   // For everything else, we want to check to make sure the symbol isn't defined
00171   // as a macro before using EXPLICIT_SYMBOL.
00172   {
00173 #ifndef stdin
00174     EXPLICIT_SYMBOL(stdin);
00175 #endif
00176 #ifndef stdout
00177     EXPLICIT_SYMBOL(stdout);
00178 #endif
00179 #ifndef stderr
00180     EXPLICIT_SYMBOL(stderr);
00181 #endif
00182   }
00183 #endif
00184 #undef EXPLICIT_SYMBOL
00185 
00186   return 0;
00187 }
00188 
00189 #endif // LLVM_ON_WIN32