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 @@ -22,56 +22,21 @@ namespace __asan { +static void OnStackUnwind(const SignalContext &sig, + const void *callback_context, + BufferedStackTrace *stack) { + // Tests and maybe some users expect that scariness is going to be printed + // just before the stack. As only asan has scariness score we have no + // corresponding code in the sanitizer_common and we use this callback to + // print it. + static_cast(callback_context)->Print(); + GetStackTraceWithPcBpAndContext(stack, kStackTraceMax, sig.pc, sig.bp, + sig.context, + common_flags()->fast_unwind_on_fatal); +} + void ErrorDeadlySignal::Print() { - if (signal.IsStackOverflow()) { - Decorator d; - Printf("%s", d.Warning()); - Report( - "ERROR: AddressSanitizer: %s on address %p" - " (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, signal.pc, - signal.bp, signal.context, - common_flags()->fast_unwind_on_fatal); - stack.Print(); - ReportErrorSummary(scariness.GetDescription(), &stack); - } else { - Decorator d; - Printf("%s", d.Warning()); - const char *description = signal.Describe(); - Report( - "ERROR: AddressSanitizer: %s on unknown address %p (pc %p bp %p sp %p " - "T%d)\n", - description, (void *)signal.addr, (void *)signal.pc, (void *)signal.bp, - (void *)signal.sp, tid); - Printf("%s", d.Default()); - if (signal.pc < GetPageSizeCached()) - Report("Hint: pc points to the zero page.\n"); - if (signal.is_memory_access) { - const char *access_type = - signal.write_flag == SignalContext::WRITE - ? "WRITE" - : (signal.write_flag == SignalContext::READ ? "READ" : "UNKNOWN"); - Report("The signal is caused by a %s memory access.\n", access_type); - if (signal.addr < GetPageSizeCached()) - Report("Hint: address points to the zero page.\n"); - } - MaybeReportNonExecRegion(signal.pc); - scariness.Print(); - BufferedStackTrace stack; - GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, signal.pc, - signal.bp, signal.context, - common_flags()->fast_unwind_on_fatal); - stack.Print(); - MaybeDumpInstructionBytes(signal.pc); - MaybeDumpRegisters(signal.context); - Printf("AddressSanitizer can not provide additional info.\n"); - ReportErrorSummary(description, &stack); - } + ReportDeadlySignal(signal, tid, &OnStackUnwind, &scariness); } void ErrorDoubleFree::Print() { Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h @@ -31,6 +31,7 @@ namespace __sanitizer { struct AddressInfo; +struct BufferedStackTrace; struct SignalContext; struct StackTrace; @@ -311,10 +312,13 @@ void InstallDeadlySignalHandlers(SignalHandlerType handler); // Signal reporting. void StartReportDeadlySignal(); -// FIXME: Hide after moving more signal handling code into common. -void MaybeReportNonExecRegion(uptr pc); -void MaybeDumpInstructionBytes(uptr pc); -void MaybeDumpRegisters(void *context); +// Each sanitizer uses slightly different implementation of stack unwinding. +typedef void (*UnwindSignalStackCallbackType)(const SignalContext &sig, + const void *callback_context, + BufferedStackTrace *stack); +void ReportDeadlySignal(const SignalContext &sig, u32 tid, + UnwindSignalStackCallbackType unwind, + const void *unwind_context); // Alternative signal stack (POSIX-only). void SetAlternateSignalStack(); void UnsetAlternateSignalStack(); Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc @@ -148,7 +148,7 @@ #endif #if !SANITIZER_GO -void MaybeReportNonExecRegion(uptr pc) { +static void MaybeReportNonExecRegion(uptr pc) { #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD MemoryMappingLayout proc_maps(/*cache_enabled*/ true); MemoryMappedSegment segment; @@ -166,7 +166,7 @@ d.Default()); } -void MaybeDumpInstructionBytes(uptr pc) { +static void MaybeDumpInstructionBytes(uptr pc) { if (!common_flags()->dump_instruction_bytes || (pc < GetPageSizeCached())) return; InternalScopedString str(1024); @@ -182,11 +182,71 @@ Report("%s", str.data()); } -void MaybeDumpRegisters(void *context) { +static void MaybeDumpRegisters(void *context) { if (!common_flags()->dump_registers) return; SignalContext::DumpAllRegisters(context); } -#endif + +static void ReportStackOverflowImpl(const SignalContext &sig, u32 tid, + UnwindSignalStackCallbackType unwind, + const void *unwind_context) { + SanitizerCommonDecorator d; + Printf("%s", d.Warning()); + static const char kDescription[] = "stack-overflow"; + Report("ERROR: %s: %s on address %p (pc %p bp %p sp %p T%d)\n", + SanitizerToolName, kDescription, (void *)sig.addr, (void *)sig.pc, + (void *)sig.bp, (void *)sig.sp, tid); + Printf("%s", d.Default()); + InternalScopedBuffer stack_buffer(1); + BufferedStackTrace *stack = stack_buffer.data(); + stack->Reset(); + unwind(sig, unwind_context, stack); + stack->Print(); + ReportErrorSummary(kDescription, stack); +} + +static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid, + UnwindSignalStackCallbackType unwind, + const void *unwind_context) { + SanitizerCommonDecorator d; + Printf("%s", d.Warning()); + const char *description = sig.Describe(); + Report("ERROR: %s: %s on unknown address %p (pc %p bp %p sp %p T%d)\n", + SanitizerToolName, description, (void *)sig.addr, (void *)sig.pc, + (void *)sig.bp, (void *)sig.sp, tid); + Printf("%s", d.Default()); + 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"); + } + MaybeReportNonExecRegion(sig.pc); + InternalScopedBuffer stack_buffer(1); + BufferedStackTrace *stack = stack_buffer.data(); + stack->Reset(); + unwind(sig, unwind_context, stack); + stack->Print(); + MaybeDumpInstructionBytes(sig.pc); + MaybeDumpRegisters(sig.context); + Printf("%s can not provide additional info.\n", SanitizerToolName); + ReportErrorSummary(description, stack); +} + +void ReportDeadlySignal(const SignalContext &sig, u32 tid, + UnwindSignalStackCallbackType unwind, + const void *unwind_context) { + if (sig.IsStackOverflow()) + ReportStackOverflowImpl(sig, tid, unwind, unwind_context); + else + ReportDeadlySignalImpl(sig, tid, unwind, unwind_context); +} +#endif // !SANITIZER_GO void WriteToSyslog(const char *msg) { InternalScopedString msg_copy(kErrorMessageBufferSize); Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_fuchsia.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_fuchsia.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_fuchsia.cc @@ -92,6 +92,9 @@ void DisableCoreDumperIfNecessary() {} void InstallDeadlySignalHandlers(SignalHandlerType handler) {} void StartReportDeadlySignal() {} +void ReportDeadlySignal(const SignalContext &sig, u32 tid, + UnwindSignalStackCallbackType unwind, + const void *unwind_context) {} void SetAlternateSignalStack() {} void UnsetAlternateSignalStack() {} void InitTlsSize() {}