diff options
author | Kostya Serebryany <kcc@google.com> | 2013-02-06 12:36:49 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2013-02-06 12:36:49 +0000 |
commit | b4c2c5c8a680597d1519fa1048b37a7ec839df2d (patch) | |
tree | fa4130331fe36100901090d6270227c237851423 | |
parent | 8035b0a6ced4dd3f1a0f34e0a027005b53f7753b (diff) | |
download | bcm5719-llvm-b4c2c5c8a680597d1519fa1048b37a7ec839df2d.tar.gz bcm5719-llvm-b4c2c5c8a680597d1519fa1048b37a7ec839df2d.zip |
[asan] print a short one-line report summary after the full report. Currently, works only if symbolization happens in-process.
llvm-svn: 174501
8 files changed, 65 insertions, 6 deletions
diff --git a/compiler-rt/include/sanitizer/common_interface_defs.h b/compiler-rt/include/sanitizer/common_interface_defs.h index 86338dcce48..238c30dd09f 100644 --- a/compiler-rt/include/sanitizer/common_interface_defs.h +++ b/compiler-rt/include/sanitizer/common_interface_defs.h @@ -31,6 +31,11 @@ extern "C" { // that the tools may call to bypass the sandbox. void __sanitizer_sandbox_on_notify(void *reserved); + // This function is called by the tool when it has just finished reporting + // an error. 'error_summary' is a one-line string that summarizes + // the error message. This function can be overridden by the client. + void __sanitizer_report_error_summary(const char *error_summary); + #ifdef __cplusplus } // extern "C" #endif diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc index 83191ea9aea..d4fe21c55ab 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cc +++ b/compiler-rt/lib/asan/asan_interceptors.cc @@ -740,7 +740,7 @@ void InitializeAsanInterceptors() { if (flags()->verbosity > 0) { Report("AddressSanitizer: libc interceptors initialized\n"); } -#endif // __APPLE__ +#endif // __APPLE__ } } // namespace __asan diff --git a/compiler-rt/lib/asan/asan_report.cc b/compiler-rt/lib/asan/asan_report.cc index e687b57b7a6..32252cbf2e7 100644 --- a/compiler-rt/lib/asan/asan_report.cc +++ b/compiler-rt/lib/asan/asan_report.cc @@ -469,6 +469,20 @@ class ScopedInErrorReport { } }; +static void ReportSummary(const char *error_type, StackTrace *stack) { + if (!stack->size) return; + if (IsSymbolizerAvailable()) { + AddressInfo ai; + // Currently, we include the first stack frame into the report summary. + // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc). + SymbolizeCode(stack->trace[0], &ai, 1); + ReportErrorSummary(error_type, + StripPathPrefix(ai.file, flags()->strip_path_prefix), + ai.line, ai.function); + } + // FIXME: do we need to print anything at all if there is no symbolizer? +} + void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) { ScopedInErrorReport in_report; Decorator d; @@ -481,6 +495,7 @@ void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) { Printf("AddressSanitizer can not provide additional info.\n"); GET_STACK_TRACE_FATAL(pc, bp); PrintStack(&stack); + ReportSummary("SEGV", &stack); } void ReportDoubleFree(uptr addr, StackTrace *stack) { @@ -491,6 +506,7 @@ void ReportDoubleFree(uptr addr, StackTrace *stack) { Printf("%s", d.EndWarning()); PrintStack(stack); DescribeHeapAddress(addr, 1); + ReportSummary("double-free", stack); } void ReportFreeNotMalloced(uptr addr, StackTrace *stack) { @@ -502,6 +518,7 @@ void ReportFreeNotMalloced(uptr addr, StackTrace *stack) { Printf("%s", d.EndWarning()); PrintStack(stack); DescribeHeapAddress(addr, 1); + ReportSummary("bad-free", stack); } void ReportAllocTypeMismatch(uptr addr, StackTrace *stack, @@ -520,6 +537,7 @@ void ReportAllocTypeMismatch(uptr addr, StackTrace *stack, Printf("%s", d.EndWarning()); PrintStack(stack); DescribeHeapAddress(addr, 1); + ReportSummary("alloc-dealloc-mismatch", stack); Report("HINT: if you don't care about these warnings you may set " "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n"); } @@ -534,6 +552,7 @@ void ReportMallocUsableSizeNotOwned(uptr addr, StackTrace *stack) { Printf("%s", d.EndWarning()); PrintStack(stack); DescribeHeapAddress(addr, 1); + ReportSummary("bad-malloc_usable_size", stack); } void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) { @@ -546,6 +565,7 @@ void ReportAsanGetAllocatedSizeNotOwned(uptr addr, StackTrace *stack) { Printf("%s", d.EndWarning()); PrintStack(stack); DescribeHeapAddress(addr, 1); + ReportSummary("bad-__asan_get_allocated_size", stack); } void ReportStringFunctionMemoryRangesOverlap( @@ -553,14 +573,17 @@ void ReportStringFunctionMemoryRangesOverlap( const char *offset2, uptr length2, StackTrace *stack) { ScopedInErrorReport in_report; Decorator d; + char bug_type[100]; + internal_snprintf(bug_type, sizeof(bug_type), "%s-param-overlap", function); Printf("%s", d.Warning()); - Report("ERROR: AddressSanitizer: %s-param-overlap: " + Report("ERROR: AddressSanitizer: %s: " "memory ranges [%p,%p) and [%p, %p) overlap\n", \ - function, offset1, offset1 + length1, offset2, offset2 + length2); + bug_type, offset1, offset1 + length1, offset2, offset2 + length2); Printf("%s", d.EndWarning()); PrintStack(stack); DescribeAddress((uptr)offset1, length1); DescribeAddress((uptr)offset2, length2); + ReportSummary(bug_type, stack); } // ----------------------- Mac-specific reports ----------------- {{{1 @@ -670,7 +693,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp, PrintStack(&stack); DescribeAddress(addr, access_size); - + ReportSummary(bug_descr, &stack); PrintShadowMemoryForAddress(addr); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.cc b/compiler-rt/lib/sanitizer_common/sanitizer_common.cc index 586e97f1bb2..fb48eaca039 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.cc @@ -192,6 +192,16 @@ void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type) { return (void*)res; } +void ReportErrorSummary(const char *error_type, const char *file, + int line, const char *function) { + const int kMaxSize = 1024; // We don't want a summary too long. + InternalScopedBuffer<char> buff(kMaxSize); + internal_snprintf(buff.data(), kMaxSize, "%s %s %s:%d %s", + SanitizerToolName, error_type, + file, line, function); + __sanitizer_report_error_summary(buff.data()); +} + } // namespace __sanitizer using namespace __sanitizer; // NOLINT @@ -224,4 +234,8 @@ void NOINLINE __sanitizer_sandbox_on_notify(void *reserved) { (void)reserved; PrepareForSandboxing(); } + +void __sanitizer_report_error_summary(const char *error_summary) { + Printf("SUMMARY: %s\n", error_summary); +} } // extern "C" diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index b39bd74e895..b0501db0998 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -19,6 +19,7 @@ #include "sanitizer_internal_defs.h" namespace __sanitizer { +struct StackTrace; // Constants. const uptr kWordSize = SANITIZER_WORDSIZE / 8; @@ -157,6 +158,12 @@ typedef void (*CheckFailedCallbackType)(const char *, int, const char *, u64, u64); void SetCheckFailedCallback(CheckFailedCallbackType callback); +// Construct a one-line string like +// SanitizerToolName: error_type file:line function +// and call __sanitizer_report_error_summary on it. +void ReportErrorSummary(const char *error_type, const char *file, + int line, const char *function); + // Math INLINE bool IsPowerOfTwo(uptr x) { return (x & (x - 1)) == 0; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h index b0ce886e356..af53395ad43 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h @@ -83,6 +83,12 @@ extern "C" { // that the tools may call to bypass the sandbox. void __sanitizer_sandbox_on_notify(void *reserved) SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE; + + // This function is called by the tool when it has just finished reporting + // an error. 'error_summary' is a one-line string that summarizes + // the error message. This function can be overridden by the client. + void __sanitizer_report_error_summary(const char *error_summary) + SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE; } // extern "C" diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc index 109a674e45b..59b42ec2611 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc @@ -17,8 +17,8 @@ #include "sanitizer_symbolizer.h" namespace __sanitizer { -static const char *StripPathPrefix(const char *filepath, - const char *strip_file_prefix) { +const char *StripPathPrefix(const char *filepath, + const char *strip_file_prefix) { if (filepath == internal_strstr(filepath, strip_file_prefix)) return filepath + internal_strlen(strip_file_prefix); return filepath; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h index 597d24fd067..b9ea9b43592 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h @@ -57,6 +57,10 @@ struct StackTrace { u32 *compressed, uptr size); }; + +const char *StripPathPrefix(const char *filepath, + const char *strip_file_prefix); + } // namespace __sanitizer // Use this macro if you want to print stack trace with the caller |