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