Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_dbghelp.h =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_dbghelp.h +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_dbghelp.h @@ -0,0 +1,42 @@ +//===-- sanitizer_dbghelp.h ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Wrappers for lazy loaded dbghelp.dll. Provides function pointers and a +// callback to initialize them. +// +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_SYMBOLIZER_WIN_H +#define SANITIZER_SYMBOLIZER_WIN_H + +#if !SANITIZER_WINDOWS +#error "sanitizer_dbghelp.h is a Windows-only header" +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#include + +namespace __sanitizer { + +extern decltype(::StackWalk64) *StackWalk64; +extern decltype(::SymCleanup) *SymCleanup; +extern decltype(::SymFromAddr) *SymFromAddr; +extern decltype(::SymFunctionTableAccess64) *SymFunctionTableAccess64; +extern decltype(::SymGetLineFromAddr64) *SymGetLineFromAddr64; +extern decltype(::SymGetModuleBase64) *SymGetModuleBase64; +extern decltype(::SymGetSearchPathW) *SymGetSearchPathW; +extern decltype(::SymInitialize) *SymInitialize; +extern decltype(::SymSetOptions) *SymSetOptions; +extern decltype(::SymSetSearchPathW) *SymSetSearchPathW; +extern decltype(::UnDecorateSymbolName) *UnDecorateSymbolName; + +} // namespace __sanitizer + +#endif // SANITIZER_SYMBOLIZER_WIN_H Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc @@ -14,15 +14,24 @@ #include "sanitizer_platform.h" #if SANITIZER_WINDOWS -#define WIN32_LEAN_AND_MEAN -#include -#include -#pragma comment(lib, "dbghelp.lib") +#include "sanitizer_dbghelp.h" #include "sanitizer_symbolizer_internal.h" namespace __sanitizer { +decltype(::StackWalk64) *StackWalk64; +decltype(::SymCleanup) *SymCleanup; +decltype(::SymFromAddr) *SymFromAddr; +decltype(::SymFunctionTableAccess64) *SymFunctionTableAccess64; +decltype(::SymGetLineFromAddr64) *SymGetLineFromAddr64; +decltype(::SymGetModuleBase64) *SymGetModuleBase64; +decltype(::SymGetSearchPathW) *SymGetSearchPathW; +decltype(::SymInitialize) *SymInitialize; +decltype(::SymSetOptions) *SymSetOptions; +decltype(::SymSetSearchPathW) *SymSetSearchPathW; +decltype(::UnDecorateSymbolName) *UnDecorateSymbolName; + namespace { class WinSymbolizerTool : public SymbolizerTool { @@ -50,6 +59,29 @@ void InitializeDbgHelpIfNeeded() { if (is_dbghelp_initialized) return; + + HMODULE dbghelp = LoadLibraryA("dbghelp.dll"); + CHECK(dbghelp && "failed to load dbghelp.dll"); + +#define DBGHELP_IMPORT(name) \ + do { \ + name = \ + reinterpret_cast(GetProcAddress(dbghelp, #name)); \ + CHECK(name != nullptr); \ + } while (0) + DBGHELP_IMPORT(StackWalk64); + DBGHELP_IMPORT(SymCleanup); + DBGHELP_IMPORT(SymFromAddr); + DBGHELP_IMPORT(SymFunctionTableAccess64); + DBGHELP_IMPORT(SymGetLineFromAddr64); + DBGHELP_IMPORT(SymGetModuleBase64); + DBGHELP_IMPORT(SymGetSearchPathW); + DBGHELP_IMPORT(SymInitialize); + DBGHELP_IMPORT(SymSetOptions); + DBGHELP_IMPORT(SymSetSearchPathW); + DBGHELP_IMPORT(UnDecorateSymbolName); +#undef DBGHELP_IMPORT + if (!TrySymInitialize()) { // OK, maybe the client app has called SymInitialize already. // That's a bit unfortunate for us as all the DbgHelp functions are Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc @@ -18,12 +18,12 @@ #define WIN32_LEAN_AND_MEAN #define NOGDI #include -#include #include #include #include #include "sanitizer_common.h" +#include "sanitizer_dbghelp.h" #include "sanitizer_libc.h" #include "sanitizer_mutex.h" #include "sanitizer_placement_new.h" @@ -781,8 +781,8 @@ stack_frame.AddrFrame.Mode = AddrModeFlat; stack_frame.AddrStack.Mode = AddrModeFlat; while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(), - &stack_frame, &ctx, NULL, &SymFunctionTableAccess64, - &SymGetModuleBase64, NULL) && + &stack_frame, &ctx, NULL, SymFunctionTableAccess64, + SymGetModuleBase64, NULL) && size < Min(max_depth, kStackTraceMax)) { trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset; } Index: compiler-rt/trunk/test/CMakeLists.txt =================================================================== --- compiler-rt/trunk/test/CMakeLists.txt +++ compiler-rt/trunk/test/CMakeLists.txt @@ -23,7 +23,7 @@ # Use LLVM utils and Clang from the same build tree. list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS clang clang-headers FileCheck count not llvm-config llvm-nm llvm-objdump - llvm-symbolizer compiler-rt-headers sancov) + llvm-readobj llvm-symbolizer compiler-rt-headers sancov) if (COMPILER_RT_HAS_PROFILE) list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS profile) endif() Index: compiler-rt/trunk/test/asan/TestCases/Windows/delay_dbghelp.cc =================================================================== --- compiler-rt/trunk/test/asan/TestCases/Windows/delay_dbghelp.cc +++ compiler-rt/trunk/test/asan/TestCases/Windows/delay_dbghelp.cc @@ -0,0 +1,18 @@ +// Build an executable with ASan, then extract the DLLs that it depends on. +// RUN: %clang_cl_asan %s -Fe%t.exe +// RUN: llvm-readobj -coff-imports %t.exe | grep Name: | sed -e 's/ *Name: *//' > %t +// +// Make sure the binary doesn't depend on dbghelp directly. +// RUN: not grep dbghelp.dll %t +// +// Make sure any clang_rt DLLs it depends on don't depend on dbghelp. In the +// static build, there won't be any clang_rt DLLs. +// RUN: not grep cl""ang_rt %t || \ +// RUN: grep cl""ang_rt %t | xargs which | \ +// RUN: xargs llvm-readobj -coff-imports | not grep dbghelp.dll %t + +extern "C" int puts(const char *); + +int main() { + puts("main"); +}