Index: compiler-rt/trunk/lib/asan/asan_errors.h =================================================================== --- compiler-rt/trunk/lib/asan/asan_errors.h +++ compiler-rt/trunk/lib/asan/asan_errors.h @@ -16,6 +16,7 @@ #include "asan_descriptions.h" #include "asan_scariness_score.h" +#include "sanitizer_common/sanitizer_common.h" namespace __asan { @@ -44,6 +45,47 @@ void Print(); }; +struct ErrorDeadlySignal : ErrorBase { + u32 tid; + uptr addr, pc, bp, sp; + int signo; + SignalContext::WriteFlag write_flag; + bool is_memory_access; + // ErrorDeadlySignal never owns the context. + void *context; + // VS2013 doesn't implement unrestricted unions, so we need a trivial default + // constructor + ErrorDeadlySignal() = default; + ErrorDeadlySignal(int signo_, const SignalContext &sig, u32 tid_) + : tid(tid_), + addr(sig.addr), + pc(sig.pc), + bp(sig.bp), + sp(sig.sp), + signo(signo_), + write_flag(sig.write_flag), + is_memory_access(sig.is_memory_access), + context(sig.context) { + scariness.Clear(); + if (is_memory_access) { + if (addr < GetPageSizeCached()) { + scariness.Scare(10, "null-deref"); + } else if (addr == pc) { + scariness.Scare(60, "wild-jump"); + } else if (write_flag == SignalContext::WRITE) { + scariness.Scare(30, "wild-addr-write"); + } else if (write_flag == SignalContext::READ) { + scariness.Scare(20, "wild-addr-read"); + } else { + scariness.Scare(25, "wild-addr"); + } + } else { + scariness.Scare(10, "signal"); + } + } + void Print(); +}; + struct ErrorDoubleFree : ErrorBase { u32 tid; HeapAddressDescription addr_description; @@ -84,6 +126,7 @@ enum ErrorKind { kErrorKindInvalid = 0, kErrorKindStackOverflow, + kErrorKindDeadlySignal, kErrorKindDoubleFree, kErrorKindNewDeleteSizeMismatch, }; @@ -97,6 +140,7 @@ // add a lot of code and the benefit wouldn't be that big. union { ErrorStackOverflow stack_overflow; + ErrorDeadlySignal deadly_signal; ErrorDoubleFree double_free; ErrorNewDeleteSizeMismatch new_delete_size_mismatch; }; @@ -104,6 +148,9 @@ ErrorDescription(const ErrorStackOverflow &e) // NOLINT : kind(kErrorKindStackOverflow), stack_overflow(e) {} + ErrorDescription(const ErrorDeadlySignal &e) // NOLINT + : kind(kErrorKindDeadlySignal), + deadly_signal(e) {} ErrorDescription(const ErrorDoubleFree &e) // NOLINT : kind(kErrorKindDoubleFree), double_free(e) {} @@ -117,6 +164,9 @@ case kErrorKindStackOverflow: stack_overflow.Print(); return; + case kErrorKindDeadlySignal: + deadly_signal.Print(); + return; case kErrorKindDoubleFree: double_free.Print(); return; Index: compiler-rt/trunk/lib/asan/asan_errors.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_errors.cc +++ compiler-rt/trunk/lib/asan/asan_errors.cc @@ -13,7 +13,9 @@ //===----------------------------------------------------------------------===// #include "asan_errors.h" +#include #include "asan_descriptions.h" +#include "asan_report.h" #include "asan_stack.h" namespace __asan { @@ -34,6 +36,50 @@ ReportErrorSummary("stack-overflow", &stack); } +static void MaybeDumpInstructionBytes(uptr pc) { + if (!flags()->dump_instruction_bytes || (pc < GetPageSizeCached())) return; + InternalScopedString str(1024); + str.append("First 16 instruction bytes at pc: "); + if (IsAccessibleMemoryRange(pc, 16)) { + for (int i = 0; i < 16; ++i) { + PrintMemoryByte(&str, "", ((u8 *)pc)[i], /*in_shadow*/ false, " "); + } + str.append("\n"); + } else { + str.append("unaccessible\n"); + } + Report("%s", str.data()); +} + +void ErrorDeadlySignal::Print() { + Decorator d; + Printf("%s", d.Warning()); + const char *description = DescribeSignalOrException(signo); + 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); + Printf("%s", d.EndWarning()); + if (pc < GetPageSizeCached()) Report("Hint: pc points to the zero page.\n"); + if (is_memory_access) { + const char *access_type = + write_flag == SignalContext::WRITE + ? "WRITE" + : (write_flag == SignalContext::READ ? "READ" : "UNKNOWN"); + Report("The signal is caused by a %s memory access.\n", access_type); + if (addr < GetPageSizeCached()) + Report("Hint: address points to the zero page.\n"); + } + scariness.Print(); + BufferedStackTrace stack; + GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context, + common_flags()->fast_unwind_on_fatal); + stack.Print(); + MaybeDumpInstructionBytes(pc); + Printf("AddressSanitizer can not provide additional info.\n"); + ReportErrorSummary(description, &stack); +} + void ErrorDoubleFree::Print() { Decorator d; Printf("%s", d.Warning()); Index: compiler-rt/trunk/lib/asan/asan_internal.h =================================================================== --- compiler-rt/trunk/lib/asan/asan_internal.h +++ compiler-rt/trunk/lib/asan/asan_internal.h @@ -65,6 +65,9 @@ // asan_win.cc void InitializePlatformExceptionHandlers(); +// asan_win.cc / asan_posix.cc +const char *DescribeSignalOrException(int signo); + // asan_rtl.cc void NORETURN ShowStatsAndAbort(); Index: compiler-rt/trunk/lib/asan/asan_posix.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_posix.cc +++ compiler-rt/trunk/lib/asan/asan_posix.cc @@ -33,6 +33,17 @@ namespace __asan { +const char *DescribeSignalOrException(int signo) { + switch (signo) { + case SIGFPE: + return "FPE"; + case SIGILL: + return "ILL"; + default: + return "SEGV"; + } +} + void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { ScopedDeadlySignal signal_scope(GetCurrentThread()); int code = (int)((siginfo_t*)siginfo)->si_code; @@ -84,14 +95,8 @@ // unaligned memory access. if (IsStackAccess && (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR)) ReportStackOverflow(sig); - else if (signo == SIGFPE) - ReportDeadlySignal("FPE", sig); - else if (signo == SIGILL) - ReportDeadlySignal("ILL", sig); - else if (signo == SIGABRT) - ReportDeadlySignal("ABRT", sig); else - ReportDeadlySignal("SEGV", sig); + ReportDeadlySignal(signo, sig); } // ---------------------- TSD ---------------- {{{1 Index: compiler-rt/trunk/lib/asan/asan_report.h =================================================================== --- compiler-rt/trunk/lib/asan/asan_report.h +++ compiler-rt/trunk/lib/asan/asan_report.h @@ -42,6 +42,9 @@ void PrintGlobalNameIfASCII(InternalScopedString *str, const __asan_global &g); void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g); +void PrintMemoryByte(InternalScopedString *str, const char *before, u8 byte, + bool in_shadow, const char *after = "\n"); + // The following functions prints address description depending // on the memory type (shadow/heap/stack/global). bool ParseFrameDescription(const char *frame_descr, @@ -51,7 +54,7 @@ void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write, uptr access_size, u32 exp, bool fatal); void ReportStackOverflow(const SignalContext &sig); -void ReportDeadlySignal(const char *description, const SignalContext &sig); +void ReportDeadlySignal(int signo, const SignalContext &sig); void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size, BufferedStackTrace *free_stack); void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack); Index: compiler-rt/trunk/lib/asan/asan_report.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_report.cc +++ compiler-rt/trunk/lib/asan/asan_report.cc @@ -69,8 +69,8 @@ // ---------------------- Helper functions ----------------------- {{{1 -static void PrintMemoryByte(InternalScopedString *str, const char *before, - u8 byte, bool in_shadow, const char *after = "\n") { +void PrintMemoryByte(InternalScopedString *str, const char *before, u8 byte, + bool in_shadow, const char *after) { Decorator d; str->append("%s%s%x%x%s%s", before, in_shadow ? d.ShadowByte(byte) : d.MemoryByte(), @@ -135,22 +135,6 @@ PrintShadowByte(str, " Right alloca redzone: ", kAsanAllocaRightMagic); } -void MaybeDumpInstructionBytes(uptr pc) { - if (!flags()->dump_instruction_bytes || (pc < GetPageSizeCached())) - return; - InternalScopedString str(1024); - str.append("First 16 instruction bytes at pc: "); - if (IsAccessibleMemoryRange(pc, 16)) { - for (int i = 0; i < 16; ++i) { - PrintMemoryByte(&str, "", ((u8 *)pc)[i], /*in_shadow*/false, " "); - } - str.append("\n"); - } else { - str.append("unaccessible\n"); - } - Report("%s", str.data()); -} - static void PrintShadowMemoryForAddress(uptr addr) { if (!AddrIsInMem(addr)) return; uptr shadow_addr = MemToShadow(addr); @@ -344,46 +328,10 @@ in_report.ReportError(error); } -void ReportDeadlySignal(const char *description, const SignalContext &sig) { +void ReportDeadlySignal(int signo, const SignalContext &sig) { ScopedInErrorReport in_report(/*report*/ nullptr, /*fatal*/ true); - Decorator d; - Printf("%s", d.Warning()); - Report( - "ERROR: AddressSanitizer: %s on unknown address %p" - " (pc %p bp %p sp %p T%d)\n", - description, (void *)sig.addr, (void *)sig.pc, (void *)sig.bp, - (void *)sig.sp, GetCurrentTidOrInvalid()); - Printf("%s", d.EndWarning()); - ScarinessScore SS; - if (sig.pc < GetPageSizeCached()) - Report("Hint: pc points to the zero page.\n"); - if (sig.is_memory_access) { - const char *access_type = - sig.write_flag == SignalContext::WRITE - ? "WRITE" - : (sig.write_flag == SignalContext::READ ? "READ" : "UNKNOWN"); - Report("The signal is caused by a %s memory access.\n", access_type); - if (sig.addr < GetPageSizeCached()) { - Report("Hint: address points to the zero page.\n"); - SS.Scare(10, "null-deref"); - } else if (sig.addr == sig.pc) { - SS.Scare(60, "wild-jump"); - } else if (sig.write_flag == SignalContext::WRITE) { - SS.Scare(30, "wild-addr-write"); - } else if (sig.write_flag == SignalContext::READ) { - SS.Scare(20, "wild-addr-read"); - } else { - SS.Scare(25, "wild-addr"); - } - } else { - SS.Scare(10, "signal"); - } - SS.Print(); - GET_STACK_TRACE_SIGNAL(sig); - stack.Print(); - MaybeDumpInstructionBytes(sig.pc); - Printf("AddressSanitizer can not provide additional info.\n"); - ReportErrorSummary(description, &stack); + ErrorDeadlySignal error(signo, sig, GetCurrentTidOrInvalid()); + in_report.ReportError(error); } void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) { Index: compiler-rt/trunk/lib/asan/asan_win.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_win.cc +++ compiler-rt/trunk/lib/asan/asan_win.cc @@ -270,7 +270,10 @@ } // Return the textual name for this exception. -static const char *DescribeDeadlyException(unsigned code) { +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"; @@ -289,12 +292,8 @@ CONTEXT *context = info->ContextRecord; if (ShouldReportDeadlyException(exception_record->ExceptionCode)) { - // Get the string description of the exception if this is a known deadly - // exception. - const char *description = - DescribeDeadlyException(exception_record->ExceptionCode); SignalContext sig = SignalContext::Create(exception_record, context); - ReportDeadlySignal(description, sig); + ReportDeadlySignal(exception_record->ExceptionCode, sig); } // FIXME: Handle EXCEPTION_STACK_OVERFLOW here.