From c081bfe418eb647ae8f90875299c9c768bec261e Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 3 Aug 2016 18:13:14 +0000 Subject: [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 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@277621 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/asan_win.cc | 38 +++++++++++++++++++++++++++----- lib/sanitizer_common/CMakeLists.txt | 8 ------- lib/sanitizer_common/sanitizer_flags.cc | 5 ----- lib/sanitizer_common/sanitizer_flags.inc | 2 +- test/asan/TestCases/ill.cc | 25 +++++++++++++++++++++ 5 files changed, 59 insertions(+), 19 deletions(-) create mode 100644 test/asan/TestCases/ill.cc diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc index 8857506d5..cb038212e 100644 --- a/lib/asan/asan_win.cc +++ b/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/lib/sanitizer_common/CMakeLists.txt b/lib/sanitizer_common/CMakeLists.txt index 9a140be45..59a6b3511 100644 --- a/lib/sanitizer_common/CMakeLists.txt +++ b/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/lib/sanitizer_common/sanitizer_flags.cc b/lib/sanitizer_common/sanitizer_flags.cc index c2f19d425..913ce3cb4 100644 --- a/lib/sanitizer_common/sanitizer_flags.cc +++ b/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/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc index 203f41ca3..450436a68 100644 --- a/lib/sanitizer_common/sanitizer_flags.inc +++ b/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/test/asan/TestCases/ill.cc b/test/asan/TestCases/ill.cc new file mode 100644 index 000000000..d4f0bdd74 --- /dev/null +++ b/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*}} -- cgit v1.2.1