https://github.com/cjappl updated https://github.com/llvm/llvm-project/pull/102622
>From 9d3d49fa755c28b21c3b4771faae65cf418dec5a Mon Sep 17 00:00:00 2001 From: Chris Apple <cja-priv...@pm.me> Date: Wed, 24 Jul 2024 14:25:44 -0700 Subject: [PATCH 1/3] [clang][rtsan] Introduce realtime sanitizer codegen and driver --- clang/include/clang/Basic/Sanitizers.def | 3 ++ clang/include/clang/Driver/SanitizerArgs.h | 1 + clang/lib/CodeGen/BackendUtil.cpp | 8 ++++ clang/lib/CodeGen/CodeGenFunction.cpp | 6 +++ clang/lib/Driver/SanitizerArgs.cpp | 14 ++++-- clang/lib/Driver/ToolChains/CommonArgs.cpp | 6 +++ clang/lib/Driver/ToolChains/Darwin.cpp | 8 ++++ clang/lib/Driver/ToolChains/Linux.cpp | 1 + clang/test/CodeGen/rtsan_attribute_inserted.c | 7 +++ clang/test/CodeGen/rtsan_insert_at_entry.c | 9 ++++ clang/test/CodeGen/rtsan_insert_at_exit.c | 9 ++++ .../rtsan_no_attribute_sanitizer_disabled.c | 8 ++++ clang/test/Driver/fsanitize.c | 46 +++++++++++++++++++ clang/test/Driver/rtsan.c | 14 ++++++ 14 files changed, 135 insertions(+), 5 deletions(-) create mode 100644 clang/test/CodeGen/rtsan_attribute_inserted.c create mode 100644 clang/test/CodeGen/rtsan_insert_at_entry.c create mode 100644 clang/test/CodeGen/rtsan_insert_at_exit.c create mode 100644 clang/test/CodeGen/rtsan_no_attribute_sanitizer_disabled.c create mode 100644 clang/test/Driver/rtsan.c diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def index bee35e9dca7c39..9223f62b3639a7 100644 --- a/clang/include/clang/Basic/Sanitizers.def +++ b/clang/include/clang/Basic/Sanitizers.def @@ -79,6 +79,9 @@ SANITIZER("thread", Thread) // Numerical stability sanitizer. SANITIZER("numerical", NumericalStability) +// RealtimeSanitizer +SANITIZER("realtime", Realtime) + // LeakSanitizer SANITIZER("leak", Leak) diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h index 47ef175302679f..c13a640268f0c7 100644 --- a/clang/include/clang/Driver/SanitizerArgs.h +++ b/clang/include/clang/Driver/SanitizerArgs.h @@ -106,6 +106,7 @@ class SanitizerArgs { bool needsNsanRt() const { return Sanitizers.has(SanitizerKind::NumericalStability); } + bool needsRtsanRt() const { return Sanitizers.has(SanitizerKind::Realtime); } bool hasMemTag() const { return hasMemtagHeap() || hasMemtagStack() || hasMemtagGlobals(); diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 81e6702d5de666..95aa328c0245de 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -78,6 +78,7 @@ #include "llvm/Transforms/Instrumentation/MemorySanitizer.h" #include "llvm/Transforms/Instrumentation/NumericalStabilitySanitizer.h" #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h" +#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h" #include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h" #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" @@ -989,6 +990,13 @@ void EmitAssemblyHelper::RunOptimizationPipeline( FPM.addPass(BoundsCheckingPass()); }); + if (LangOpts.Sanitize.has(SanitizerKind::Realtime)) + PB.registerScalarOptimizerLateEPCallback( + [](FunctionPassManager &FPM, OptimizationLevel Level) { + RealtimeSanitizerOptions Opts; + FPM.addPass(RealtimeSanitizerPass(Opts)); + }); + // Don't add sanitizers if we are here from ThinLTO PostLink. That already // done on PreLink stage. if (!IsThinLTOPostLink) { diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 2b2e23f1e5d7fb..fc388f6f879a1e 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -845,6 +845,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, if (SanOpts.has(SanitizerKind::ShadowCallStack)) Fn->addFnAttr(llvm::Attribute::ShadowCallStack); + if (SanOpts.has(SanitizerKind::Realtime)) { + for (const FunctionEffectWithCondition &Fe : FD->getFunctionEffects()) + if (Fe.Effect.kind() == FunctionEffect::Kind::NonBlocking) + Fn->addFnAttr(llvm::Attribute::SanitizeRealtime); + } + // Apply fuzzing attribute to the function. if (SanOpts.hasOneOf(SanitizerKind::Fuzzer | SanitizerKind::FuzzerNoLink)) Fn->addFnAttr(llvm::Attribute::OptForFuzzing); diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 1fd870b72286e5..7b38f20fc8d059 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -552,11 +552,15 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, SanitizerKind::Leak | SanitizerKind::Thread | SanitizerKind::Memory | SanitizerKind::KernelAddress | SanitizerKind::Scudo | SanitizerKind::SafeStack), - std::make_pair(SanitizerKind::MemTag, - SanitizerKind::Address | SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | - SanitizerKind::KernelHWAddress), - std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function)}; + std::make_pair(SanitizerKind::MemTag, SanitizerKind::Address | + SanitizerKind::KernelAddress | + SanitizerKind::HWAddress | + SanitizerKind::KernelHWAddress), + std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function), + std::make_pair(SanitizerKind::Realtime, + SanitizerKind::Address | SanitizerKind::Thread | + SanitizerKind::Undefined | SanitizerKind::Memory)}; + // Enable toolchain specific default sanitizers if not explicitly disabled. SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove; diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 6e9744607d9ebc..61ec730aa4a5b5 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1431,6 +1431,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, if (!Args.hasArg(options::OPT_shared)) HelperStaticRuntimes.push_back("hwasan-preinit"); } + if (SanArgs.needsRtsanRt() && SanArgs.linkRuntimes()) + SharedRuntimes.push_back("rtsan"); } // The stats_client library is also statically linked into DSOs. @@ -1456,6 +1458,10 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, StaticRuntimes.push_back("asan_cxx"); } + if (!SanArgs.needsSharedRt() && SanArgs.needsRtsanRt() && + SanArgs.linkRuntimes()) + StaticRuntimes.push_back("rtsan"); + if (!SanArgs.needsSharedRt() && SanArgs.needsMemProfRt()) { StaticRuntimes.push_back("memprof"); if (SanArgs.linkCXXRuntimes()) diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index ee6890d5b98f0e..9dfb803e12bbee 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1519,6 +1519,8 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, const char *sanitizer = nullptr; if (Sanitize.needsUbsanRt()) { sanitizer = "UndefinedBehaviorSanitizer"; + } else if (Sanitize.needsRtsanRt()) { + sanitizer = "RealtimeSanitizer"; } else if (Sanitize.needsAsanRt()) { sanitizer = "AddressSanitizer"; } else if (Sanitize.needsTsanRt()) { @@ -1541,6 +1543,11 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, AddLinkSanitizerLibArgs(Args, CmdArgs, "asan"); } } + if (Sanitize.needsRtsanRt()) { + assert(Sanitize.needsSharedRt() && + "Static sanitizer runtimes not supported"); + AddLinkSanitizerLibArgs(Args, CmdArgs, "rtsan"); + } if (Sanitize.needsLsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan"); if (Sanitize.needsUbsanRt()) { @@ -3531,6 +3538,7 @@ SanitizerMask Darwin::getSupportedSanitizers() const { Res |= SanitizerKind::Address; Res |= SanitizerKind::PointerCompare; Res |= SanitizerKind::PointerSubtract; + Res |= SanitizerKind::Realtime; Res |= SanitizerKind::Leak; Res |= SanitizerKind::Fuzzer; Res |= SanitizerKind::FuzzerNoLink; diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index 2265138edbffbe..96680b3412a2db 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -800,6 +800,7 @@ SanitizerMask Linux::getSupportedSanitizers() const { Res |= SanitizerKind::Address; Res |= SanitizerKind::PointerCompare; Res |= SanitizerKind::PointerSubtract; + Res |= SanitizerKind::Realtime; Res |= SanitizerKind::Fuzzer; Res |= SanitizerKind::FuzzerNoLink; Res |= SanitizerKind::KernelAddress; diff --git a/clang/test/CodeGen/rtsan_attribute_inserted.c b/clang/test/CodeGen/rtsan_attribute_inserted.c new file mode 100644 index 00000000000000..ecba06703fee2c --- /dev/null +++ b/clang/test/CodeGen/rtsan_attribute_inserted.c @@ -0,0 +1,7 @@ +// RUN: %clang -target x86_64-unknown-linux -fsanitize=realtime %s -S -emit-llvm -o - | FileCheck %s + +float process(float *a) [[clang::nonblocking]] { return *a; } + +// CHECK-LABEL: @process{{.*}}#0 { +// CHECK: attributes #0 = { +// CHECK-SAME: {{.*sanitize_realtime.*}} diff --git a/clang/test/CodeGen/rtsan_insert_at_entry.c b/clang/test/CodeGen/rtsan_insert_at_entry.c new file mode 100644 index 00000000000000..22d568425cbe74 --- /dev/null +++ b/clang/test/CodeGen/rtsan_insert_at_entry.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -fsanitize=realtime -emit-llvm -o - %s | FileCheck %s + +// The first instruction after the function is entred should be a call to +// enable the realtime sanitizer stack + +int foo(int *a) [[clang::nonblocking]] { return *a; } +// CHECK-LABEL: define{{.*}}@foo +// CHECK-NEXT: entry: +// CHECK-NEXT: call{{.*}}__rtsan_realtime_enter diff --git a/clang/test/CodeGen/rtsan_insert_at_exit.c b/clang/test/CodeGen/rtsan_insert_at_exit.c new file mode 100644 index 00000000000000..32b381f163f595 --- /dev/null +++ b/clang/test/CodeGen/rtsan_insert_at_exit.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -fsanitize=realtime -emit-llvm -o - %s | FileCheck %s + +// __rtsan_realtime_exit should be inserted at all function returns + +int bar(int* x) [[clang::nonblocking]] { + return *x; +} +// CHECK-LABEL: call{{.*}}__rtsan_realtime_exit +// CHECK-NEXT: ret diff --git a/clang/test/CodeGen/rtsan_no_attribute_sanitizer_disabled.c b/clang/test/CodeGen/rtsan_no_attribute_sanitizer_disabled.c new file mode 100644 index 00000000000000..85742d8b63d9ec --- /dev/null +++ b/clang/test/CodeGen/rtsan_no_attribute_sanitizer_disabled.c @@ -0,0 +1,8 @@ +// RUN: %clang -target x86_64-unknown-linux %s -S -emit-llvm -o - | FileCheck %s + + +float process(float *a) [[clang::nonblocking]] { return *a; } + +// Without the -fsanitize=realtime flag, we shouldn't attach +// the attribute +// CHECK-NOT: {{.*sanitize_realtime.*}} diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 678fa432fb0a0a..f86c978f221cd4 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -1040,3 +1040,49 @@ // RUN: not %clang --target=aarch64-none-elf -fsanitize=dataflow %s -### 2>&1 | FileCheck %s -check-prefix=UNSUPPORTED-BAREMETAL // RUN: not %clang --target=arm-arm-none-eabi -fsanitize=shadow-call-stack %s -### 2>&1 | FileCheck %s -check-prefix=UNSUPPORTED-BAREMETAL // UNSUPPORTED-BAREMETAL: unsupported option '-fsanitize={{.*}}' for target + +// RUN: %clang --target=x86_64-apple-darwin -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-X86-64-DARWIN +// CHECK-RTSAN-X86-64-DARWIN-NOT: unsupported option + +// RUN: %clang --target=x86_64-apple-darwin -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-X86-64-DARWIN +// CHECK-RTSAN-X86-64-DARWIN-NOT: unsupported option +// RUN: %clang --target=x86_64-apple-macos -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-X86-64-MACOS +// CHECK-RTSAN-X86-64-MACOS-NOT: unsupported option +// RUN: %clang --target=arm64-apple-macos -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-ARM64-MACOS +// CHECK-RTSAN-ARM64-MACOS-NOT: unsupported option + +// RUN: %clang --target=arm64-apple-ios-simulator -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-ARM64-IOSSIMULATOR +// CHECK-RTSAN-ARM64-IOSSIMULATOR-NOT: unsupported option + +// RUN: %clang --target=arm64-apple-watchos-simulator -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-ARM64-WATCHOSSIMULATOR +// CHECK-RTSAN-ARM64-WATCHOSSIMULATOR-NOT: unsupported option + +// RUN: %clang --target=arm64-apple-tvos-simulator -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-ARM64-TVOSSIMULATOR +// CHECK-RTSAN-ARM64-TVOSSIMULATOR-NOT: unsupported option + +// RUN: %clang --target=x86_64-apple-ios-simulator -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-X86-64-IOSSIMULATOR +// CHECK-RTSAN-X86-64-IOSSIMULATOR-NOT: unsupported option + +// RUN: %clang --target=x86_64-apple-watchos-simulator -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-X86-64-WATCHOSSIMULATOR +// CHECK-RTSAN-X86-64-WATCHOSSIMULATOR-NOT: unsupported option + +// RUN: %clang --target=x86_64-apple-tvos-simulator -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-X86-64-TVOSSIMULATOR +// CHECK-RTSAN-X86-64-TVOSSIMULATOR-NOT: unsupported option + +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-X86-64-LINUX +// CHECK-RTSAN-X86-64-LINUX-NOT: unsupported option + +// RUN: not %clang --target=i386-pc-openbsd -fsanitize=realtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-RTSAN-OPENBSD +// CHECK-RTSAN-OPENBSD: unsupported option '-fsanitize=realtime' for target 'i386-pc-openbsd' + +// RUN: not %clang --target=x86_64-linux-gnu -fsanitize=realtime,thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-REALTIME-TSAN +// CHECK-REALTIME-TSAN: error: invalid argument '-fsanitize=realtime' not allowed with '-fsanitize=thread' + +// RUN: not %clang --target=x86_64-linux-gnu -fsanitize=realtime,address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-REALTIME-ASAN +// CHECK-REALTIME-ASAN: error: invalid argument '-fsanitize=realtime' not allowed with '-fsanitize=address' + +// RUN: not %clang --target=x86_64-linux-gnu -fsanitize=realtime,memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-REALTIME-MSAN +// CHECK-REALTIME-MSAN: error: invalid argument '-fsanitize=realtime' not allowed with '-fsanitize=memory' + +// RUN: not %clang --target=x86_64-linux-gnu -fsanitize=realtime,undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-REALTIME-UBSAN +// CHECK-REALTIME-UBSAN: error: invalid argument '-fsanitize=realtime' not allowed with '-fsanitize=undefined' diff --git a/clang/test/Driver/rtsan.c b/clang/test/Driver/rtsan.c new file mode 100644 index 00000000000000..999e88d066427c --- /dev/null +++ b/clang/test/Driver/rtsan.c @@ -0,0 +1,14 @@ +// RUN: %clang -target x86_64-unknown-linux -fsanitize=realtime %s -S -emit-llvm -o - | FileCheck %s +// RUN: %clang -O1 -target x86_64-unknown-linux -fsanitize=realtime %s -S -emit-llvm -o - | FileCheck %s +// RUN: %clang -O2 -target x86_64-unknown-linux -fsanitize=realtime %s -S -emit-llvm -o - | FileCheck %s +// RUN: %clang -O3 -target x86_64-unknown-linux -fsanitize=realtime %s -S -emit-llvm -o - | FileCheck %s +// RUN: %clang -target x86_64-unknown-linux -fsanitize=realtime %s -S -emit-llvm -flto=thin -o - | FileCheck %s +// RUN: %clang -O2 -target x86_64-unknown-linux -fsanitize=realtime %s -S -emit-llvm -flto=thin -o - | FileCheck %s +// RUN: %clang -target x86_64-unknown-linux -fsanitize=realtime %s -S -emit-llvm -flto -o - | FileCheck %s +// RUN: %clang -O2 -target x86_64-unknown-linux -fsanitize=realtime %s -S -emit-llvm -flto -o - | FileCheck %s + +// Ensure the rtsan_realtime calls are never optimized away + +int foo(int *a) [[clang::nonblocking]] { return *a; } +// CHECK: __rtsan_realtime_enter +// CHECK: __rtsan_realtime_exit >From 57de56187f721fa257ba84923e9f24bd910074b5 Mon Sep 17 00:00:00 2001 From: Chris Apple <cja-priv...@pm.me> Date: Fri, 9 Aug 2024 08:42:22 -0700 Subject: [PATCH 2/3] [PR] Test hasAnyFunctionEffects before iterating --- clang/lib/CodeGen/CodeGenFunction.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index fc388f6f879a1e..364333e780b6d7 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -846,9 +846,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, Fn->addFnAttr(llvm::Attribute::ShadowCallStack); if (SanOpts.has(SanitizerKind::Realtime)) { - for (const FunctionEffectWithCondition &Fe : FD->getFunctionEffects()) - if (Fe.Effect.kind() == FunctionEffect::Kind::NonBlocking) - Fn->addFnAttr(llvm::Attribute::SanitizeRealtime); + if (FD && FD->getASTContext().hasAnyFunctionEffects()) { + for (const FunctionEffectWithCondition &Fe : FD->getFunctionEffects()) { + if (Fe.Effect.kind() == FunctionEffect::Kind::NonBlocking) + Fn->addFnAttr(llvm::Attribute::SanitizeRealtime); + } + } } // Apply fuzzing attribute to the function. >From e047ca614dad3719cd7828d0b688a2186eaff679 Mon Sep 17 00:00:00 2001 From: Chris Apple <cja-priv...@pm.me> Date: Sat, 10 Aug 2024 08:41:31 -0700 Subject: [PATCH 3/3] Documentation draft 1 --- clang/docs/RealtimeSanitizer.rst | 81 ++++++++++++++++++++++++++++++++ clang/docs/ReleaseNotes.rst | 5 ++ 2 files changed, 86 insertions(+) create mode 100644 clang/docs/RealtimeSanitizer.rst diff --git a/clang/docs/RealtimeSanitizer.rst b/clang/docs/RealtimeSanitizer.rst new file mode 100644 index 00000000000000..f9af41467df05f --- /dev/null +++ b/clang/docs/RealtimeSanitizer.rst @@ -0,0 +1,81 @@ +================= +RealtimeSanitizer +================= + +.. contents:: + :local: + +Introduction +============ +RealtimeSanitizer (a.k.a. RTSan) is a real-time safety testing tool for C and +C++ projects. RTSan can be used to detect real-time violations,such as calls to +methods that are not safe for use in functions with deterministic runtime +requirements. + +The tool can detect the following types of real-time violations: + +* System calls +* Allocations +* Exceptions + +These checks are put in place when compiling with the +``-fsanitize=realtime`` flag, for functions marked with +``[[clang::nonblocking]]``. + +.. code-block:: c + void process_audio(float* buffer) [[clang::nonblocking]] { + ... + } + +The runtime slowdown introduced by RealtimeSanitizer is trivial. Code in +real-time contexts without real-time safety violations have no slowdown. + +How to build +============ + +Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>` and enable the +``compiler-rt`` runtime. An example CMake configuration that will allow for the +use/testing of RealtimeSanitizer: + +.. code-block:: console + + $ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_RUNTIMES="compiler-rt" <path to source>/llvm + +Usage +===== + +There are two requirements: +1. The code must be compiled with the ``-fsanitize=realtime`` flag. +2. Functions that are subject to real-time constraints must be + marked with the ``[[clang::nonblocking]]`` attribute. + +Typically, these attributes should be added onto the functions that are entry +points for threads with real-time priority. These threads are subject to a fixed +callback time, such as audio callback threads or rendering loops in video game +code. + +.. code-block:: console + % cat example_realtime_violation.cpp + int main() [[clang::nonblocking]] { + int* p = new int; + return 0; + } + + # Compile and link + % clang -fsanitize=realtime -g example_realtime_violation.cpp + +If a real-time safety violation is detected in a ``[[clang::nonblocking]]`` +context, or any function invoked by that function, the program will exit with a +non-zero exit code. + +.. code-block:: console + % clang -fsanitize=realtime -g example_realtime_violation.cpp + % ./a.out + Real-time violation: intercepted call to real-time unsafe function `malloc` in real-time context! Stack trace: + #0 0x00010065ad9c in __rtsan::PrintStackTrace() rtsan_stack.cpp:45 + #1 0x00010065abcc in __rtsan::Context::ExpectNotRealtime(char const*) rtsan_context.cpp:78 + #2 0x00010065b8d0 in malloc rtsan_interceptors.cpp:289 + #3 0x000195bd7bd0 in operator new(unsigned long)+0x1c (libc++abi.dylib:arm64+0x16bd0) + #4 0xb338001000dbf68 (<unknown module>) + #5 0x0001958960dc (<unknown module>) + #6 0x45737ffffffffffc (<unknown module>) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 6796a619ba97f8..79f721169fdbb2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -349,6 +349,11 @@ Moved checkers Sanitizers ---------- +- Introduced Realtime Sanitizer, activated by using the -fsanitize=realtime + flag. This sanitizer detects unsafe system library calls, such as memory + allocations and mutex locks. If any such function is called during invocation + of a function marked with the ``[[clang::nonblocking]]`` attribute, an error + is printed to the console and the process exits non-zero. Python Binding Changes ---------------------- _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits