From f879a22fd1c89f6ca5e703621742e8c913780ca1 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 10 Jan 2025 21:23:19 -0800 Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?= =?UTF-8?q?l=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.4 --- .../Instrumentation/BoundsChecking.h | 1 + llvm/lib/Passes/PassBuilder.cpp | 16 ++++-- .../Instrumentation/BoundsChecking.cpp | 11 +++- .../BoundsChecking/runtimes.ll | 51 +++++++++++++++++++ 4 files changed, 74 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h b/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h index 836fc907375d3..ab2dcee06551e 100644 --- a/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h +++ b/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h @@ -29,6 +29,7 @@ class BoundsCheckingPass : public PassInfoMixin { }; std::optional Rt; // Trap if empty. bool Merge = false; + std::optional GuardKind; // `allow_ubsan_check` argument. }; BoundsCheckingPass(Options Opts) : Opts(Opts) {} diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index aac4407740055..f923d5aabe0a0 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -1315,10 +1315,18 @@ parseBoundsCheckingOptions(StringRef Params) { } else if (ParamName == "merge") { Options.Merge = true; } else { - return make_error( - formatv("invalid BoundsChecking pass parameter '{0}' ", ParamName) - .str(), - inconvertibleErrorCode()); + StringRef ParamEQ; + StringRef Val; + std::tie(ParamEQ, Val) = ParamName.split('='); + int8_t Id = 0; + if (ParamEQ == "guard" && !Val.getAsInteger(0, Id)) { + Options.GuardKind = Id; + } else { + return make_error( + formatv("invalid BoundsChecking pass parameter '{0}' ", ParamName) + .str(), + inconvertibleErrorCode()); + } } } return Options; diff --git a/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp index 8004552250b47..609678f9979c6 100644 --- a/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp +++ b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp @@ -214,8 +214,15 @@ static bool addBoundsChecking(Function &F, TargetLibraryInfo &TLI, Or = getBoundsCheckCond(AI->getPointerOperand(), AI->getValOperand(), DL, TLI, ObjSizeEval, IRB, SE); } - if (Or) + if (Or) { + if (Opts.GuardKind) { + llvm::Value *Allow = IRB.CreateIntrinsic( + IRB.getInt1Ty(), Intrinsic::allow_ubsan_check, + {llvm::ConstantInt::getSigned(IRB.getInt8Ty(), *Opts.GuardKind)}); + Or = IRB.CreateAnd(Or, Allow); + } TrapInfo.push_back(std::make_pair(&I, Or)); + } } std::string Name; @@ -299,5 +306,7 @@ void BoundsCheckingPass::printPipeline( } if (Opts.Merge) OS << ";merge"; + if (Opts.GuardKind) + OS << ";guard=" << static_cast(*Opts.GuardKind); OS << ">"; } diff --git a/llvm/test/Instrumentation/BoundsChecking/runtimes.ll b/llvm/test/Instrumentation/BoundsChecking/runtimes.ll index ccc7e93615fed..055bd5544ac38 100644 --- a/llvm/test/Instrumentation/BoundsChecking/runtimes.ll +++ b/llvm/test/Instrumentation/BoundsChecking/runtimes.ll @@ -9,6 +9,8 @@ ; RUN: opt < %s -passes='bounds-checking' -S | FileCheck %s --check-prefixes=MINRT-NOMERGE ; RUN: opt < %s -passes='bounds-checking' -S | FileCheck %s --check-prefixes=MINRTABORT-NOMERGE ; +; RUN: opt < %s -passes='bounds-checking' -S | FileCheck %s --check-prefixes=TR-GUARD +; RUN: opt < %s -passes='bounds-checking' -S | FileCheck %s --check-prefixes=RT-GUARDRT target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" define void @f1(i64 %x) nounwind { @@ -123,6 +125,42 @@ define void @f1(i64 %x) nounwind { ; MINRTABORT-NOMERGE: [[TRAP]]: ; MINRTABORT-NOMERGE-NEXT: call void @__ubsan_handle_local_out_of_bounds_minimal_abort() #[[ATTR2:[0-9]+]], !nosanitize [[META0]] ; MINRTABORT-NOMERGE-NEXT: unreachable, !nosanitize [[META0]] +; +; TR-GUARD-LABEL: define void @f1( +; TR-GUARD-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; TR-GUARD-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]] +; TR-GUARD-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8 +; TR-GUARD-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0, !nosanitize [[META0:![0-9]+]] +; TR-GUARD-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16, !nosanitize [[META0]] +; TR-GUARD-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]], !nosanitize [[META0]] +; TR-GUARD-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]], !nosanitize [[META0]] +; TR-GUARD-NEXT: [[TMP7:%.*]] = call i1 @llvm.allow.ubsan.check(i8 3), !nosanitize [[META0]] +; TR-GUARD-NEXT: [[TMP8:%.*]] = and i1 [[TMP6]], [[TMP7]], !nosanitize [[META0]] +; TR-GUARD-NEXT: br i1 [[TMP8]], label %[[TRAP:.*]], label %[[BB9:.*]] +; TR-GUARD: [[BB9]]: +; TR-GUARD-NEXT: [[TMP10:%.*]] = load i128, ptr [[TMP2]], align 4 +; TR-GUARD-NEXT: ret void +; TR-GUARD: [[TRAP]]: +; TR-GUARD-NEXT: call void @llvm.ubsantrap(i8 3) #[[ATTR3:[0-9]+]], !nosanitize [[META0]] +; TR-GUARD-NEXT: unreachable, !nosanitize [[META0]] +; +; RT-GUARDRT-LABEL: define void @f1( +; RT-GUARDRT-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; RT-GUARDRT-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]] +; RT-GUARDRT-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8 +; RT-GUARDRT-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0, !nosanitize [[META0:![0-9]+]] +; RT-GUARDRT-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16, !nosanitize [[META0]] +; RT-GUARDRT-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]], !nosanitize [[META0]] +; RT-GUARDRT-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]], !nosanitize [[META0]] +; RT-GUARDRT-NEXT: [[TMP7:%.*]] = call i1 @llvm.allow.ubsan.check(i8 -5), !nosanitize [[META0]] +; RT-GUARDRT-NEXT: [[TMP8:%.*]] = and i1 [[TMP6]], [[TMP7]], !nosanitize [[META0]] +; RT-GUARDRT-NEXT: br i1 [[TMP8]], label %[[TRAP:.*]], label %[[BB9:.*]] +; RT-GUARDRT: [[BB9]]: +; RT-GUARDRT-NEXT: [[TMP10:%.*]] = load i128, ptr [[TMP2]], align 4 +; RT-GUARDRT-NEXT: ret void +; RT-GUARDRT: [[TRAP]]: +; RT-GUARDRT-NEXT: call void @__ubsan_handle_local_out_of_bounds() #[[ATTR2:[0-9]+]], !nosanitize [[META0]] +; RT-GUARDRT-NEXT: br label %[[BB9]], !nosanitize [[META0]] ; %1 = alloca i128, i64 %x %3 = load i128, ptr %1, align 4 @@ -154,6 +192,15 @@ define void @f1(i64 %x) nounwind { ; MINRTABORT-NOMERGE: attributes #[[ATTR1:[0-9]+]] = { noreturn nounwind } ; MINRTABORT-NOMERGE: attributes #[[ATTR2]] = { nomerge noreturn nounwind } ;. +; TR-GUARD: attributes #[[ATTR0]] = { nounwind } +; TR-GUARD: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) } +; TR-GUARD: attributes #[[ATTR2:[0-9]+]] = { cold noreturn nounwind } +; TR-GUARD: attributes #[[ATTR3]] = { nomerge noreturn nounwind } +;. +; RT-GUARDRT: attributes #[[ATTR0]] = { nounwind } +; RT-GUARDRT: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) } +; RT-GUARDRT: attributes #[[ATTR2]] = { nomerge nounwind } +;. ; TR: [[META0]] = !{} ;. ; RT: [[META0]] = !{} @@ -168,3 +215,7 @@ define void @f1(i64 %x) nounwind { ;. ; MINRTABORT-NOMERGE: [[META0]] = !{} ;. +; TR-GUARD: [[META0]] = !{} +;. +; RT-GUARDRT: [[META0]] = !{} +;.