1218885Sdim//===- Win32/DynamicLibrary.cpp - Win32 DL Implementation -------*- C++ -*-===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file provides the Win32 specific implementation of DynamicLibrary. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14218885Sdim#include "Windows.h" 15218885Sdim 16218885Sdim#ifdef __MINGW32__ 17218885Sdim #include <imagehlp.h> 18218885Sdim#else 19218885Sdim #include <dbghelp.h> 20218885Sdim#endif 21218885Sdim 22218885Sdim#ifdef _MSC_VER 23218885Sdim #include <ntverp.h> 24218885Sdim#endif 25218885Sdim 26218885Sdim#ifdef __MINGW32__ 27218885Sdim #if (HAVE_LIBIMAGEHLP != 1) 28218885Sdim #error "libimagehlp.a should be present" 29218885Sdim #endif 30218885Sdim#else 31218885Sdim #pragma comment(lib, "dbghelp.lib") 32218885Sdim#endif 33218885Sdim 34218885Sdimnamespace llvm { 35218885Sdimusing namespace sys; 36218885Sdim 37218885Sdim//===----------------------------------------------------------------------===// 38218885Sdim//=== WARNING: Implementation here must contain only Win32 specific code 39218885Sdim//=== and must not be UNIX code. 40218885Sdim//===----------------------------------------------------------------------===// 41218885Sdim 42226633Sdimstatic DenseSet<HMODULE> *OpenedHandles; 43218885Sdim 44218885Sdimextern "C" { 45218885Sdim 46221345Sdim static BOOL CALLBACK ELM_Callback(WIN32_ELMCB_PCSTR ModuleName, 47221345Sdim ULONG_PTR ModuleBase, 48218885Sdim ULONG ModuleSize, 49218885Sdim PVOID UserContext) 50218885Sdim { 51218885Sdim // Ignore VC++ runtimes prior to 7.1. Somehow some of them get loaded 52218885Sdim // into the process. 53218885Sdim if (stricmp(ModuleName, "msvci70") != 0 && 54218885Sdim stricmp(ModuleName, "msvcirt") != 0 && 55218885Sdim stricmp(ModuleName, "msvcp50") != 0 && 56218885Sdim stricmp(ModuleName, "msvcp60") != 0 && 57218885Sdim stricmp(ModuleName, "msvcp70") != 0 && 58218885Sdim stricmp(ModuleName, "msvcr70") != 0 && 59218885Sdim#ifndef __MINGW32__ 60218885Sdim // Mingw32 uses msvcrt.dll by default. Don't ignore it. 61218885Sdim // Otherwise, user should be aware, what he's doing :) 62218885Sdim stricmp(ModuleName, "msvcrt") != 0 && 63218885Sdim#endif 64218885Sdim stricmp(ModuleName, "msvcrt20") != 0 && 65218885Sdim stricmp(ModuleName, "msvcrt40") != 0) { 66226633Sdim OpenedHandles->insert((HMODULE)ModuleBase); 67218885Sdim } 68218885Sdim return TRUE; 69218885Sdim } 70218885Sdim} 71218885Sdim 72226633SdimDynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, 73226633Sdim std::string *errMsg) { 74226633Sdim SmartScopedLock<true> lock(getMutex()); 75218885Sdim 76226633Sdim if (!filename) { 77226633Sdim // When no file is specified, enumerate all DLLs and EXEs in the process. 78226633Sdim if (OpenedHandles == 0) 79226633Sdim OpenedHandles = new DenseSet<HMODULE>(); 80218885Sdim 81218885Sdim EnumerateLoadedModules(GetCurrentProcess(), ELM_Callback, 0); 82226633Sdim // Dummy library that represents "search all handles". 83226633Sdim // This is mostly to ensure that the return value still shows up as "valid". 84226633Sdim return DynamicLibrary(&OpenedHandles); 85218885Sdim } 86226633Sdim 87226633Sdim HMODULE a_handle = LoadLibrary(filename); 88218885Sdim 89226633Sdim if (a_handle == 0) { 90226633Sdim MakeErrMsg(errMsg, std::string(filename) + ": Can't open : "); 91226633Sdim return DynamicLibrary(); 92226633Sdim } 93226633Sdim 94226633Sdim if (OpenedHandles == 0) 95226633Sdim OpenedHandles = new DenseSet<HMODULE>(); 96226633Sdim 97226633Sdim // If we've already loaded this library, FreeLibrary() the handle in order to 98226633Sdim // keep the internal refcount at +1. 99226633Sdim if (!OpenedHandles->insert(a_handle).second) 100226633Sdim FreeLibrary(a_handle); 101226633Sdim 102226633Sdim return DynamicLibrary(a_handle); 103218885Sdim} 104218885Sdim 105218885Sdim// Stack probing routines are in the support library (e.g. libgcc), but we don't 106218885Sdim// have dynamic linking on windows. Provide a hook. 107218885Sdim#define EXPLICIT_SYMBOL(SYM) \ 108218885Sdim extern "C" { extern void *SYM; } 109218885Sdim#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO) 110218885Sdim 111218885Sdim#include "explicit_symbols.inc" 112218885Sdim 113218885Sdim#undef EXPLICIT_SYMBOL 114218885Sdim#undef EXPLICIT_SYMBOL2 115218885Sdim 116218885Sdimvoid* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { 117226633Sdim SmartScopedLock<true> Lock(getMutex()); 118226633Sdim 119218885Sdim // First check symbols added via AddSymbol(). 120218885Sdim if (ExplicitSymbols) { 121226633Sdim StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName); 122226633Sdim 123226633Sdim if (i != ExplicitSymbols->end()) 124226633Sdim return i->second; 125218885Sdim } 126218885Sdim 127218885Sdim // Now search the libraries. 128226633Sdim if (OpenedHandles) { 129226633Sdim for (DenseSet<HMODULE>::iterator I = OpenedHandles->begin(), 130226633Sdim E = OpenedHandles->end(); I != E; ++I) { 131226633Sdim FARPROC ptr = GetProcAddress((HMODULE)*I, symbolName); 132226633Sdim if (ptr) { 133226633Sdim return (void *)(intptr_t)ptr; 134226633Sdim } 135218885Sdim } 136218885Sdim } 137218885Sdim 138218885Sdim #define EXPLICIT_SYMBOL(SYM) \ 139218885Sdim if (!strcmp(symbolName, #SYM)) return (void*)&SYM; 140218885Sdim #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) \ 141218885Sdim if (!strcmp(symbolName, #SYMFROM)) return (void*)&SYMTO; 142218885Sdim 143218885Sdim { 144218885Sdim #include "explicit_symbols.inc" 145218885Sdim } 146218885Sdim 147218885Sdim #undef EXPLICIT_SYMBOL 148218885Sdim #undef EXPLICIT_SYMBOL2 149218885Sdim 150218885Sdim return 0; 151218885Sdim} 152218885Sdim 153226633Sdim 154226633Sdimvoid *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { 155226633Sdim if (!isValid()) 156226633Sdim return NULL; 157226633Sdim if (Data == &OpenedHandles) 158226633Sdim return SearchForAddressOfSymbol(symbolName); 159226633Sdim return (void *)(intptr_t)GetProcAddress((HMODULE)Data, symbolName); 160218885Sdim} 161226633Sdim 162226633Sdim 163226633Sdim} 164