Skip to content

[rtsan] Add statistics for suppression count #112718

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 17, 2024

Conversation

cjappl
Copy link
Contributor

@cjappl cjappl commented Oct 17, 2024

I thought this could be a good debugging tool, if someone passed a suppression file and wondered why their binary wasn't dying.

@llvmbot
Copy link
Member

llvmbot commented Oct 17, 2024

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Chris Apple (cjappl)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/112718.diff

8 Files Affected:

  • (modified) compiler-rt/lib/rtsan/rtsan_assertions.h (+7-2)
  • (modified) compiler-rt/lib/rtsan/rtsan_flags.h (+2)
  • (modified) compiler-rt/lib/rtsan/rtsan_stats.cpp (+13)
  • (modified) compiler-rt/lib/rtsan/rtsan_stats.h (+1)
  • (modified) compiler-rt/lib/rtsan/rtsan_suppressions.cpp (+1-1)
  • (modified) compiler-rt/test/rtsan/exit_stats.cpp (+11)
  • (added) compiler-rt/test/rtsan/exit_stats.cpp.supp (+1)
  • (modified) compiler-rt/test/rtsan/stack_suppressions.cpp (+4-1)
diff --git a/compiler-rt/lib/rtsan/rtsan_assertions.h b/compiler-rt/lib/rtsan/rtsan_assertions.h
index 927b32e03cf026..28a272b6462372 100644
--- a/compiler-rt/lib/rtsan/rtsan_assertions.h
+++ b/compiler-rt/lib/rtsan/rtsan_assertions.h
@@ -15,6 +15,7 @@
 #include "rtsan/rtsan.h"
 #include "rtsan/rtsan_context.h"
 #include "rtsan/rtsan_diagnostics.h"
+#include "rtsan/rtsan_stats.h"
 #include "rtsan/rtsan_suppressions.h"
 
 #include "sanitizer_common/sanitizer_stacktrace.h"
@@ -28,8 +29,10 @@ void ExpectNotRealtime(Context &context, const DiagnosticsInfo &info,
   if (context.InRealtimeContext() && !context.IsBypassed()) {
     ScopedBypass sb{context};
 
-    if (IsFunctionSuppressed(info.func_name))
+    if (IsFunctionSuppressed(info.func_name)) {
+      IncrementSuppressedCount();
       return;
+    }
 
     __sanitizer::BufferedStackTrace stack;
 
@@ -38,8 +41,10 @@ void ExpectNotRealtime(Context &context, const DiagnosticsInfo &info,
     stack.Unwind(info.pc, info.bp, nullptr,
                  __sanitizer::common_flags()->fast_unwind_on_fatal);
 
-    if (IsStackTraceSuppressed(stack))
+    if (IsStackTraceSuppressed(stack)) {
+      IncrementSuppressedCount();
       return;
+    }
 
     OnViolation(stack, info);
   }
diff --git a/compiler-rt/lib/rtsan/rtsan_flags.h b/compiler-rt/lib/rtsan/rtsan_flags.h
index 29025c29b6fc2a..f46e04933fa528 100644
--- a/compiler-rt/lib/rtsan/rtsan_flags.h
+++ b/compiler-rt/lib/rtsan/rtsan_flags.h
@@ -18,6 +18,8 @@ struct Flags {
   Type Name{DefaultValue};
 #include "rtsan_flags.inc"
 #undef RTSAN_FLAG
+
+  bool ContainsSuppresionFile() { return suppressions[0] != '\0'; }
 };
 
 extern Flags flags_data;
diff --git a/compiler-rt/lib/rtsan/rtsan_stats.cpp b/compiler-rt/lib/rtsan/rtsan_stats.cpp
index dac7b23c3ef520..1562b73cf94cd8 100644
--- a/compiler-rt/lib/rtsan/rtsan_stats.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_stats.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "rtsan/rtsan_stats.h"
+#include "rtsan/rtsan_flags.h"
 
 #include "sanitizer_common/sanitizer_atomic.h"
 #include "sanitizer_common/sanitizer_common.h"
@@ -20,6 +21,7 @@ using namespace __rtsan;
 
 static atomic_uint32_t rtsan_total_error_count{0};
 static atomic_uint32_t rtsan_unique_error_count{0};
+static atomic_uint32_t rtsan_suppressed_count{0};
 
 void __rtsan::IncrementTotalErrorCount() {
   atomic_fetch_add(&rtsan_total_error_count, 1, memory_order_relaxed);
@@ -37,9 +39,20 @@ static u32 GetUniqueErrorCount() {
   return atomic_load(&rtsan_unique_error_count, memory_order_relaxed);
 }
 
+void __rtsan::IncrementSuppressedCount() {
+  atomic_fetch_add(&rtsan_suppressed_count, 1, memory_order_relaxed);
+}
+
+static u32 GetSuppressedCount() {
+  return atomic_load(&rtsan_suppressed_count, memory_order_relaxed);
+}
+
 void __rtsan::PrintStatisticsSummary() {
   ScopedErrorReportLock l;
   Printf("RealtimeSanitizer exit stats:\n");
   Printf("    Total error count: %u\n", GetTotalErrorCount());
   Printf("    Unique error count: %u\n", GetUniqueErrorCount());
+
+  if (flags().ContainsSuppresionFile())
+    Printf("    Suppression count: %u\n", GetSuppressedCount());
 }
diff --git a/compiler-rt/lib/rtsan/rtsan_stats.h b/compiler-rt/lib/rtsan/rtsan_stats.h
index a72098792c89c9..a8a67ea2a44b6d 100644
--- a/compiler-rt/lib/rtsan/rtsan_stats.h
+++ b/compiler-rt/lib/rtsan/rtsan_stats.h
@@ -16,6 +16,7 @@ namespace __rtsan {
 
 void IncrementTotalErrorCount();
 void IncrementUniqueErrorCount();
+void IncrementSuppressedCount();
 
 void PrintStatisticsSummary();
 
diff --git a/compiler-rt/lib/rtsan/rtsan_suppressions.cpp b/compiler-rt/lib/rtsan/rtsan_suppressions.cpp
index a7c3d42ac68af9..2bcfbeed4195bc 100644
--- a/compiler-rt/lib/rtsan/rtsan_suppressions.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_suppressions.cpp
@@ -56,7 +56,7 @@ void __rtsan::InitializeSuppressions() {
   CHECK_EQ(nullptr, suppression_ctx);
 
   // We will use suppression_ctx == nullptr as an early out
-  if (flags().suppressions[0] == '\0')
+  if (!flags().ContainsSuppresionFile())
     return;
 
   suppression_ctx = new (suppression_placeholder)
diff --git a/compiler-rt/test/rtsan/exit_stats.cpp b/compiler-rt/test/rtsan/exit_stats.cpp
index d4d19ace778ba5..92ca58f1edde86 100644
--- a/compiler-rt/test/rtsan/exit_stats.cpp
+++ b/compiler-rt/test/rtsan/exit_stats.cpp
@@ -1,6 +1,7 @@
 // RUN: %clangxx -fsanitize=realtime %s -o %t
 // RUN: %env_rtsan_opts="halt_on_error=false,print_stats_on_exit=true" %run %t 2>&1 | FileCheck %s
 // RUN: %env_rtsan_opts="halt_on_error=true,print_stats_on_exit=true" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-HALT
+// RUN: %env_rtsan_opts="suppressions=%s.supp,print_stats_on_exit=true" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-SUPPRESSIONS
 
 // UNSUPPORTED: ios
 
@@ -23,7 +24,17 @@ int main() {
 // CHECK: RealtimeSanitizer exit stats:
 // CHECK-NEXT: Total error count: 10
 // CHECK-NEXT: Unique error count: 1
+// CHECK-NOT: Suppression count
 
 // CHECK-HALT: RealtimeSanitizer exit stats:
 // CHECK-HALT-NEXT: Total error count: 1
 // CHECK-HALT-NEXT: Unique error count: 1
+// CHECK-HALT-NOT: Suppression count
+
+// We pass in intentionally_non_existant_function in the suppressions file
+// This is just to ensure we only get the "Suppression count" metric if this
+// file is passed at runtime, otherwise that statistic is omitted
+// CHECK-SUPPRESSIONS: RealtimeSanitizer exit stats:
+// CHECK-SUPPRESSIONS-NEXT: Total error count: 1
+// CHECK-SUPPRESSIONS-NEXT: Unique error count: 1
+// CHECK-SUPPRESSIONS-NEXT: Suppression count: 0
diff --git a/compiler-rt/test/rtsan/exit_stats.cpp.supp b/compiler-rt/test/rtsan/exit_stats.cpp.supp
new file mode 100644
index 00000000000000..b720bdb770808b
--- /dev/null
+++ b/compiler-rt/test/rtsan/exit_stats.cpp.supp
@@ -0,0 +1 @@
+function-name-matches:intentionally_non_existant_function
diff --git a/compiler-rt/test/rtsan/stack_suppressions.cpp b/compiler-rt/test/rtsan/stack_suppressions.cpp
index b9b2d0957636d9..be1cf4963c7f80 100644
--- a/compiler-rt/test/rtsan/stack_suppressions.cpp
+++ b/compiler-rt/test/rtsan/stack_suppressions.cpp
@@ -1,6 +1,6 @@
 // RUN: %clangxx -fsanitize=realtime %s -o %t
 // RUN: %env_rtsan_opts=halt_on_error=false %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NOSUPPRESSIONS
-// RUN: %env_rtsan_opts=suppressions='%s.supp' not %run %t 2>&1 | FileCheck %s
+// RUN: %env_rtsan_opts=suppressions='%s.supp':print_stats_on_exit=true not %run %t 2>&1 | FileCheck %s
 // UNSUPPORTED: ios
 
 // Intent: Ensure that suppressions work as intended
@@ -61,6 +61,9 @@ int main() {
 // CHECK-NOT: free
 // CHECK-NOT: BlockFunc
 
+// CHECK: RealtimeSanitizer exit stats:
+// CHECK: Suppression count: 7
+
 // CHECK-NOSUPPRESSIONS: malloc
 // CHECK-NOSUPPRESSIONS: vector
 // CHECK-NOSUPPRESSIONS: free

@cjappl cjappl merged commit 8f8d5f0 into llvm:main Oct 17, 2024
10 checks passed
@cjappl cjappl deleted the suppressions_stats branch October 17, 2024 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants