From dbde6f337c671fa30fc4510136eef13e23f49745 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Wed, 13 Sep 2017 18:30:16 +0000 Subject: [PATCH] [compiler-rt] Use SignalContext in ErrorStackOverflow and ErrorDeadlySignal Summary: Part of https://github.com/google/sanitizers/issues/637 Reviewers: eugenis, alekseyshl, filcab Subscribers: kubamracek, llvm-commits, dberris Differential Revision: https://reviews.llvm.org/D37793 llvm-svn: 313168 --- compiler-rt/lib/asan/asan_errors.cc | 33 +++++---- compiler-rt/lib/asan/asan_errors.h | 38 +++------- .../lib/sanitizer_common/sanitizer_common.h | 6 +- .../lib/sanitizer_common/sanitizer_fuchsia.cc | 2 +- .../lib/sanitizer_common/sanitizer_posix.cc | 4 +- .../lib/sanitizer_common/sanitizer_win.cc | 69 ++++++++++++------- 6 files changed, 78 insertions(+), 74 deletions(-) diff --git a/compiler-rt/lib/asan/asan_errors.cc b/compiler-rt/lib/asan/asan_errors.cc index c9cf8f70bf10..7625dc9b8ea6 100644 --- a/compiler-rt/lib/asan/asan_errors.cc +++ b/compiler-rt/lib/asan/asan_errors.cc @@ -27,12 +27,14 @@ void ErrorStackOverflow::Print() { Printf("%s", d.Warning()); Report( "ERROR: AddressSanitizer: %s on address %p" - " (pc %p bp %p sp %p T%d)\n", scariness.GetDescription(), - (void *)addr, (void *)pc, (void *)bp, (void *)sp, tid); + " (pc %p bp %p sp %p T%d)\n", + scariness.GetDescription(), (void *)signal.addr, (void *)signal.pc, + (void *)signal.bp, (void *)signal.sp, tid); Printf("%s", d.Default()); scariness.Print(); BufferedStackTrace stack; - GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context, + GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, signal.pc, signal.bp, + signal.context, common_flags()->fast_unwind_on_fatal); stack.Print(); ReportErrorSummary(scariness.GetDescription(), &stack); @@ -41,30 +43,33 @@ void ErrorStackOverflow::Print() { void ErrorDeadlySignal::Print() { Decorator d; Printf("%s", d.Warning()); - const char *description = __sanitizer::DescribeSignalOrException(signo); + const char *description = signal.Describe(); Report( "ERROR: AddressSanitizer: %s on unknown address %p (pc %p bp %p sp %p " "T%d)\n", - description, (void *)addr, (void *)pc, (void *)bp, (void *)sp, tid); + description, (void *)signal.addr, (void *)signal.pc, (void *)signal.bp, + (void *)signal.sp, tid); Printf("%s", d.Default()); - if (pc < GetPageSizeCached()) Report("Hint: pc points to the zero page.\n"); - if (is_memory_access) { + if (signal.pc < GetPageSizeCached()) + Report("Hint: pc points to the zero page.\n"); + if (signal.is_memory_access) { const char *access_type = - write_flag == SignalContext::WRITE + signal.write_flag == SignalContext::WRITE ? "WRITE" - : (write_flag == SignalContext::READ ? "READ" : "UNKNOWN"); + : (signal.write_flag == SignalContext::READ ? "READ" : "UNKNOWN"); Report("The signal is caused by a %s memory access.\n", access_type); - if (addr < GetPageSizeCached()) + if (signal.addr < GetPageSizeCached()) Report("Hint: address points to the zero page.\n"); } - MaybeReportNonExecRegion(pc); + MaybeReportNonExecRegion(signal.pc); scariness.Print(); BufferedStackTrace stack; - GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context, + GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, signal.pc, signal.bp, + signal.context, common_flags()->fast_unwind_on_fatal); stack.Print(); - MaybeDumpInstructionBytes(pc); - MaybeDumpRegisters(context); + MaybeDumpInstructionBytes(signal.pc); + MaybeDumpRegisters(signal.context); Printf("AddressSanitizer can not provide additional info.\n"); ReportErrorSummary(description, &stack); } diff --git a/compiler-rt/lib/asan/asan_errors.h b/compiler-rt/lib/asan/asan_errors.h index 55b8360a3f70..b9944739bf14 100644 --- a/compiler-rt/lib/asan/asan_errors.h +++ b/compiler-rt/lib/asan/asan_errors.h @@ -28,19 +28,12 @@ struct ErrorBase { }; struct ErrorStackOverflow : ErrorBase { - uptr addr, pc, bp, sp; - // ErrorStackOverflow never owns the context. - void *context; + SignalContext signal; // VS2013 doesn't implement unrestricted unions, so we need a trivial default // constructor ErrorStackOverflow() = default; ErrorStackOverflow(u32 tid, const SignalContext &sig) - : ErrorBase(tid), - addr(sig.addr), - pc(sig.pc), - bp(sig.bp), - sp(sig.sp), - context(sig.context) { + : ErrorBase(tid), signal(sig) { scariness.Clear(); scariness.Scare(10, "stack-overflow"); } @@ -48,34 +41,21 @@ struct ErrorStackOverflow : ErrorBase { }; struct ErrorDeadlySignal : ErrorBase { - uptr addr, pc, bp, sp; - // ErrorDeadlySignal never owns the context. - void *context; - int signo; - SignalContext::WriteFlag write_flag; - bool is_memory_access; + SignalContext signal; // VS2013 doesn't implement unrestricted unions, so we need a trivial default // constructor ErrorDeadlySignal() = default; ErrorDeadlySignal(u32 tid, const SignalContext &sig) - : ErrorBase(tid), - addr(sig.addr), - pc(sig.pc), - bp(sig.bp), - sp(sig.sp), - context(sig.context), - signo(sig.GetType()), - write_flag(sig.write_flag), - is_memory_access(sig.is_memory_access) { + : ErrorBase(tid), signal(sig) { scariness.Clear(); - if (is_memory_access) { - if (addr < GetPageSizeCached()) { + if (signal.is_memory_access) { + if (signal.addr < GetPageSizeCached()) { scariness.Scare(10, "null-deref"); - } else if (addr == pc) { + } else if (signal.addr == signal.pc) { scariness.Scare(60, "wild-jump"); - } else if (write_flag == SignalContext::WRITE) { + } else if (signal.write_flag == SignalContext::WRITE) { scariness.Scare(30, "wild-addr-write"); - } else if (write_flag == SignalContext::READ) { + } else if (signal.write_flag == SignalContext::READ) { scariness.Scare(20, "wild-addr-read"); } else { scariness.Scare(25, "wild-addr"); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 32fd381cc2bb..6cd21d79ab0b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -309,7 +309,6 @@ void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded)); typedef void (*SignalHandlerType)(int, void *, void *); HandleSignalMode GetHandleSignalMode(int signum); void InstallDeadlySignalHandlers(SignalHandlerType handler); -const char *DescribeSignalOrException(int signo); // Signal reporting. void StartReportDeadlySignal(); bool IsStackOverflow(const SignalContext &sig); @@ -805,6 +804,9 @@ struct SignalContext { enum WriteFlag { UNKNOWN, READ, WRITE } write_flag; + // VS2013 doesn't implement unrestricted unions, so we need a trivial default + // constructor + SignalContext() = default; // SignalContext is going to keep pointers to siginfo and context without // owning them. SignalContext(void *siginfo, void *context, uptr addr, uptr pc, uptr sp, @@ -830,7 +832,7 @@ struct SignalContext { int GetType() const; // String description of the signal. - const char *Describe() const { return DescribeSignalOrException(GetType()); } + const char *Describe() const; }; void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc index 7ea522a0d4da..07190f15071b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc @@ -98,7 +98,7 @@ void InitTlsSize() {} void PrintModuleMap() {} void SignalContext::DumpAllRegisters(void *context) { UNIMPLEMENTED(); } -const char *DescribeSignalOrException(int signo) { UNIMPLEMENTED(); } +const char *SignalContext::Describe() const { UNIMPLEMENTED(); } struct UnwindTraceArg { BufferedStackTrace *stack; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc index b74b1f995c38..35fc35ce9490 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc @@ -310,8 +310,8 @@ int SignalContext::GetType() const { return static_cast(siginfo)->si_signo; } -const char *DescribeSignalOrException(int signo) { - switch (signo) { +const char *SignalContext::Describe() const { + switch (GetType()) { case SIGFPE: return "FPE"; case SIGILL: diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc index 65898a709e84..65e7aa8d71cb 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc @@ -890,32 +890,6 @@ bool IsHandledDeadlyException(DWORD exceptionCode) { return false; } -const char *DescribeSignalOrException(int signo) { - unsigned code = signo; - // Get the string description of the exception if this is a known deadly - // exception. - switch (code) { - case EXCEPTION_ACCESS_VIOLATION: return "access-violation"; - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "array-bounds-exceeded"; - case EXCEPTION_STACK_OVERFLOW: return "stack-overflow"; - case EXCEPTION_DATATYPE_MISALIGNMENT: return "datatype-misalignment"; - case EXCEPTION_IN_PAGE_ERROR: return "in-page-error"; - case EXCEPTION_ILLEGAL_INSTRUCTION: return "illegal-instruction"; - case EXCEPTION_PRIV_INSTRUCTION: return "priv-instruction"; - case EXCEPTION_BREAKPOINT: return "breakpoint"; - case EXCEPTION_FLT_DENORMAL_OPERAND: return "flt-denormal-operand"; - case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "flt-divide-by-zero"; - case EXCEPTION_FLT_INEXACT_RESULT: return "flt-inexact-result"; - case EXCEPTION_FLT_INVALID_OPERATION: return "flt-invalid-operation"; - case EXCEPTION_FLT_OVERFLOW: return "flt-overflow"; - case EXCEPTION_FLT_STACK_CHECK: return "flt-stack-check"; - case EXCEPTION_FLT_UNDERFLOW: return "flt-underflow"; - case EXCEPTION_INT_DIVIDE_BY_ZERO: return "int-divide-by-zero"; - case EXCEPTION_INT_OVERFLOW: return "int-overflow"; - } - return "unknown exception"; -} - bool IsAccessibleMemoryRange(uptr beg, uptr size) { SYSTEM_INFO si; GetNativeSystemInfo(&si); @@ -978,6 +952,49 @@ int SignalContext::GetType() const { return static_cast(siginfo)->ExceptionCode; } +const char *SignalContext::Describe() const { + unsigned code = GetType(); + // Get the string description of the exception if this is a known deadly + // exception. + switch (code) { + case EXCEPTION_ACCESS_VIOLATION: + return "access-violation"; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + return "array-bounds-exceeded"; + case EXCEPTION_STACK_OVERFLOW: + return "stack-overflow"; + case EXCEPTION_DATATYPE_MISALIGNMENT: + return "datatype-misalignment"; + case EXCEPTION_IN_PAGE_ERROR: + return "in-page-error"; + case EXCEPTION_ILLEGAL_INSTRUCTION: + return "illegal-instruction"; + case EXCEPTION_PRIV_INSTRUCTION: + return "priv-instruction"; + case EXCEPTION_BREAKPOINT: + return "breakpoint"; + case EXCEPTION_FLT_DENORMAL_OPERAND: + return "flt-denormal-operand"; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + return "flt-divide-by-zero"; + case EXCEPTION_FLT_INEXACT_RESULT: + return "flt-inexact-result"; + case EXCEPTION_FLT_INVALID_OPERATION: + return "flt-invalid-operation"; + case EXCEPTION_FLT_OVERFLOW: + return "flt-overflow"; + case EXCEPTION_FLT_STACK_CHECK: + return "flt-stack-check"; + case EXCEPTION_FLT_UNDERFLOW: + return "flt-underflow"; + case EXCEPTION_INT_DIVIDE_BY_ZERO: + return "int-divide-by-zero"; + case EXCEPTION_INT_OVERFLOW: + return "int-overflow"; + } + return "unknown exception"; +} + uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { // FIXME: Actually implement this function. CHECK_GT(buf_len, 0);