[asan] print a short one-line report summary after the full report. Currently, works...
authorKostya Serebryany <kcc@google.com>
Wed, 6 Feb 2013 12:36:49 +0000 (12:36 +0000)
committerKostya Serebryany <kcc@google.com>
Wed, 6 Feb 2013 12:36:49 +0000 (12:36 +0000)
llvm-svn: 174501

compiler-rt/include/sanitizer/common_interface_defs.h
compiler-rt/lib/asan/asan_interceptors.cc
compiler-rt/lib/asan/asan_report.cc
compiler-rt/lib/sanitizer_common/sanitizer_common.cc
compiler-rt/lib/sanitizer_common/sanitizer_common.h
compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h
compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc
compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h

index 86338dc..238c30d 100644 (file)
@@ -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
index 83191ea..d4fe21c 100644 (file)
@@ -740,7 +740,7 @@ void InitializeAsanInterceptors() {
   if (flags()->verbosity > 0) {
     Report("AddressSanitizer: libc interceptors initialized\n");
   }
-#endif // __APPLE__
+#endif  // __APPLE__
 }
 
 }  // namespace __asan
index e687b57..32252cb 100644 (file)
@@ -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);
 }
 
index 586e97f..fb48eac 100644 (file)
@@ -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"
index b39bd74..b0501db 100644 (file)
@@ -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;
index b0ce886..af53395 100644 (file)
@@ -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"
 
 
index 109a674..59b42ec 100644 (file)
@@ -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;
index 597d24f..b9ea9b4 100644 (file)
@@ -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