LLVM API Documentation

DynamicLibrary.inc
Go to the documentation of this file.
00001 //===- Win32/DynamicLibrary.cpp - Win32 DL Implementation -------*- 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 provides the Win32 specific implementation of DynamicLibrary.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "WindowsSupport.h"
00015 
00016 #ifdef __MINGW32__
00017  #include <imagehlp.h>
00018 #else
00019  #include <dbghelp.h>
00020 #endif
00021 
00022 #ifdef _MSC_VER
00023  #include <ntverp.h>
00024 #endif
00025 
00026 #ifdef __MINGW32__
00027  #if (HAVE_LIBIMAGEHLP != 1)
00028   #error "libimagehlp.a should be present"
00029  #endif
00030 #else
00031  #pragma comment(lib, "dbghelp.lib")
00032 #endif
00033 
00034 namespace llvm {
00035 using namespace sys;
00036 
00037 //===----------------------------------------------------------------------===//
00038 //=== WARNING: Implementation here must contain only Win32 specific code
00039 //===          and must not be UNIX code.
00040 //===----------------------------------------------------------------------===//
00041 
00042 static DenseSet<HMODULE> *OpenedHandles;
00043 
00044 extern "C" {
00045 
00046   static BOOL CALLBACK ELM_Callback(WIN32_ELMCB_PCSTR ModuleName,
00047                                     ULONG_PTR ModuleBase,
00048                                     ULONG ModuleSize,
00049                                     PVOID UserContext)
00050   {
00051     // Ignore VC++ runtimes prior to 7.1.  Somehow some of them get loaded
00052     // into the process.
00053     if (stricmp(ModuleName, "msvci70") != 0 &&
00054         stricmp(ModuleName, "msvcirt") != 0 &&
00055         stricmp(ModuleName, "msvcp50") != 0 &&
00056         stricmp(ModuleName, "msvcp60") != 0 &&
00057         stricmp(ModuleName, "msvcp70") != 0 &&
00058         stricmp(ModuleName, "msvcr70") != 0 &&
00059 #ifndef __MINGW32__
00060         // Mingw32 uses msvcrt.dll by default. Don't ignore it.
00061         // Otherwise the user should be aware what they are doing.
00062         stricmp(ModuleName, "msvcrt") != 0 &&
00063 #endif
00064         stricmp(ModuleName, "msvcrt20") != 0 &&
00065         stricmp(ModuleName, "msvcrt40") != 0) {
00066       OpenedHandles->insert((HMODULE)ModuleBase);
00067     }
00068     return TRUE;
00069   }
00070 }
00071 
00072 DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
00073                                                    std::string *errMsg) {
00074   SmartScopedLock<true> lock(*SymbolsMutex);
00075 
00076   if (!filename) {
00077     // When no file is specified, enumerate all DLLs and EXEs in the process.
00078     if (OpenedHandles == 0)
00079       OpenedHandles = new DenseSet<HMODULE>();
00080 
00081     EnumerateLoadedModules(GetCurrentProcess(), ELM_Callback, 0);
00082     // Dummy library that represents "search all handles".
00083     // This is mostly to ensure that the return value still shows up as "valid".
00084     return DynamicLibrary(&OpenedHandles);
00085   }
00086 
00087   SmallVector<wchar_t, MAX_PATH> filenameUnicode;
00088   if (std::error_code ec = windows::UTF8ToUTF16(filename, filenameUnicode)) {
00089     SetLastError(ec.value());
00090     MakeErrMsg(errMsg, std::string(filename) + ": Can't convert to UTF-16: ");
00091     return DynamicLibrary();
00092   }
00093   
00094   HMODULE a_handle = LoadLibraryW(filenameUnicode.data());
00095 
00096   if (a_handle == 0) {
00097     MakeErrMsg(errMsg, std::string(filename) + ": Can't open : ");
00098     return DynamicLibrary();
00099   }
00100 
00101   if (OpenedHandles == 0)
00102     OpenedHandles = new DenseSet<HMODULE>();
00103 
00104   // If we've already loaded this library, FreeLibrary() the handle in order to
00105   // keep the internal refcount at +1.
00106   if (!OpenedHandles->insert(a_handle).second)
00107     FreeLibrary(a_handle);
00108 
00109   return DynamicLibrary(a_handle);
00110 }
00111 
00112 // Stack probing routines are in the support library (e.g. libgcc), but we don't
00113 // have dynamic linking on windows. Provide a hook.
00114 #define EXPLICIT_SYMBOL(SYM)                    \
00115   extern "C" { extern void *SYM; }
00116 #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO)
00117 
00118 #include "explicit_symbols.inc"
00119 
00120 #undef EXPLICIT_SYMBOL
00121 #undef EXPLICIT_SYMBOL2
00122 
00123 void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
00124   SmartScopedLock<true> Lock(*SymbolsMutex);
00125 
00126   // First check symbols added via AddSymbol().
00127   if (ExplicitSymbols.isConstructed()) {
00128     StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
00129 
00130     if (i != ExplicitSymbols->end())
00131       return i->second;
00132   }
00133 
00134   // Now search the libraries.
00135   if (OpenedHandles) {
00136     for (DenseSet<HMODULE>::iterator I = OpenedHandles->begin(),
00137          E = OpenedHandles->end(); I != E; ++I) {
00138       FARPROC ptr = GetProcAddress((HMODULE)*I, symbolName);
00139       if (ptr) {
00140         return (void *)(intptr_t)ptr;
00141       }
00142     }
00143   }
00144 
00145   #define EXPLICIT_SYMBOL(SYM)                    \
00146     if (!strcmp(symbolName, #SYM)) return (void*)&SYM;
00147   #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO)        \
00148     if (!strcmp(symbolName, #SYMFROM)) return (void*)&SYMTO;
00149 
00150   {
00151     #include "explicit_symbols.inc"
00152   }
00153 
00154   #undef EXPLICIT_SYMBOL
00155   #undef EXPLICIT_SYMBOL2
00156 
00157   return 0;
00158 }
00159 
00160 
00161 void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
00162   if (!isValid())
00163     return NULL;
00164   if (Data == &OpenedHandles)
00165     return SearchForAddressOfSymbol(symbolName);
00166   return (void *)(intptr_t)GetProcAddress((HMODULE)Data, symbolName);
00167 }
00168 
00169 
00170 }