[msan] Implement MSAN_OPTIONS=print_stats=1.
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Wed, 21 May 2014 09:56:28 +0000 (09:56 +0000)
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Wed, 21 May 2014 09:56:28 +0000 (09:56 +0000)
llvm-svn: 209287

compiler-rt/lib/msan/msan.cc
compiler-rt/lib/msan/msan.h
compiler-rt/lib/msan/msan_flags.h
compiler-rt/lib/msan/msan_linux.cc
compiler-rt/lib/msan/msan_report.cc
compiler-rt/test/msan/print_stats.cc [new file with mode: 0644]

index 308be46..058ef7e 100644 (file)
@@ -143,6 +143,7 @@ static void ParseFlagsFromString(Flags *f, const char *str) {
 
   ParseFlag(str, &f->report_umrs, "report_umrs", "");
   ParseFlag(str, &f->wrap_signals, "wrap_signals", "");
+  ParseFlag(str, &f->print_stats, "print_stats", "");
 
   // keep_going is an old name for halt_on_error,
   // and it has inverse meaning.
@@ -171,6 +172,7 @@ static void InitializeFlags(Flags *f, const char *options) {
   f->origin_history_per_stack_limit = 20000;
   f->report_umrs = true;
   f->wrap_signals = true;
+  f->print_stats = false;
   f->halt_on_error = !&__msan_keep_going;
 
   // Override from user-specified string.
@@ -331,6 +333,8 @@ void __msan_warning() {
   (void)sp;
   PrintWarning(pc, bp);
   if (__msan::flags()->halt_on_error) {
+    if (__msan::flags()->print_stats)
+      ReportStats();
     Printf("Exiting\n");
     Die();
   }
@@ -340,6 +344,8 @@ void __msan_warning_noreturn() {
   GET_CALLER_PC_BP_SP;
   (void)sp;
   PrintWarning(pc, bp);
+  if (__msan::flags()->print_stats)
+    ReportStats();
   Printf("Exiting\n");
   Die();
 }
index 65e233c..e8b25e3 100644 (file)
@@ -76,6 +76,7 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,
 
 void ReportUMR(StackTrace *stack, u32 origin);
 void ReportExpectedUMRNotFound(StackTrace *stack);
+void ReportStats();
 void ReportAtExitStatistics();
 void DescribeMemoryRange(const void *x, uptr size);
 void ReportUMRInsideAddressRange(const char *what, const void *start, uptr size,
index a506bbe..47ac7e4 100644 (file)
@@ -27,6 +27,7 @@ struct Flags {
   bool poison_in_free;  // default: true
   bool report_umrs;
   bool wrap_signals;
+  bool print_stats;
   bool halt_on_error;
 };
 
index 2582ee2..72f7c59 100644 (file)
@@ -92,6 +92,8 @@ void MsanDie() {
 static void MsanAtExit(void) {
   if (msan_report_count > 0) {
     ReportAtExitStatistics();
+    if (flags()->print_stats)
+      ReportStats();
     if (flags()->exit_code)
       _exit(flags()->exit_code);
   }
index 118e164..ee8c2b2 100644 (file)
@@ -115,6 +115,24 @@ void ReportExpectedUMRNotFound(StackTrace *stack) {
   stack->Print();
 }
 
+void ReportStats() {
+  SpinMutexLock l(&CommonSanitizerReportMutex);
+
+  if (__msan_get_track_origins() > 0) {
+    StackDepotStats *stack_depot_stats = StackDepotGetStats();
+    // FIXME: we want this at normal exit, too!
+    // FIXME: but only with verbosity=1 or something
+    Printf("Unique heap origins: %zu\n", stack_depot_stats->n_uniq_ids);
+    Printf("Stack depot allocated bytes: %zu\n", stack_depot_stats->allocated);
+
+    StackDepotStats *chained_origin_depot_stats = ChainedOriginDepotGetStats();
+    Printf("Unique origin histories: %zu\n",
+           chained_origin_depot_stats->n_uniq_ids);
+    Printf("History depot allocated bytes: %zu\n",
+           chained_origin_depot_stats->allocated);
+  }
+}
+
 void ReportAtExitStatistics() {
   SpinMutexLock l(&CommonSanitizerReportMutex);
 
@@ -124,18 +142,6 @@ void ReportAtExitStatistics() {
     Printf("MemorySanitizer: %d warnings reported.\n", msan_report_count);
     Printf("%s", d.End());
   }
-
-  StackDepotStats *stack_depot_stats = StackDepotGetStats();
-  // FIXME: we want this at normal exit, too!
-  // FIXME: but only with verbosity=1 or something
-  Printf("Unique heap origins: %zu\n", stack_depot_stats->n_uniq_ids);
-  Printf("Stack depot allocated bytes: %zu\n", stack_depot_stats->allocated);
-
-  StackDepotStats *chained_origin_depot_stats = ChainedOriginDepotGetStats();
-  Printf("Unique origin histories: %zu\n",
-         chained_origin_depot_stats->n_uniq_ids);
-  Printf("History depot allocated bytes: %zu\n",
-         chained_origin_depot_stats->allocated);
 }
 
 class OriginSet {
diff --git a/compiler-rt/test/msan/print_stats.cc b/compiler-rt/test/msan/print_stats.cc
new file mode 100644 (file)
index 0000000..bee364b
--- /dev/null
@@ -0,0 +1,43 @@
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -g %s -o %t 
+// RUN: %run %t 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK --check-prefix=CHECK-NOSTATS %s
+// RUN: MSAN_OPTIONS=print_stats=1 %run %t 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK --check-prefix=CHECK-NOSTATS %s
+
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -g -DPOSITIVE=1 %s -o %t 
+// RUN: not %run %t 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK --check-prefix=CHECK-NOSTATS %s
+// RUN: MSAN_OPTIONS=print_stats=1 not %run %t 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK --check-prefix=CHECK-STATS %s
+
+// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -m64 -g -DPOSITIVE=1 -mllvm -msan-keep-going=1 %s -o %t 
+// RUN: not %run %t 2>&1 | \
+// RUN:  FileCheck --check-prefix=CHECK --check-prefix=CHECK-NOSTATS --check-prefix=CHECK-KEEPGOING %s
+// RUN: MSAN_OPTIONS=print_stats=1 not %run %t 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK --check-prefix=CHECK-STATS --check-prefix=CHECK-KEEPGOING %s
+
+#include <stdio.h>
+int main(int argc, char **argv) {
+  int x;
+  int *volatile p = &x;
+  fprintf(stderr, "TEST\n");
+#ifdef POSITIVE
+  return *p;
+#else
+  return 0;
+#endif
+}
+
+// CHECK: TEST
+
+// CHECK-KEEPGOING: MemorySanitizer: 1 warnings reported.
+
+// CHECK-STATS: Unique heap origins:
+// CHECK-STATS: Stack depot allocated bytes:
+// CHECK-STATS: Unique origin histories:
+// CHECK-STATS: History depot allocated bytes:
+
+// CHECK-NOSTATS-NOT: Unique heap origins:
+// CHECK-NOSTATS-NOT: Stack depot allocated bytes:
+// CHECK-NOSTATS-NOT: Unique origin histories:
+// CHECK-NOSTATS-NOT: History depot allocated bytes: