-
Notifications
You must be signed in to change notification settings - Fork 11.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[compiler-rt] Realtime Sanitizer: Introduce Realtime Sanitizer (RTSan…
…) backend (#92460) Introducing the main runtime of realtime sanitizer. For more information, please see the [discourse thread](https://discourse.llvm.org/t/rfc-nolock-and-noalloc-attributes/76837). We have also put together a [reviewer support document](https://github.com/realtime-sanitizer/radsan/blob/doc/review-support/doc/review.md) to show what our intention is. This review introduces the sanitizer backend. This includes: * CMake build files (largely adapted from asan). * Main RTSan architecture (the external API, thread local context, stack). * Interceptors. * Many unit tests. Please see the [reviewer support document](https://github.com/realtime-sanitizer/radsan/blob/doc/review-support/doc/review.md) for what our next steps are. We are moving in lockstep with this PR #84983 for the codegen coming up next. Note to reviewers: If you see support documentation mention "RADSan", this was the "old acronym" for the realtime sanitizer, they refer to the same thing. If you see it let us know and we can correct it (especially in the llvm codebase) --------- Co-authored-by: David Trevelyan <[email protected]>
- Loading branch information
1 parent
8492ad5
commit 1adb55b
Showing
23 changed files
with
1,939 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,3 +67,7 @@ D: ThreadSanitizer | |
N: Bill Wendling | ||
E: [email protected] | ||
D: Profile runtime library | ||
|
||
N: Christopher Apple, David Trevelyan | ||
E: [email protected], [email protected] | ||
D: Realtime Sanitizer (RTSan) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
include_directories(..) | ||
|
||
set(RTSAN_CXX_SOURCES | ||
rtsan.cpp | ||
rtsan_context.cpp | ||
rtsan_stack.cpp | ||
rtsan_interceptors.cpp) | ||
|
||
set(RTSAN_PREINIT_SOURCES | ||
rtsan_preinit.cpp) | ||
|
||
set(RTSAN_HEADERS | ||
rtsan.h | ||
rtsan_context.h | ||
rtsan_stack.h) | ||
|
||
set(RTSAN_DEPS) | ||
|
||
set(RTSAN_CFLAGS | ||
${COMPILER_RT_COMMON_CFLAGS} | ||
${COMPILER_RT_CXX_CFLAGS} | ||
-DSANITIZER_COMMON_NO_REDEFINE_BUILTINS) | ||
set(RTSAN_LINK_FLAGS ${COMPILER_RT_COMMON_LINK_FLAGS}) | ||
set(RTSAN_LINK_LIBS | ||
${COMPILER_RT_UNWINDER_LINK_LIBS} | ||
${COMPILER_RT_CXX_LINK_LIBS}) | ||
|
||
if(APPLE) | ||
add_compiler_rt_object_libraries(RTRtsan | ||
OS ${SANITIZER_COMMON_SUPPORTED_OS} | ||
ARCHS ${RTSAN_SUPPORTED_ARCH} | ||
SOURCES ${RTSAN_CXX_SOURCES} | ||
ADDITIONAL_HEADERS ${RTSAN_HEADERS} | ||
CFLAGS ${RTSAN_CFLAGS} | ||
DEPS ${RTSAN_DEPS}) | ||
else() | ||
add_compiler_rt_object_libraries(RTRtsan | ||
ARCHS ${RTSAN_SUPPORTED_ARCH} | ||
SOURCES ${RTSAN_CXX_SOURCES} | ||
ADDITIONAL_HEADERS ${RTSAN_HEADERS} | ||
CFLAGS ${RTSAN_CFLAGS} | ||
DEPS ${RTSAN_DEPS}) | ||
add_compiler_rt_object_libraries(RTRtsan_preinit | ||
ARCHS ${RTSAN_SUPPORTED_ARCH} | ||
SOURCES ${RTSAN_PREINIT_SOURCES} | ||
ADDITIONAL_HEADERS ${RTSAN_HEADERS} | ||
CFLAGS ${RTSAN_CFLAGS}) | ||
endif() | ||
|
||
set(RTSAN_COMMON_RUNTIME_OBJECT_LIBS | ||
RTInterception | ||
RTSanitizerCommon | ||
RTSanitizerCommonLibc | ||
RTSanitizerCommonCoverage | ||
RTSanitizerCommonSymbolizer) | ||
|
||
append_list_if(COMPILER_RT_HAS_LIBDL dl RTSAN_LINK_LIBS) | ||
append_list_if(COMPILER_RT_HAS_LIBRT rt RTSAN_LINK_LIBS) | ||
append_list_if(COMPILER_RT_HAS_LIBM m RTSAN_LINK_LIBS) | ||
append_list_if(COMPILER_RT_HAS_LIBPTHREAD pthread RTSAN_LINK_LIBS) | ||
append_list_if(COMPILER_RT_HAS_LIBLOG log RTSAN_LINK_LIBS) | ||
|
||
add_compiler_rt_component(rtsan) | ||
|
||
if (APPLE) | ||
add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINK_FLAGS) | ||
set(RTSAN_LINK_FLAGS ${RTSAN_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS}) | ||
|
||
add_compiler_rt_runtime(clang_rt.rtsan | ||
SHARED | ||
OS ${SANITIZER_COMMON_SUPPORTED_OS} | ||
ARCHS ${RTSAN_SUPPORTED_ARCH} | ||
OBJECT_LIBS RTRtsan | ||
${RTSAN_COMMON_RUNTIME_OBJECT_LIBS} | ||
LINK_FLAGS ${RTSAN_LINK_FLAGS} | ||
LINK_LIBS ${RTSAN_LINK_LIBS} | ||
PARENT_TARGET rtsan) | ||
else() | ||
add_compiler_rt_runtime(clang_rt.rtsan | ||
STATIC | ||
ARCHS ${RTSAN_SUPPORTED_ARCH} | ||
OBJECT_LIBS RTRtsan_preinit | ||
RTRtsan | ||
${RTSAN_COMMON_RUNTIME_OBJECT_LIBS} | ||
LINK_FLAGS ${RTSAN_LINK_FLAGS} | ||
CFLAGS ${RTSAN_CFLAGS} | ||
PARENT_TARGET rtsan) | ||
endif() | ||
|
||
if(COMPILER_RT_INCLUDE_TESTS) | ||
add_subdirectory(tests) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
//===--- rtsan.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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include <rtsan/rtsan.h> | ||
#include <rtsan/rtsan_context.h> | ||
#include <rtsan/rtsan_interceptors.h> | ||
|
||
extern "C" { | ||
|
||
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_init() { | ||
__rtsan::InitializeInterceptors(); | ||
} | ||
|
||
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_realtime_enter() { | ||
__rtsan::GetContextForThisThread().RealtimePush(); | ||
} | ||
|
||
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_realtime_exit() { | ||
__rtsan::GetContextForThisThread().RealtimePop(); | ||
} | ||
|
||
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_off() { | ||
__rtsan::GetContextForThisThread().BypassPush(); | ||
} | ||
|
||
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_on() { | ||
__rtsan::GetContextForThisThread().BypassPop(); | ||
} | ||
|
||
} // extern "C" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
//===--- rtsan.h - 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#pragma once | ||
|
||
#include "sanitizer_common/sanitizer_internal_defs.h" | ||
|
||
extern "C" { | ||
|
||
// Initialise rtsan interceptors. | ||
// A call to this method is added to the preinit array on Linux systems. | ||
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_init(); | ||
|
||
// Enter real-time context. | ||
// When in a real-time context, RTSan interceptors will error if realtime | ||
// violations are detected. Calls to this method are injected at the code | ||
// generation stage when RTSan is enabled. | ||
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_realtime_enter(); | ||
|
||
// Exit the real-time context. | ||
// When not in a real-time context, RTSan interceptors will simply forward | ||
// intercepted method calls to the real methods. | ||
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_realtime_exit(); | ||
|
||
// Disable all RTSan error reporting. | ||
// Injected into the code if "nosanitize(realtime)" is on a function. | ||
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_off(); | ||
|
||
// Re-enable all RTSan error reporting. | ||
// The counterpart to `__rtsan_off`. | ||
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_on(); | ||
|
||
} // extern "C" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
//===--- rtsan_context.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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include <rtsan/rtsan_context.h> | ||
|
||
#include <rtsan/rtsan_stack.h> | ||
|
||
#include <sanitizer_common/sanitizer_allocator_internal.h> | ||
#include <sanitizer_common/sanitizer_stacktrace.h> | ||
|
||
#include <new> | ||
#include <pthread.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
static pthread_key_t context_key; | ||
static pthread_once_t key_once = PTHREAD_ONCE_INIT; | ||
|
||
// InternalFree cannot be passed directly to pthread_key_create | ||
// because it expects a signature with only one arg | ||
static void InternalFreeWrapper(void *ptr) { __sanitizer::InternalFree(ptr); } | ||
|
||
static __rtsan::Context &GetContextForThisThreadImpl() { | ||
auto make_thread_local_context_key = []() { | ||
CHECK_EQ(pthread_key_create(&context_key, InternalFreeWrapper), 0); | ||
}; | ||
|
||
pthread_once(&key_once, make_thread_local_context_key); | ||
__rtsan::Context *current_thread_context = | ||
static_cast<__rtsan::Context *>(pthread_getspecific(context_key)); | ||
if (current_thread_context == nullptr) { | ||
current_thread_context = static_cast<__rtsan::Context *>( | ||
__sanitizer::InternalAlloc(sizeof(__rtsan::Context))); | ||
new (current_thread_context) __rtsan::Context(); | ||
pthread_setspecific(context_key, current_thread_context); | ||
} | ||
|
||
return *current_thread_context; | ||
} | ||
|
||
/* | ||
This is a placeholder stub for a future feature that will allow | ||
a user to configure RTSan's behaviour when a real-time safety | ||
violation is detected. The RTSan developers intend for the | ||
following choices to be made available, via a RTSAN_OPTIONS | ||
environment variable, in a future PR: | ||
i) exit, | ||
ii) continue, or | ||
iii) wait for user input from stdin. | ||
Until then, and to keep the first PRs small, only the exit mode | ||
is available. | ||
*/ | ||
static void InvokeViolationDetectedAction() { exit(EXIT_FAILURE); } | ||
|
||
__rtsan::Context::Context() = default; | ||
|
||
void __rtsan::Context::RealtimePush() { realtime_depth++; } | ||
|
||
void __rtsan::Context::RealtimePop() { realtime_depth--; } | ||
|
||
void __rtsan::Context::BypassPush() { bypass_depth++; } | ||
|
||
void __rtsan::Context::BypassPop() { bypass_depth--; } | ||
|
||
void __rtsan::Context::ExpectNotRealtime( | ||
const char *intercepted_function_name) { | ||
if (InRealtimeContext() && !IsBypassed()) { | ||
BypassPush(); | ||
PrintDiagnostics(intercepted_function_name); | ||
InvokeViolationDetectedAction(); | ||
BypassPop(); | ||
} | ||
} | ||
|
||
bool __rtsan::Context::InRealtimeContext() const { return realtime_depth > 0; } | ||
|
||
bool __rtsan::Context::IsBypassed() const { return bypass_depth > 0; } | ||
|
||
void __rtsan::Context::PrintDiagnostics(const char *intercepted_function_name) { | ||
fprintf(stderr, | ||
"Real-time violation: intercepted call to real-time unsafe function " | ||
"`%s` in real-time context! Stack trace:\n", | ||
intercepted_function_name); | ||
__rtsan::PrintStackTrace(); | ||
} | ||
|
||
__rtsan::Context &__rtsan::GetContextForThisThread() { | ||
return GetContextForThisThreadImpl(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
//===--- rtsan_context.h - 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#pragma once | ||
|
||
namespace __rtsan { | ||
|
||
class Context { | ||
public: | ||
Context(); | ||
|
||
void RealtimePush(); | ||
void RealtimePop(); | ||
|
||
void BypassPush(); | ||
void BypassPop(); | ||
|
||
void ExpectNotRealtime(const char *intercepted_function_name); | ||
|
||
private: | ||
bool InRealtimeContext() const; | ||
bool IsBypassed() const; | ||
void PrintDiagnostics(const char *intercepted_function_name); | ||
|
||
int realtime_depth{0}; | ||
int bypass_depth{0}; | ||
}; | ||
|
||
Context &GetContextForThisThread(); | ||
|
||
} // namespace __rtsan |
Oops, something went wrong.