From 222610bf100cfe15730f60f8f5dc35782cb99ce1 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 3 Aug 2016 18:13:14 +0000 Subject: [PATCH] [ASan] Report illegal instruction exceptions in ASan Summary: Respect the handle_sigill common flag and handle_segv flags while we're at it. We still handle signals/exceptions differently on Unix and Windows. The installation process is tricky on Windows, and difficult to push down into sanitizer_common without concerning it with the different static/dynamic CRT models on Windows. Reviewers: kcc, etienneb Subscribers: llvm-commits, kubabrecka Differential Revision: https://reviews.llvm.org/D23098 llvm-svn: 277621 --- compiler-rt/lib/asan/asan_win.cc | 38 +++++++++++++++++++--- compiler-rt/lib/sanitizer_common/CMakeLists.txt | 8 ----- .../lib/sanitizer_common/sanitizer_flags.cc | 5 --- .../lib/sanitizer_common/sanitizer_flags.inc | 2 +- compiler-rt/test/asan/TestCases/ill.cc | 25 ++++++++++++++ 5 files changed, 59 insertions(+), 19 deletions(-) create mode 100644 compiler-rt/test/asan/TestCases/ill.cc diff --git a/compiler-rt/lib/asan/asan_win.cc b/compiler-rt/lib/asan/asan_win.cc index 8857506..cb03821 100644 --- a/compiler-rt/lib/asan/asan_win.cc +++ b/compiler-rt/lib/asan/asan_win.cc @@ -247,16 +247,44 @@ void InitializePlatformExceptionHandlers() { static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler; +// Check based on flags if we should report this exception. +static bool ShouldReportDeadlyException(unsigned code) { + switch (code) { + case EXCEPTION_ACCESS_VIOLATION: + case EXCEPTION_IN_PAGE_ERROR: + return common_flags()->handle_segv; + case EXCEPTION_BREAKPOINT: + case EXCEPTION_ILLEGAL_INSTRUCTION: { + return common_flags()->handle_sigill; + } + } + return false; +} + +// Return the textual name for this exception. +static const char *DescribeDeadlyException(unsigned code) { + switch (code) { + case EXCEPTION_ACCESS_VIOLATION: + return "access-violation"; + case EXCEPTION_IN_PAGE_ERROR: + return "in-page-error"; + case EXCEPTION_BREAKPOINT: + return "breakpoint"; + case EXCEPTION_ILLEGAL_INSTRUCTION: + return "illegal-instruction"; + } + return nullptr; +} + static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) { EXCEPTION_RECORD *exception_record = info->ExceptionRecord; CONTEXT *context = info->ContextRecord; - if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION || - exception_record->ExceptionCode == EXCEPTION_IN_PAGE_ERROR) { + if (ShouldReportDeadlyException(exception_record->ExceptionCode)) { + // Get the string description of the exception if this is a known deadly + // exception. const char *description = - (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) - ? "access-violation" - : "in-page-error"; + DescribeDeadlyException(exception_record->ExceptionCode); SignalContext sig = SignalContext::Create(exception_record, context); ReportDeadlySignal(description, sig); } diff --git a/compiler-rt/lib/sanitizer_common/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/CMakeLists.txt index 9a140be..59a6b35 100644 --- a/compiler-rt/lib/sanitizer_common/CMakeLists.txt +++ b/compiler-rt/lib/sanitizer_common/CMakeLists.txt @@ -126,14 +126,6 @@ set(SANITIZER_HEADERS set(SANITIZER_COMMON_DEFINITIONS) -if(MSVC) - list(APPEND SANITIZER_COMMON_DEFINITIONS - SANITIZER_NEEDS_SEGV=0) -else() - list(APPEND SANITIZER_COMMON_DEFINITIONS - SANITIZER_NEEDS_SEGV=1) -endif() - include(CheckIncludeFile) append_have_file_definition(rpc/xdr.h HAVE_RPC_XDR_H SANITIZER_COMMON_DEFINITIONS) append_have_file_definition(tirpc/rpc/xdr.h HAVE_TIRPC_RPC_XDR_H SANITIZER_COMMON_DEFINITIONS) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.cc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.cc index c2f19d4..913ce3c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.cc @@ -30,11 +30,6 @@ struct FlagDescription { IntrusiveList flag_descriptions; -// If set, the tool will install its own SEGV signal handler by default. -#ifndef SANITIZER_NEEDS_SEGV -# define SANITIZER_NEEDS_SEGV 1 -#endif - void CommonFlags::SetDefaults() { #define COMMON_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; #include "sanitizer_flags.inc" diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc index 203f41c..450436a 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc @@ -75,7 +75,7 @@ COMMON_FLAG(bool, print_summary, true, "If false, disable printing error summaries in addition to error " "reports.") COMMON_FLAG(bool, check_printf, true, "Check printf arguments.") -COMMON_FLAG(bool, handle_segv, SANITIZER_NEEDS_SEGV, +COMMON_FLAG(bool, handle_segv, true, "If set, registers the tool's custom SIGSEGV/SIGBUS handler.") COMMON_FLAG(bool, handle_abort, false, "If set, registers the tool's custom SIGABRT handler.") diff --git a/compiler-rt/test/asan/TestCases/ill.cc b/compiler-rt/test/asan/TestCases/ill.cc new file mode 100644 index 0000000..d4f0bdd --- /dev/null +++ b/compiler-rt/test/asan/TestCases/ill.cc @@ -0,0 +1,25 @@ +// Test the handle_sigill option. +// +// RUN: %clangxx_asan %s -o %t && %env_asan_opts=handle_sigill=0 not --crash %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0 +// RUN: %clangxx_asan %s -o %t && %env_asan_opts=handle_sigill=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 + +#ifdef _WIN32 +#include +#endif + +int main() { +#ifdef _WIN32 + // Sometimes on Windows this test generates a WER fault dialog. Suppress that. + UINT new_flags = SEM_FAILCRITICALERRORS | + SEM_NOGPFAULTERRORBOX | + SEM_NOOPENFILEERRORBOX; + // Preserve existing error mode, as discussed at + // http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx + UINT existing_flags = SetErrorMode(new_flags); + SetErrorMode(existing_flags | new_flags); +#endif + + __builtin_trap(); +} +// CHECK0-NOT: ERROR: AddressSanitizer +// CHECK1: ERROR: AddressSanitizer: {{ILL|illegal-instruction}} on unknown address {{0x0*}} -- 2.7.4