[compiler-rt] r217679 - [ASan/Win] Fix PR20918 -- SEH handler doesn't work with the MD runtime
Timur Iskhodzhanov
timurrrr at google.com
Fri Sep 12 07:01:31 PDT 2014
Author: timurrrr
Date: Fri Sep 12 09:01:30 2014
New Revision: 217679
URL: http://llvm.org/viewvc/llvm-project?rev=217679&view=rev
Log:
[ASan/Win] Fix PR20918 -- SEH handler doesn't work with the MD runtime
Added:
compiler-rt/trunk/test/asan/TestCases/Windows/dll_null_deref.cc
compiler-rt/trunk/test/asan/TestCases/Windows/null_deref_multiple_dlls.cc
Modified:
compiler-rt/trunk/lib/asan/asan_win.cc
compiler-rt/trunk/lib/asan/asan_win_dynamic_runtime_thunk.cc
Modified: compiler-rt/trunk/lib/asan/asan_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_win.cc?rev=217679&r1=217678&r2=217679&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_win.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_win.cc Fri Sep 12 09:01:30 2014
@@ -89,7 +89,7 @@ void AsanOnSIGSEGV(int, void *siginfo, v
static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
-long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
+static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
CONTEXT *context = info->ContextRecord;
uptr pc = (uptr)exception_record->ExceptionAddress;
@@ -114,16 +114,39 @@ long WINAPI SEHHandler(EXCEPTION_POINTER
return default_seh_handler(info);
}
-int SetSEHFilter() {
- default_seh_handler = SetUnhandledExceptionFilter(SEHHandler);
+// We want to install our own exception handler (EH) to print helpful reports
+// on access violations and whatnot. Unfortunately, the CRT initializers assume
+// they are run before any user code and drop any previously-installed EHs on
+// the floor, so we can't install our handler inside __asan_init.
+// (See crt0dat.c in the CRT sources for the details)
+//
+// Things get even more complicated with the dynamic runtime, as it finishes its
+// initialization before the .exe module CRT begins to initialize.
+//
+// For the static runtime (-MT), it's enough to put a callback to
+// __asan_set_seh_filter in the last section for C initializers.
+//
+// For the dynamic runtime (-MD), we want link the same
+// asan_dynamic_runtime_thunk.lib to all the modules, thus __asan_set_seh_filter
+// will be called for each instrumented module. This ensures that at least one
+// __asan_set_seh_filter call happens after the .exe module CRT is initialized.
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+int __asan_set_seh_filter() {
+ // We should only store the previous handler if it's not our own handler in
+ // order to avoid loops in the EH chain.
+ auto prev_seh_handler = SetUnhandledExceptionFilter(SEHHandler);
+ if (prev_seh_handler != &SEHHandler)
+ default_seh_handler = prev_seh_handler;
return 0;
}
-// Put a pointer to SetSEHFilter at the end of the global list
-// of C initializers, after the default handler is set by the CRT.
-// See crt0dat.c in the CRT sources for the details.
+#if !ASAN_DYNAMIC
+// Put a pointer to __asan_set_seh_filter at the end of the global list
+// of C initializers, after the default EH is set by the CRT.
#pragma section(".CRT$XIZ", long, read) // NOLINT
-__declspec(allocate(".CRT$XIZ")) int (*__intercept_seh)() = SetSEHFilter;
+static __declspec(allocate(".CRT$XIZ"))
+ int (*__intercept_seh)() = __asan_set_seh_filter;
+#endif
} // namespace __asan
Modified: compiler-rt/trunk/lib/asan/asan_win_dynamic_runtime_thunk.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_win_dynamic_runtime_thunk.cc?rev=217679&r1=217678&r2=217679&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_win_dynamic_runtime_thunk.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_win_dynamic_runtime_thunk.cc Fri Sep 12 09:01:30 2014
@@ -15,7 +15,7 @@
//
// This includes:
// - forwarding the detect_stack_use_after_return runtime option
-// - FIXME: installing a custom SEH handler (PR20918)
+// - installing a custom SEH handler
//
//===----------------------------------------------------------------------===//
@@ -24,6 +24,7 @@
// simplifies the build procedure.
#ifdef ASAN_DYNAMIC_RUNTIME_THUNK
extern "C" {
+__declspec(dllimport) int __asan_set_seh_filter();
__declspec(dllimport) int __asan_should_detect_stack_use_after_return();
// Define a copy of __asan_option_detect_stack_use_after_return that should be
@@ -38,5 +39,14 @@ __declspec(dllimport) int __asan_should_
// constant after initialization anyways.
int __asan_option_detect_stack_use_after_return =
__asan_should_detect_stack_use_after_return();
+
+// Set the ASan-specific SEH handler at the end of CRT initialization of each
+// module (see asan_win.cc for the details).
+//
+// Unfortunately, putting a pointer to __asan_set_seh_filter into
+// __asan_intercept_seh gets optimized out, so we have to use an extra function.
+static int SetSEHFilter() { return __asan_set_seh_filter(); }
+#pragma section(".CRT$XIZ", long, read) // NOLINT
+__declspec(allocate(".CRT$XIZ")) int (*__asan_seh_interceptor)() = SetSEHFilter;
}
#endif // ASAN_DYNAMIC_RUNTIME_THUNK
Added: compiler-rt/trunk/test/asan/TestCases/Windows/dll_null_deref.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Windows/dll_null_deref.cc?rev=217679&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Windows/dll_null_deref.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Windows/dll_null_deref.cc Fri Sep 12 09:01:30 2014
@@ -0,0 +1,18 @@
+// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t
+// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll
+// RUN: not %run %t %t.dll 2>&1 | FileCheck %s
+
+__attribute__((noinline))
+static void NullDeref(int *ptr) {
+ // CHECK: ERROR: AddressSanitizer: access-violation on unknown address
+ // CHECK: {{0x0*000.. .*pc 0x.*}}
+ ptr[10]++; // BOOM
+}
+
+extern "C" __declspec(dllexport)
+int test_function() {
+ NullDeref((int*)0);
+ // CHECK: {{ #1 0x.* in test_function .*\dll_null_deref.cc:}}[[@LINE-1]]
+ // CHECK: AddressSanitizer can not provide additional info.
+ return 0;
+}
Added: compiler-rt/trunk/test/asan/TestCases/Windows/null_deref_multiple_dlls.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Windows/null_deref_multiple_dlls.cc?rev=217679&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Windows/null_deref_multiple_dlls.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Windows/null_deref_multiple_dlls.cc Fri Sep 12 09:01:30 2014
@@ -0,0 +1,40 @@
+// Make sure everything works even if the main module doesn't have any stack
+// variables, thus doesn't explicitly reference any symbol exported by the
+// runtime thunk.
+//
+// RUN: %clang_cl_asan -LD -O0 -DDLL1 %s -Fe%t1.dll
+// RUN: %clang_cl_asan -LD -O0 -DDLL2 %s -Fe%t2.dll
+// RUN: %clang_cl_asan -O0 -DEXE %s %t1.lib %t2.lib -Fe%t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+#include <malloc.h>
+#include <string.h>
+
+extern "C" {
+#if defined(EXE)
+__declspec(dllimport) void foo1();
+__declspec(dllimport) void foo2();
+
+int main() {
+ foo1();
+ foo2();
+}
+#elif defined(DLL1)
+__declspec(dllexport) void foo1() {}
+#elif defined(DLL2)
+__attribute__((noinline))
+static void NullDeref(int *ptr) {
+ // CHECK: ERROR: AddressSanitizer: access-violation on unknown address
+ // CHECK: {{0x0*000.. .*pc 0x.*}}
+ ptr[10]++; // BOOM
+}
+
+__declspec(dllexport) void foo2() {
+ NullDeref((int*)0);
+ // CHECK: {{ #1 0x.* in foo2.*null_deref_multiple_dlls.cc:}}[[@LINE-1]]
+ // CHECK: AddressSanitizer can not provide additional info.
+}
+#else
+# error oops!
+#endif
+}
More information about the llvm-commits
mailing list