[compiler-rt] r286848 - [asan/win] Delay load dbghelp.dll to delay ucrtbase.dll initialization

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 14 09:37:50 PST 2016


Author: rnk
Date: Mon Nov 14 11:37:50 2016
New Revision: 286848

URL: http://llvm.org/viewvc/llvm-project?rev=286848&view=rev
Log:
[asan/win] Delay load dbghelp.dll to delay ucrtbase.dll initialization

Summary:
ASan needs to initialize before ucrtbase.dll so that it can intercept
all of its heap allocations. New versions of dbghelp.dll depend on
ucrtbase.dll, which means both of those DLLs will initialize before the
dynamic ASan runtime. By lazily loading dbghelp.dll with LoadLibrary, we
avoid the issue.

Eventually, I would like to remove our dbghelp.dll dependency in favor
of always using llvm-symbolizer.exe, but this seems like an acceptable
interim solution.

Fixes PR30903

Reviewers: etienneb

Subscribers: kubabrecka, mgorny, llvm-commits

Differential Revision: https://reviews.llvm.org/D26473

Added:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_dbghelp.h
    compiler-rt/trunk/test/asan/TestCases/Windows/delay_dbghelp.cc
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
    compiler-rt/trunk/test/CMakeLists.txt

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_dbghelp.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_dbghelp.h?rev=286848&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_dbghelp.h (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_dbghelp.h Mon Nov 14 11:37:50 2016
@@ -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 <windows.h>
+#include <dbghelp.h>
+
+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

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc?rev=286848&r1=286847&r2=286848&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc Mon Nov 14 11:37:50 2016
@@ -14,15 +14,24 @@
 
 #include "sanitizer_platform.h"
 #if SANITIZER_WINDOWS
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <dbghelp.h>
-#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 @@ bool TrySymInitialize() {
 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<decltype(::name) *>(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

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc?rev=286848&r1=286847&r2=286848&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc Mon Nov 14 11:37:50 2016
@@ -18,12 +18,12 @@
 #define WIN32_LEAN_AND_MEAN
 #define NOGDI
 #include <windows.h>
-#include <dbghelp.h>
 #include <io.h>
 #include <psapi.h>
 #include <stdlib.h>
 
 #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 @@ void BufferedStackTrace::SlowUnwindStack
   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;
   }

Modified: compiler-rt/trunk/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/CMakeLists.txt?rev=286848&r1=286847&r2=286848&view=diff
==============================================================================
--- compiler-rt/trunk/test/CMakeLists.txt (original)
+++ compiler-rt/trunk/test/CMakeLists.txt Mon Nov 14 11:37:50 2016
@@ -23,7 +23,7 @@ if(NOT ANDROID)
     # 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()

Added: compiler-rt/trunk/test/asan/TestCases/Windows/delay_dbghelp.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Windows/delay_dbghelp.cc?rev=286848&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Windows/delay_dbghelp.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Windows/delay_dbghelp.cc Mon Nov 14 11:37:50 2016
@@ -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");
+}




More information about the llvm-commits mailing list