diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 2e6030af7ba93..91c3e60bb0acb 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -2325,6 +2325,11 @@ example: This attribute indicates that RealtimeSanitizer checks (realtime safety analysis - no allocations, syscalls or exceptions) are enabled for this function. +``sanitize_realtime_unsafe`` + This attribute indicates that RealtimeSanitizer should error immediately + if the attributed function is called during invocation of a function + attributed with ``sanitize_realtime``. + This attribute is incompatible with the ``sanitize_realtime`` attribute. ``speculative_load_hardening`` This attribute indicates that `Speculative Load Hardening `_ diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 96668435e8d7b..cbd92fd52fc75 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -761,7 +761,7 @@ enum AttributeKindCodes { ATTR_KIND_INITIALIZES = 94, ATTR_KIND_HYBRID_PATCHABLE = 95, ATTR_KIND_SANITIZE_REALTIME = 96, - ATTR_KIND_NO_SANITIZE_REALTIME = 97, + ATTR_KIND_SANITIZE_REALTIME_UNSAFE = 97, ATTR_KIND_CORO_ELIDE_SAFE = 98, ATTR_KIND_NO_EXT = 99, }; diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td index 24070d646e184..9044d127b4794 100644 --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -303,6 +303,10 @@ def SanitizeNumericalStability : EnumAttr<"sanitize_numerical_stability", [FnAtt /// RealtimeSanitizer is on. def SanitizeRealtime : EnumAttr<"sanitize_realtime", [FnAttr]>; +/// RealtimeSanitizer should error if a real-time unsafe function is invoked +/// during a real-time sanitized function (see `sanitize_realtime`). +def SanitizeRealtimeUnsafe : EnumAttr<"sanitize_realtime_unsafe", [FnAttr]>; + /// Speculative Load Hardening is enabled. /// /// Note that this uses the default compatibility (always compatible during @@ -396,6 +400,7 @@ def : CompatRule<"isEqual">; def : CompatRule<"isEqual">; def : CompatRule<"isEqual">; def : CompatRule<"isEqual">; +def : CompatRule<"isEqual">; def : CompatRule<"isEqual">; def : CompatRule<"isEqual">; def : CompatRule<"isEqual">; diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index b7db631d7d432..6f997510b0360 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2144,6 +2144,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { return Attribute::SanitizeNumericalStability; case bitc::ATTR_KIND_SANITIZE_REALTIME: return Attribute::SanitizeRealtime; + case bitc::ATTR_KIND_SANITIZE_REALTIME_UNSAFE: + return Attribute::SanitizeRealtimeUnsafe; case bitc::ATTR_KIND_SPECULATIVE_LOAD_HARDENING: return Attribute::SpeculativeLoadHardening; case bitc::ATTR_KIND_SWIFT_ERROR: diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 5ead94218c3f8..d9086bfebbd2a 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -849,6 +849,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_SANITIZE_NUMERICAL_STABILITY; case Attribute::SanitizeRealtime: return bitc::ATTR_KIND_SANITIZE_REALTIME; + case Attribute::SanitizeRealtimeUnsafe: + return bitc::ATTR_KIND_SANITIZE_REALTIME_UNSAFE; case Attribute::SpeculativeLoadHardening: return bitc::ATTR_KIND_SPECULATIVE_LOAD_HARDENING; case Attribute::SwiftError: diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 06a67346fbf95..1cd5eb36c4ab6 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -2224,6 +2224,12 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, "Attributes 'optdebug and optnone' are incompatible!", V); } + Check(!(Attrs.hasFnAttr(Attribute::SanitizeRealtime) && + Attrs.hasFnAttr(Attribute::SanitizeRealtimeUnsafe)), + "Attributes " + "'sanitize_realtime and sanitize_realtime_unsafe' are incompatible!", + V); + if (Attrs.hasFnAttr(Attribute::OptimizeForDebugging)) { Check(!Attrs.hasFnAttr(Attribute::OptimizeForSize), "Attributes 'optsize and optdebug' are incompatible!", V); diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 1a4987722dc29..f58448dd9562d 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -952,6 +952,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs, case Attribute::SanitizeHWAddress: case Attribute::SanitizeMemTag: case Attribute::SanitizeRealtime: + case Attribute::SanitizeRealtimeUnsafe: case Attribute::SpeculativeLoadHardening: case Attribute::StackProtect: case Attribute::StackProtectReq: diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll index 4402289ac170d..a66eda19ff573 100644 --- a/llvm/test/Bitcode/attributes.ll +++ b/llvm/test/Bitcode/attributes.ll @@ -511,6 +511,11 @@ define void @f92() sanitize_realtime ret void; } +; CHECK: define void @f93() #54 +define void @f93() sanitize_realtime_unsafe { + ret void; +} + ; CHECK: define void @f87() [[FNRETTHUNKEXTERN:#[0-9]+]] define void @f87() fn_ret_thunk_extern { ret void } @@ -606,6 +611,7 @@ define void @initializes(ptr initializes((-4, 0), (4, 8)) %a) { ; CHECK: attributes #51 = { uwtable(sync) } ; CHECK: attributes #52 = { nosanitize_bounds } ; CHECK: attributes #53 = { sanitize_realtime } +; CHECK: attributes #54 = { sanitize_realtime_unsafe } ; CHECK: attributes [[FNRETTHUNKEXTERN]] = { fn_ret_thunk_extern } ; CHECK: attributes [[SKIPPROFILE]] = { skipprofile } ; CHECK: attributes [[OPTDEBUG]] = { optdebug } diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll index e38c9783c9a8f..ea29ff634a43b 100644 --- a/llvm/test/Bitcode/compatibility.ll +++ b/llvm/test/Bitcode/compatibility.ll @@ -1590,7 +1590,7 @@ exit: ; CHECK: select <2 x i1> , <2 x i8> , <2 x i8> call void @f.nobuiltin() builtin - ; CHECK: call void @f.nobuiltin() #53 + ; CHECK: call void @f.nobuiltin() #54 call fastcc noalias ptr @f.noalias() noinline ; CHECK: call fastcc noalias ptr @f.noalias() #12 @@ -2020,6 +2020,9 @@ declare void @f.sanitize_numerical_stability() sanitize_numerical_stability declare void @f.sanitize_realtime() sanitize_realtime ; CHECK: declare void @f.sanitize_realtime() #52 +declare void @f.sanitize_realtime_unsafe() sanitize_realtime_unsafe +; CHECK: declare void @f.sanitize_realtime_unsafe() #53 + ; CHECK: declare nofpclass(snan) float @nofpclass_snan(float nofpclass(snan)) declare nofpclass(snan) float @nofpclass_snan(float nofpclass(snan)) @@ -2143,7 +2146,8 @@ define float @nofpclass_callsites(float %arg) { ; CHECK: attributes #50 = { allockind("alloc,uninitialized") } ; CHECK: attributes #51 = { sanitize_numerical_stability } ; CHECK: attributes #52 = { sanitize_realtime } -; CHECK: attributes #53 = { builtin } +; CHECK: attributes #53 = { sanitize_realtime_unsafe } +; CHECK: attributes #54 = { builtin } ;; Metadata diff --git a/llvm/test/Verifier/rtsan-attrs.ll b/llvm/test/Verifier/rtsan-attrs.ll new file mode 100644 index 0000000000000..fcc44d8d63c1d --- /dev/null +++ b/llvm/test/Verifier/rtsan-attrs.ll @@ -0,0 +1,9 @@ +; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s + +; CHECK: Attributes 'sanitize_realtime and sanitize_realtime_unsafe' are incompatible! +; CHECK-NEXT: ptr @sanitize_unsafe +define void @sanitize_unsafe() #0 { + ret void +} + +attributes #0 = { sanitize_realtime sanitize_realtime_unsafe }