[compiler-rt] [llvm] [compiler-rt][rtsan] Introduce RTSAN_OPTIONS and flags (PR #107174)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 3 18:18:49 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

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

Author: Chris Apple (cjappl)

<details>
<summary>Changes</summary>

All of this matches boilerplate you can find in the other sanitizers. 

This allows us to specify some of the existing flags like:
* abort_on_error - get better stack traces on mac, speed up our unit tests
* verbosity - help debugging
* color - colorized output reports


In the future we will want custom flags, such as:
* halt_on_error - continue mode, matching other sanitizers name for this
* print_exit_stats - how many rt violations occurred during continue mode?? 
* json_output - ??

This lays down the basics necessary to do these in the future

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


12 Files Affected:

- (modified) compiler-rt/lib/rtsan/CMakeLists.txt (+5-1) 
- (modified) compiler-rt/lib/rtsan/rtsan.cpp (+6) 
- (modified) compiler-rt/lib/rtsan/rtsan_context.cpp (+2) 
- (added) compiler-rt/lib/rtsan/rtsan_flags.cpp (+66) 
- (added) compiler-rt/lib/rtsan/rtsan_flags.h (+29) 
- (added) compiler-rt/lib/rtsan/rtsan_flags.inc (+20) 
- (modified) compiler-rt/lib/rtsan/rtsan_stack.cpp (-12) 
- (modified) compiler-rt/lib/rtsan/tests/rtsan_test_context.cpp (+16-10) 
- (added) compiler-rt/test/rtsan/unrecognized_flags.cpp (+11) 
- (modified) llvm/test/Unit/lit.cfg.py (+1) 
- (modified) llvm/utils/lit/lit/TestingConfig.py (+1) 
- (modified) llvm/utils/lit/lit/llvm/config.py (+1) 


``````````diff
diff --git a/compiler-rt/lib/rtsan/CMakeLists.txt b/compiler-rt/lib/rtsan/CMakeLists.txt
index bd7358e86e59b1..3f146a757a97eb 100644
--- a/compiler-rt/lib/rtsan/CMakeLists.txt
+++ b/compiler-rt/lib/rtsan/CMakeLists.txt
@@ -3,6 +3,7 @@ include_directories(..)
 set(RTSAN_CXX_SOURCES
   rtsan.cpp
   rtsan_context.cpp
+  rtsan_flags.cpp
   rtsan_stack.cpp
   rtsan_interceptors.cpp)
 
@@ -12,7 +13,10 @@ set(RTSAN_PREINIT_SOURCES
 set(RTSAN_HEADERS
   rtsan.h
   rtsan_context.h
-  rtsan_stack.h)
+  rtsan_flags.h
+  rtsan_flags.inc
+  rtsan_stack.h
+  )
 
 set(RTSAN_DEPS)
 
diff --git a/compiler-rt/lib/rtsan/rtsan.cpp b/compiler-rt/lib/rtsan/rtsan.cpp
index 1388ce66cbde22..f929c9ae81c11b 100644
--- a/compiler-rt/lib/rtsan/rtsan.cpp
+++ b/compiler-rt/lib/rtsan/rtsan.cpp
@@ -10,9 +10,11 @@
 
 #include <rtsan/rtsan.h>
 #include <rtsan/rtsan_context.h>
+#include <rtsan/rtsan_flags.h>
 #include <rtsan/rtsan_interceptors.h>
 
 #include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_mutex.h"
 
 using namespace __rtsan;
@@ -29,7 +31,11 @@ extern "C" {
 
 SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_init() {
   CHECK(!__rtsan_is_initialized());
+
+  SanitizerToolName = "RealtimeSanitizer";
+  InitializeFlags();
   InitializeInterceptors();
+
   SetInitialized();
 }
 
diff --git a/compiler-rt/lib/rtsan/rtsan_context.cpp b/compiler-rt/lib/rtsan/rtsan_context.cpp
index 97f18dfbbcca8e..a49b70360babbd 100644
--- a/compiler-rt/lib/rtsan/rtsan_context.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_context.cpp
@@ -8,6 +8,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include <rtsan/rtsan.h>
 #include <rtsan/rtsan_context.h>
 
 #include <rtsan/rtsan_stack.h>
@@ -75,6 +76,7 @@ void __rtsan::Context::BypassPop() { bypass_depth_--; }
 
 void __rtsan::ExpectNotRealtime(Context &context,
                                 const char *intercepted_function_name) {
+  CHECK(__rtsan_is_initialized());
   if (context.InRealtimeContext() && !context.IsBypassed()) {
     context.BypassPush();
 
diff --git a/compiler-rt/lib/rtsan/rtsan_flags.cpp b/compiler-rt/lib/rtsan/rtsan_flags.cpp
new file mode 100644
index 00000000000000..a81b5fc6bd77af
--- /dev/null
+++ b/compiler-rt/lib/rtsan/rtsan_flags.cpp
@@ -0,0 +1,66 @@
+//===--- rtsan_flags.cpp - Realtime Sanitizer -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of RealtimeSanitizer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "rtsan/rtsan_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_flags.h"
+
+using namespace __sanitizer;
+using namespace __rtsan;
+
+Flags __rtsan::flags_data;
+
+SANITIZER_INTERFACE_WEAK_DEF(const char *, __rtsan_default_options, void) {
+  return "";
+}
+
+static void RegisterRtsanFlags(FlagParser *parser, Flags *f) {
+#define RTSAN_FLAG(Type, Name, DefaultValue, Description)                      \
+  RegisterFlag(parser, #Name, Description, &f->Name);
+#include "rtsan_flags.inc"
+#undef RTSAN_FLAG
+}
+
+void Flags::SetDefaults() {
+#define RTSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+#include "rtsan_flags.inc"
+#undef RTSAN_FLAG
+}
+
+void __rtsan::InitializeFlags() {
+  SetCommonFlagsDefaults();
+  {
+    CommonFlags cf;
+    cf.CopyFrom(*common_flags());
+    cf.external_symbolizer_path = GetEnv("RTSAN_SYMBOLIZER_PATH");
+    OverrideCommonFlags(cf);
+  }
+
+  flags().SetDefaults();
+
+  FlagParser parser;
+  RegisterRtsanFlags(&parser, &flags());
+  RegisterCommonFlags(&parser);
+
+  // Override from user-specified string.
+  parser.ParseString(__rtsan_default_options());
+
+  parser.ParseStringFromEnv("RTSAN_OPTIONS");
+
+  InitializeCommonFlags();
+
+  if (Verbosity())
+    ReportUnrecognizedFlags();
+
+  if (common_flags()->help)
+    parser.PrintFlagDescriptions();
+}
diff --git a/compiler-rt/lib/rtsan/rtsan_flags.h b/compiler-rt/lib/rtsan/rtsan_flags.h
new file mode 100644
index 00000000000000..30d7fefa5fe155
--- /dev/null
+++ b/compiler-rt/lib/rtsan/rtsan_flags.h
@@ -0,0 +1,29 @@
+//===----------------------- rtsan_flags.h ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of RealtimeSanitizer.
+//
+//===----------------------------------------------------------------------===//
+#pragma once
+
+namespace __rtsan {
+
+struct Flags {
+#define RTSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "rtsan_flags.inc"
+#undef RTSAN_FLAG
+
+  void SetDefaults();
+};
+
+extern Flags flags_data;
+inline Flags &flags() { return flags_data; }
+
+void InitializeFlags();
+
+} // namespace __rtsan
diff --git a/compiler-rt/lib/rtsan/rtsan_flags.inc b/compiler-rt/lib/rtsan/rtsan_flags.inc
new file mode 100644
index 00000000000000..93b0294313672f
--- /dev/null
+++ b/compiler-rt/lib/rtsan/rtsan_flags.inc
@@ -0,0 +1,20 @@
+//===------------------------ rtsan_flags.inc -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// RTSan runtime flags.
+//
+//===----------------------------------------------------------------------===//
+#ifndef RTSAN_FLAG
+#error "Define RTSAN_FLAG prior to including this file!"
+#endif
+
+// RTSAN_FLAG(Type, Name, DefaultValue, Description)
+// See COMMON_FLAG in sanitizer_flags.inc for more details.
+
+// Example flag, until we get a real one
+// RTSAN_FLAG(bool, halt_on_error, true, "If true, halt the program on error")
diff --git a/compiler-rt/lib/rtsan/rtsan_stack.cpp b/compiler-rt/lib/rtsan/rtsan_stack.cpp
index 0598af2337ed18..aeb6a2a3cbd7e2 100644
--- a/compiler-rt/lib/rtsan/rtsan_stack.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_stack.cpp
@@ -29,21 +29,9 @@ void BufferedStackTrace::UnwindImpl(uptr pc, uptr bp, void *context,
 }
 } // namespace __sanitizer
 
-static void SetGlobalStackTraceFormat() {
-  SetCommonFlagsDefaults();
-  CommonFlags cf;
-  cf.CopyFrom(*common_flags());
-  cf.stack_trace_format = "DEFAULT";
-  cf.external_symbolizer_path = GetEnv("RTSAN_SYMBOLIZER_PATH");
-  OverrideCommonFlags(cf);
-}
-
 void __rtsan::PrintStackTrace(uptr pc, uptr bp) {
-
   BufferedStackTrace stack{};
 
   stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal);
-
-  SetGlobalStackTraceFormat();
   stack.Print();
 }
diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_context.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_context.cpp
index cad8cf2d539960..6b9d7e2df123c1 100644
--- a/compiler-rt/lib/rtsan/tests/rtsan_test_context.cpp
+++ b/compiler-rt/lib/rtsan/tests/rtsan_test_context.cpp
@@ -10,31 +10,37 @@
 
 #include "rtsan_test_utilities.h"
 
-#include "rtsan_context.h"
+#include "rtsan/rtsan.h"
+#include "rtsan/rtsan_context.h"
 
-TEST(TestRtsanContext, CanCreateContext) { __rtsan::Context context{}; }
+#include <gtest/gtest.h>
 
-TEST(TestRtsanContext, ExpectNotRealtimeDoesNotDieBeforeRealtimePush) {
+class TestRtsanContext : public ::testing::Test {
+protected:
+  void SetUp() override { __rtsan_ensure_initialized(); }
+};
+
+TEST_F(TestRtsanContext, ExpectNotRealtimeDoesNotDieBeforeRealtimePush) {
   __rtsan::Context context{};
   ExpectNotRealtime(context, "do_some_stuff");
 }
 
-TEST(TestRtsanContext, ExpectNotRealtimeDoesNotDieAfterPushAndPop) {
+TEST_F(TestRtsanContext, ExpectNotRealtimeDoesNotDieAfterPushAndPop) {
   __rtsan::Context context{};
   context.RealtimePush();
   context.RealtimePop();
   ExpectNotRealtime(context, "do_some_stuff");
 }
 
-TEST(TestRtsanContext, ExpectNotRealtimeDiesAfterRealtimePush) {
+TEST_F(TestRtsanContext, ExpectNotRealtimeDiesAfterRealtimePush) {
   __rtsan::Context context{};
 
   context.RealtimePush();
   EXPECT_DEATH(ExpectNotRealtime(context, "do_some_stuff"), "");
 }
 
-TEST(TestRtsanContext,
-     ExpectNotRealtimeDiesAfterRealtimeAfterMorePushesThanPops) {
+TEST_F(TestRtsanContext,
+       ExpectNotRealtimeDiesAfterRealtimeAfterMorePushesThanPops) {
   __rtsan::Context context{};
 
   context.RealtimePush();
@@ -45,7 +51,7 @@ TEST(TestRtsanContext,
   EXPECT_DEATH(ExpectNotRealtime(context, "do_some_stuff"), "");
 }
 
-TEST(TestRtsanContext, ExpectNotRealtimeDoesNotDieAfterBypassPush) {
+TEST_F(TestRtsanContext, ExpectNotRealtimeDoesNotDieAfterBypassPush) {
   __rtsan::Context context{};
 
   context.RealtimePush();
@@ -53,8 +59,8 @@ TEST(TestRtsanContext, ExpectNotRealtimeDoesNotDieAfterBypassPush) {
   ExpectNotRealtime(context, "do_some_stuff");
 }
 
-TEST(TestRtsanContext,
-     ExpectNotRealtimeDoesNotDieIfBypassDepthIsGreaterThanZero) {
+TEST_F(TestRtsanContext,
+       ExpectNotRealtimeDoesNotDieIfBypassDepthIsGreaterThanZero) {
   __rtsan::Context context{};
 
   context.RealtimePush();
diff --git a/compiler-rt/test/rtsan/unrecognized_flags.cpp b/compiler-rt/test/rtsan/unrecognized_flags.cpp
new file mode 100644
index 00000000000000..9e44e9f4299368
--- /dev/null
+++ b/compiler-rt/test/rtsan/unrecognized_flags.cpp
@@ -0,0 +1,11 @@
+// RUN: %clangxx -fsanitize=realtime %s -o %t
+// RUN: RTSAN_OPTIONS="verbosity=1,asdf=1" %run %t 2>&1 | FileCheck %s
+// UNSUPPORTED: ios
+
+// Intent: Make sure we are respecting some basic common flags
+
+int main() {
+  return 0;
+  // CHECK: WARNING: found 1 unrecognized flag(s):
+  // CHECK-NEXT: {{.*asdf*}}
+}
diff --git a/llvm/test/Unit/lit.cfg.py b/llvm/test/Unit/lit.cfg.py
index 61296d7ea0032e..f1646d1b894cde 100644
--- a/llvm/test/Unit/lit.cfg.py
+++ b/llvm/test/Unit/lit.cfg.py
@@ -47,6 +47,7 @@
     "ASAN_OPTIONS",
     "HWASAN_OPTIONS",
     "MSAN_OPTIONS",
+    "RTSAN_OPTIONS",
     "TSAN_OPTIONS",
     "UBSAN_OPTIONS",
 ]:
diff --git a/llvm/utils/lit/lit/TestingConfig.py b/llvm/utils/lit/lit/TestingConfig.py
index 9d8e93460933d8..f81b07baeeaed0 100644
--- a/llvm/utils/lit/lit/TestingConfig.py
+++ b/llvm/utils/lit/lit/TestingConfig.py
@@ -41,6 +41,7 @@ def fromdefaults(litConfig):
             "LSAN_OPTIONS",
             "HWASAN_OPTIONS",
             "MSAN_OPTIONS",
+            "RTSAN_OPTIONS",
             "TSAN_OPTIONS",
             "UBSAN_OPTIONS",
             "ADB",
diff --git a/llvm/utils/lit/lit/llvm/config.py b/llvm/utils/lit/lit/llvm/config.py
index 8a6a0c2ed8089e..5f762ec7f3514a 100644
--- a/llvm/utils/lit/lit/llvm/config.py
+++ b/llvm/utils/lit/lit/llvm/config.py
@@ -83,6 +83,7 @@ def __init__(self, lit_config, config):
                 "UBSAN_SYMBOLIZER_PATH" "ASAN_OPTIONS",
                 "HWASAN_OPTIONS",
                 "MSAN_OPTIONS",
+                "RTSAN_OPTIONS",
                 "TSAN_OPTIONS",
                 "UBSAN_OPTIONS",
             ]

``````````

</details>


https://github.com/llvm/llvm-project/pull/107174


More information about the llvm-commits mailing list