https://github.com/cjappl updated https://github.com/llvm/llvm-project/pull/100120
>From e0a1336da28f0f1d9f870be1676991d415160321 Mon Sep 17 00:00:00 2001 From: Chris Apple <cja-priv...@pm.me> Date: Thu, 18 Jul 2024 17:29:01 +0200 Subject: [PATCH 1/2] [rtsan] Introduce rtsan frontend --- clang/include/clang/Basic/Attr.td | 5 ++ clang/include/clang/Basic/Sanitizers.def | 3 ++ clang/include/clang/Driver/SanitizerArgs.h | 1 + clang/lib/CodeGen/CGCall.cpp | 6 +++ clang/lib/CodeGen/CodeGenFunction.cpp | 43 +++++++++++++++++ clang/lib/Driver/SanitizerArgs.cpp | 14 ++++-- clang/lib/Driver/ToolChains/CommonArgs.cpp | 7 +++ clang/lib/Driver/ToolChains/Darwin.cpp | 8 ++++ clang/lib/Driver/ToolChains/Linux.cpp | 1 + clang/test/Driver/fsanitize.c | 48 +++++++++++++++++++ clang/test/Driver/rtsan.c | 12 +++++ compiler-rt/lib/rtsan/rtsan_interceptors.cpp | 4 +- compiler-rt/lib/rtsan/tests/CMakeLists.txt | 15 +++--- compiler-rt/test/rtsan/CMakeLists.txt | 11 ----- compiler-rt/test/rtsan/test_rtsan.cpp | 17 +++++++ .../test/rtsan/test_rtsan_inactive.cpp | 23 +++++++++ .../test/sanitizer_common/CMakeLists.txt | 2 +- .../test/sanitizer_common/lit.common.cfg.py | 3 ++ llvm/include/llvm/Bitcode/LLVMBitCodes.h | 1 + llvm/include/llvm/IR/Attributes.td | 3 ++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 2 + llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 2 + llvm/lib/Transforms/Utils/CodeExtractor.cpp | 1 + 23 files changed, 206 insertions(+), 26 deletions(-) create mode 100644 clang/test/Driver/rtsan.c create mode 100644 compiler-rt/test/rtsan/test_rtsan.cpp create mode 100644 compiler-rt/test/rtsan/test_rtsan_inactive.cpp diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 4825979a974d2..8a4a29d589b9b 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3527,6 +3527,11 @@ def NoSanitize : InheritableAttr { bool hasCoverage() const { return llvm::is_contained(sanitizers(), "coverage"); } + + bool hasRealtime() const { + return llvm::is_contained(sanitizers(), "realtime"); + } + }]; } diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def index bee35e9dca7c3..8a5df643ffa0c 100644 --- a/clang/include/clang/Basic/Sanitizers.def +++ b/clang/include/clang/Basic/Sanitizers.def @@ -37,6 +37,9 @@ #endif +// RealtimeSanitizer +SANITIZER("realtime", Realtime) + // AddressSanitizer SANITIZER("address", Address) diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h index 47ef175302679..6c0df926aec5b 100644 --- a/clang/include/clang/Driver/SanitizerArgs.h +++ b/clang/include/clang/Driver/SanitizerArgs.h @@ -79,6 +79,7 @@ class SanitizerArgs { bool needsStableAbi() const { return StableABI; } bool needsMemProfRt() const { return NeedsMemProfRt; } + bool needsRtsanRt() const { return Sanitizers.has(SanitizerKind::Realtime); } bool needsAsanRt() const { return Sanitizers.has(SanitizerKind::Address); } bool needsHwasanRt() const { return Sanitizers.has(SanitizerKind::HWAddress); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index d582aba679ddc..7af7785515688 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2408,6 +2408,12 @@ void CodeGenModule::ConstructAttributeList(StringRef Name, FuncAttrs.addAttribute(llvm::Attribute::NoReturn); NBA = Fn->getAttr<NoBuiltinAttr>(); } + + for (const FunctionEffectWithCondition &Fe : Fn->getFunctionEffects()) { + if (Fe.Effect.kind() == FunctionEffect::Kind::NonBlocking) { + FuncAttrs.addAttribute(llvm::Attribute::NonBlocking); + } + } } if (isa<FunctionDecl>(TargetDecl) || isa<VarDecl>(TargetDecl)) { diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 1e98bea8c8ce3..84ce2b20dd45d 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -31,6 +31,7 @@ #include "clang/AST/StmtObjC.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/CodeGenOptions.h" +#include "clang/Basic/Sanitizers.h" #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/CGFunctionInfo.h" @@ -40,6 +41,9 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/FPEnv.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/MDBuilder.h" @@ -1410,6 +1414,35 @@ QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD, return ResTy; } +void InsertCallBeforeInstruction(llvm::Function *Fn, + llvm::Instruction &Instruction, + const char *FunctionName) { + llvm::LLVMContext &context = Fn->getContext(); + llvm::FunctionType *FuncType = + llvm::FunctionType::get(llvm::Type::getVoidTy(context), false); + llvm::FunctionCallee Func = + Fn->getParent()->getOrInsertFunction(FunctionName, FuncType); + llvm::IRBuilder<> builder{&Instruction}; + builder.CreateCall(Func, {}); +} + +void InsertCallAtFunctionEntryPoint(llvm::Function *Fn, + const char *InsertFnName) { + + InsertCallBeforeInstruction(Fn, Fn->front().front(), InsertFnName); +} + +void InsertCallAtAllFunctionExitPoints(llvm::Function *Fn, + const char *InsertFnName) { + for (auto &BB : *Fn) { + for (auto &I : BB) { + if (auto *RI = dyn_cast<llvm::ReturnInst>(&I)) { + InsertCallBeforeInstruction(Fn, I, InsertFnName); + } + } + } +} + void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, const CGFunctionInfo &FnInfo) { assert(Fn && "generating code for null Function"); @@ -1578,9 +1611,19 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, } } + if (SanOpts.has(SanitizerKind::Realtime)) { + if (Fn->hasFnAttribute(llvm::Attribute::NonBlocking)) + InsertCallAtFunctionEntryPoint(Fn, "__rtsan_realtime_enter"); + } + // Emit the standard function epilogue. FinishFunction(BodyRange.getEnd()); + if (SanOpts.has(SanitizerKind::Realtime)) { + if (Fn->hasFnAttribute(llvm::Attribute::NonBlocking)) + InsertCallAtAllFunctionExitPoints(Fn, "__rtsan_realtime_exit"); + } + // If we haven't marked the function nothrow through other means, do // a quick pass now to see if we can. if (!CurFn->doesNotThrow()) diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 1fd870b72286e..7b38f20fc8d05 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 019df16a909f4..5c2040fdee8d7 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1430,6 +1430,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. @@ -1455,6 +1457,11 @@ 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 c6f9d7beffb1d..28e735795cb2b 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()) { @@ -3477,6 +3484,7 @@ SanitizerMask Darwin::getSupportedSanitizers() const { const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64; SanitizerMask Res = ToolChain::getSupportedSanitizers(); Res |= SanitizerKind::Address; + Res |= SanitizerKind::Realtime; Res |= SanitizerKind::PointerCompare; Res |= SanitizerKind::PointerSubtract; Res |= SanitizerKind::Leak; diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index 2265138edbffb..aa8a219dc9745 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -798,6 +798,7 @@ SanitizerMask Linux::getSupportedSanitizers() const { const bool IsHexagon = getTriple().getArch() == llvm::Triple::hexagon; SanitizerMask Res = ToolChain::getSupportedSanitizers(); Res |= SanitizerKind::Address; + Res |= SanitizerKind::Realtime; Res |= SanitizerKind::PointerCompare; Res |= SanitizerKind::PointerSubtract; Res |= SanitizerKind::Fuzzer; diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index db14f6e195c64..c3ce8b5ae8b72 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -1038,3 +1038,51 @@ // 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 0000000000000..1ccf52d34873d --- /dev/null +++ b/clang/test/Driver/rtsan.c @@ -0,0 +1,12 @@ +// 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 + +int foo(int *a) [[clang::nonblocking]] { return *a; } +// CHECK: __rtsan_realtime_enter +// CHECK: __rtsan_realtime_exit diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors.cpp index 4d5423ec629d2..833062c3de41e 100644 --- a/compiler-rt/lib/rtsan/rtsan_interceptors.cpp +++ b/compiler-rt/lib/rtsan/rtsan_interceptors.cpp @@ -39,7 +39,6 @@ using namespace __sanitizer; -using __rtsan::rtsan_init_is_running; using __rtsan::rtsan_initialized; namespace { @@ -49,6 +48,9 @@ struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> { } // namespace void ExpectNotRealtime(const char *intercepted_function_name) { + if (!rtsan_initialized) + __rtsan_init(); + __rtsan::GetContextForThisThread().ExpectNotRealtime( intercepted_function_name); } diff --git a/compiler-rt/lib/rtsan/tests/CMakeLists.txt b/compiler-rt/lib/rtsan/tests/CMakeLists.txt index 3b783c90c2658..0320bbad59218 100644 --- a/compiler-rt/lib/rtsan/tests/CMakeLists.txt +++ b/compiler-rt/lib/rtsan/tests/CMakeLists.txt @@ -60,14 +60,13 @@ endif() foreach(arch ${RTSAN_TEST_ARCH}) set(RtsanTestObjects) - # TODO: Re-enable once -fsanitize=realtime exists in clang driver - #generate_compiler_rt_tests(RtsanTestObjects - # RtsanUnitTests "Rtsan-${arch}-Test" ${arch} - # COMPILE_DEPS ${RTSAN_UNITTEST_HEADERS} - # SOURCES ${RTSAN_INST_TEST_SOURCES} ${COMPILER_RT_GOOGLETEST_SOURCES} - # DEPS rtsan - # CFLAGS ${RTSAN_UNITTEST_CFLAGS} -fsanitize=realtime - # LINK_FLAGS ${RTSAN_UNITTEST_LINK_FLAGS} -fsanitize=realtime) + generate_compiler_rt_tests(RtsanTestObjects + RtsanUnitTests "Rtsan-${arch}-Test" ${arch} + COMPILE_DEPS ${RTSAN_UNITTEST_HEADERS} + SOURCES ${RTSAN_INST_TEST_SOURCES} ${COMPILER_RT_GOOGLETEST_SOURCES} + DEPS rtsan + CFLAGS ${RTSAN_UNITTEST_CFLAGS} -fsanitize=realtime + LINK_FLAGS ${RTSAN_UNITTEST_LINK_FLAGS} -fsanitize=realtime) set(RTSAN_TEST_RUNTIME RTRtsanTest.${arch}) if(APPLE) diff --git a/compiler-rt/test/rtsan/CMakeLists.txt b/compiler-rt/test/rtsan/CMakeLists.txt index e1f9eb39408dc..59fc5a29703fe 100644 --- a/compiler-rt/test/rtsan/CMakeLists.txt +++ b/compiler-rt/test/rtsan/CMakeLists.txt @@ -1,14 +1,3 @@ - - - - -###### -# TODO: Full lit tests coming in a future review when we introduce the codegen -###### - - - - set(RTSAN_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(RTSAN_TESTSUITES) diff --git a/compiler-rt/test/rtsan/test_rtsan.cpp b/compiler-rt/test/rtsan/test_rtsan.cpp new file mode 100644 index 0000000000000..101aadc56e960 --- /dev/null +++ b/compiler-rt/test/rtsan/test_rtsan.cpp @@ -0,0 +1,17 @@ +// RUN: %clangxx -fsanitize=realtime %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: ios + +// Intent: Ensure that an intercepted call in a [[clang::nonblocking]] function +// is flagged as an error. Basic smoke test. + +#include <stdlib.h> + +void violation() [[clang::nonblocking]] { void *Ptr = malloc(2); } + +int main() { + violation(); + return 0; + // CHECK: {{.*Real-time violation.*}} + // CHECK: {{.*malloc*}} +} diff --git a/compiler-rt/test/rtsan/test_rtsan_inactive.cpp b/compiler-rt/test/rtsan/test_rtsan_inactive.cpp new file mode 100644 index 0000000000000..86907df6dfa16 --- /dev/null +++ b/compiler-rt/test/rtsan/test_rtsan_inactive.cpp @@ -0,0 +1,23 @@ +// RUN: %clangxx %s -o %t +// RUN: %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: ios + +// Intent: Ensure [[clang::nonblocking]] has no impact if -fsanitize=realtime is not used + +#include <stdio.h> +#include <stdlib.h> + +// In this test, we don't use the -fsanitize=realtime flag, so nothing +// should happen here +void violation() [[clang::nonblocking]] { void *Ptr = malloc(2); } + +int main() { + printf("Starting run\n"); + violation(); + printf("No violations ended the program\n"); + return 0; + // CHECK: {{.*Starting run.*}} + // CHECK NOT: {{.*Real-time violation.*}} + // CHECK NOT: {{.*malloc*}} + // CHECK: {{.*No violations ended the program.*}} +} diff --git a/compiler-rt/test/sanitizer_common/CMakeLists.txt b/compiler-rt/test/sanitizer_common/CMakeLists.txt index fa06b82acebd9..90bb55db3d1a6 100644 --- a/compiler-rt/test/sanitizer_common/CMakeLists.txt +++ b/compiler-rt/test/sanitizer_common/CMakeLists.txt @@ -7,7 +7,7 @@ set(SANITIZER_COMMON_TESTSUITES) # FIXME(dliew): We should switch to COMPILER_RT_SANITIZERS_TO_BUILD instead of # the hard coded `SUPPORTED_TOOLS_INIT` list once we know that the other # sanitizers work. -set(SUPPORTED_TOOLS_INIT asan lsan hwasan msan tsan ubsan) +set(SUPPORTED_TOOLS_INIT asan lsan hwasan msan rtsan tsan ubsan) set(SUPPORTED_TOOLS) foreach(SANITIZER_TOOL ${SUPPORTED_TOOLS_INIT}) string(TOUPPER ${SANITIZER_TOOL} SANITIZER_TOOL_UPPER) diff --git a/compiler-rt/test/sanitizer_common/lit.common.cfg.py b/compiler-rt/test/sanitizer_common/lit.common.cfg.py index 04af4816eb6e7..5406e8838f2fc 100644 --- a/compiler-rt/test/sanitizer_common/lit.common.cfg.py +++ b/compiler-rt/test/sanitizer_common/lit.common.cfg.py @@ -18,6 +18,9 @@ tool_options = "HWASAN_OPTIONS" if not config.has_lld: config.unsupported = True +elif config.tool_name == "rtsan": + tool_cflags = ["-fsanitize=realtime"] + tool_options = "RTSAN_OPTIONS" elif config.tool_name == "tsan": tool_cflags = ["-fsanitize=thread"] tool_options = "TSAN_OPTIONS" diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index fb88f2fe75adb..61b046c26a97f 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -758,6 +758,7 @@ enum AttributeKindCodes { ATTR_KIND_SANITIZE_NUMERICAL_STABILITY = 93, ATTR_KIND_INITIALIZES = 94, ATTR_KIND_HYBRID_PATCHABLE = 95, + ATTR_KIND_NONBLOCKING = 96, }; enum ComdatSelectionKindCodes { diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td index e1bd193891c1e..8d90e912f279c 100644 --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -239,6 +239,9 @@ def ReadNone : EnumAttr<"readnone", [ParamAttr]>; /// Function only reads from memory. def ReadOnly : EnumAttr<"readonly", [ParamAttr]>; +/// Function is marked to be non-blocking +def NonBlocking : EnumAttr<"nonblocking", [FnAttr]>; + /// Return value is always equal to this argument. def Returned : EnumAttr<"returned", [ParamAttr]>; diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 84d624f6cf8fa..a519748bc1c83 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2109,6 +2109,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { return Attribute::ReadOnly; case bitc::ATTR_KIND_RETURNED: return Attribute::Returned; + case bitc::ATTR_KIND_NONBLOCKING: + return Attribute::NonBlocking; case bitc::ATTR_KIND_RETURNS_TWICE: return Attribute::ReturnsTwice; case bitc::ATTR_KIND_S_EXT: diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 324dcbca8137e..d54aeae74a59f 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -805,6 +805,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_OPTIMIZE_FOR_SIZE; case Attribute::OptimizeNone: return bitc::ATTR_KIND_OPTIMIZE_NONE; + case Attribute::NonBlocking: + return bitc::ATTR_KIND_NONBLOCKING; case Attribute::ReadNone: return bitc::ATTR_KIND_READ_NONE; case Attribute::ReadOnly: diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 5bca5cf8ff91f..913c0f844f833 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -970,6 +970,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs, case Attribute::MustProgress: case Attribute::NoProfile: case Attribute::SkipProfile: + case Attribute::NonBlocking: break; // These attributes cannot be applied to functions. case Attribute::Alignment: >From e7cce538fe2dae3c22f648d7f1e9d143b137166a Mon Sep 17 00:00:00 2001 From: Chris Apple <cja-priv...@pm.me> Date: Tue, 23 Jul 2024 08:49:18 -0700 Subject: [PATCH 2/2] Remove rtsan from SanitizerCommonTests --- compiler-rt/test/sanitizer_common/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-rt/test/sanitizer_common/CMakeLists.txt b/compiler-rt/test/sanitizer_common/CMakeLists.txt index 90bb55db3d1a6..fa06b82acebd9 100644 --- a/compiler-rt/test/sanitizer_common/CMakeLists.txt +++ b/compiler-rt/test/sanitizer_common/CMakeLists.txt @@ -7,7 +7,7 @@ set(SANITIZER_COMMON_TESTSUITES) # FIXME(dliew): We should switch to COMPILER_RT_SANITIZERS_TO_BUILD instead of # the hard coded `SUPPORTED_TOOLS_INIT` list once we know that the other # sanitizers work. -set(SUPPORTED_TOOLS_INIT asan lsan hwasan msan rtsan tsan ubsan) +set(SUPPORTED_TOOLS_INIT asan lsan hwasan msan tsan ubsan) set(SUPPORTED_TOOLS) foreach(SANITIZER_TOOL ${SUPPORTED_TOOLS_INIT}) string(TOUPPER ${SANITIZER_TOOL} SANITIZER_TOOL_UPPER) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits