[compiler-rt] r293957 - [asan] Intercept SetUnhandledExceptionFilter.

Marcos Pividori via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 2 15:02:05 PST 2017


Author: mpividori
Date: Thu Feb  2 17:02:04 2017
New Revision: 293957

URL: http://llvm.org/viewvc/llvm-project?rev=293957&view=rev
Log:
[asan] Intercept SetUnhandledExceptionFilter.

In this diff I update the code for asan on Windows, so we can intercept
SetUnhandledExceptionFilter and catch some exceptions depending on the result of
IsHandledDeadlyException() (which depends on asan flags).

This way we have the same behavior on Windows and Posix systems.
On Posix, we intercept signal and sigaction, so user's code can only register
signal handlers for signals that are not handled by asan.
After this diff, the same happens on Windows, user's code can only register
exception handlers for exceptions that are not handled by asan.

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

Modified:
    compiler-rt/trunk/lib/asan/asan_win.cc
    compiler-rt/trunk/test/asan/TestCases/Windows/dll_host.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=293957&r1=293956&r2=293957&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_win.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_win.cc Thu Feb  2 17:02:04 2017
@@ -47,6 +47,47 @@ uptr __asan_get_shadow_memory_dynamic_ad
 }  // extern "C"
 
 // ---------------------- Windows-specific interceptors ---------------- {{{
+static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
+static LPTOP_LEVEL_EXCEPTION_FILTER user_seh_handler;
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+long __asan_unhandled_exception_filter(EXCEPTION_POINTERS *info) {
+  EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
+  CONTEXT *context = info->ContextRecord;
+
+  // FIXME: Handle EXCEPTION_STACK_OVERFLOW here.
+
+  SignalContext sig = SignalContext::Create(exception_record, context);
+  ReportDeadlySignal(exception_record->ExceptionCode, sig);
+  UNREACHABLE("returned from reporting deadly signal");
+}
+
+// Wrapper SEH Handler. If the exception should be handled by asan, we call
+// __asan_unhandled_exception_filter, otherwise, we execute the user provided
+// exception handler or the default.
+static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
+  DWORD exception_code = info->ExceptionRecord->ExceptionCode;
+  if (__sanitizer::IsHandledDeadlyException(exception_code))
+    return __asan_unhandled_exception_filter(info);
+  if (user_seh_handler)
+    return user_seh_handler(info);
+  // Bubble out to the default exception filter.
+  if (default_seh_handler)
+    return default_seh_handler(info);
+  return EXCEPTION_CONTINUE_SEARCH;
+}
+
+INTERCEPTOR_WINAPI(LPTOP_LEVEL_EXCEPTION_FILTER, SetUnhandledExceptionFilter,
+    LPTOP_LEVEL_EXCEPTION_FILTER ExceptionFilter) {
+  CHECK(REAL(SetUnhandledExceptionFilter));
+  if (ExceptionFilter == &SEHHandler || common_flags()->allow_user_segv_handler)
+    return REAL(SetUnhandledExceptionFilter)(ExceptionFilter);
+  // We record the user provided exception handler to be called for all the
+  // exceptions unhandled by asan.
+  Swap(ExceptionFilter, user_seh_handler);
+  return ExceptionFilter;
+}
+
 INTERCEPTOR_WINAPI(void, RtlRaiseException, EXCEPTION_RECORD *ExceptionRecord) {
   CHECK(REAL(RtlRaiseException));
   // This is a noreturn function, unless it's one of the exceptions raised to
@@ -119,6 +160,7 @@ namespace __asan {
 
 void InitializePlatformInterceptors() {
   ASAN_INTERCEPT_FUNC(CreateThread);
+  ASAN_INTERCEPT_FUNC(SetUnhandledExceptionFilter);
 
 #ifdef _WIN64
   ASAN_INTERCEPT_FUNC(__C_specific_handler);
@@ -235,30 +277,6 @@ void InitializePlatformExceptionHandlers
 #endif
 }
 
-static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
-
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE
-long __asan_unhandled_exception_filter(EXCEPTION_POINTERS *info) {
-  EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
-  CONTEXT *context = info->ContextRecord;
-
-  // Continue the search if the signal wasn't deadly.
-  if (!IsHandledDeadlyException(exception_record->ExceptionCode))
-    return EXCEPTION_CONTINUE_SEARCH;
-  // FIXME: Handle EXCEPTION_STACK_OVERFLOW here.
-
-  SignalContext sig = SignalContext::Create(exception_record, context);
-  ReportDeadlySignal(exception_record->ExceptionCode, sig);
-  UNREACHABLE("returned from reporting deadly signal");
-}
-
-static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
-  __asan_unhandled_exception_filter(info);
-
-  // Bubble out to the default exception filter.
-  return default_seh_handler(info);
-}
-
 // 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

Modified: compiler-rt/trunk/test/asan/TestCases/Windows/dll_host.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Windows/dll_host.cc?rev=293957&r1=293956&r2=293957&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Windows/dll_host.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Windows/dll_host.cc Thu Feb  2 17:02:04 2017
@@ -31,6 +31,7 @@
 // IMPORT: __asan_wrap_CreateThread
 // IMPORT: __asan_wrap_RaiseException
 // IMPORT: __asan_wrap_RtlRaiseException
+// IMPORT: __asan_wrap_SetUnhandledExceptionFilter
 //
 // RUN: cat %t.imports1 %t.imports2 | sort | uniq > %t.imports-sorted
 // RUN: cat %t.exports1 %t.exports2 | sort | uniq > %t.exports-sorted




More information about the llvm-commits mailing list