-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[compiler-rt][rtsan] Introduce RTSAN_OPTIONS and flags #107174
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
Conversation
CC @davidtrevelyan for review |
@llvm/pr-subscribers-testing-tools @llvm/pr-subscribers-compiler-rt-sanitizer Author: Chris Apple (cjappl) ChangesAll of this matches boilerplate you can find in the other sanitizers. This allows us to specify some of the existing flags like:
In the future we will want custom flags, such as:
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:
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",
]
|
@@ -29,21 +29,9 @@ void BufferedStackTrace::UnwindImpl(uptr pc, uptr bp, void *context, | |||
} | |||
} // namespace __sanitizer | |||
|
|||
static void SetGlobalStackTraceFormat() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was moved to InitializeFlags
#undef RTSAN_FLAG | ||
} | ||
|
||
void Flags::SetDefaults() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we eliminate this function if we change line 17 of rtsan_flags.h to the following?
#define RTSAN_FLAG(Type, Name, DefaultValue, Description) Type Name { DefaultValue };
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, that is... extremely clever!! I had to think through what these macros are doing to figure out what was going on here.
This does work.
One possible downside of this approach, is the other sanitizers all seem to agree on the other approach, e.g.
> rg "define.*SAN_FLAG\(Type" -B 2
compiler-rt/lib/nsan/nsan_flags.h
16-
17-struct Flags {
18:#define NSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
compiler-rt/lib/nsan/nsan_flags.cpp
26-
27-void Flags::SetDefaults() {
28:#define NSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
...
compiler-rt/lib/asan/asan_flags.h
30-
31-struct Flags {
32:#define ASAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
compiler-rt/lib/asan/asan_flags.cpp
36-
37-void Flags::SetDefaults() {
38:#define ASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
compiler-rt/lib/ubsan/ubsan_flags.h
22-
23-struct Flags {
24:#define UBSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
compiler-rt/lib/ubsan/ubsan_flags.cpp
34-
35-void Flags::SetDefaults() {
36:#define UBSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
Whether this is by design or not, I'm not exactly sure. I want to do a second round of reviews with a broader audience on this one, possibly post-commit where we could ask a question like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have updated this to your proposed version in the latest.
✅ With the latest revision this PR passed the C/C++ code formatter. |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/72/builds/3032 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/146/builds/1085 Here is the relevant piece of the build log for the reference
|
All of this matches boilerplate you can find in the other sanitizers.
This allows us to specify some of the existing flags like:
At some point we will want custom flags, such as:
This lays down the basics necessary to do these in the future