diff options
author | Thurston Dang <thurston@google.com> | 2024-12-18 15:36:12 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-18 15:36:12 -0800 |
commit | 7eaf4708098c216bf432fc7e0bc79c3771e793a4 (patch) | |
tree | 1c5502120259f400d40b59c7ee2c91b8c68dc9d4 /clang/lib/CodeGen | |
parent | 0fd7c49a770da936b704ea9b2162a85377b1e374 (diff) | |
download | llvm-7eaf4708098c216bf432fc7e0bc79c3771e793a4.zip llvm-7eaf4708098c216bf432fc7e0bc79c3771e793a4.tar.gz llvm-7eaf4708098c216bf432fc7e0bc79c3771e793a4.tar.bz2 |
[ubsan] Add -fsanitize-merge (and -fno-sanitize-merge) (#120464)
'-mllvm -ubsan-unique-traps'
(https://github.com/llvm/llvm-project/pull/65972) applies to all UBSan
checks. This patch introduces -fsanitize-merge (defaults to on,
maintaining the status quo behavior) and -fno-sanitize-merge (equivalent
to '-mllvm -ubsan-unique-traps'), with the option to selectively
applying non-merged handlers to a subset of UBSan checks (e.g.,
-fno-sanitize-merge=bool,enum).
N.B. we do not use "trap" in the argument name since
https://github.com/llvm/llvm-project/pull/119302 has generalized
-ubsan-unique-traps to work for non-trap modes (min-rt and regular rt).
This patch does not remove the -ubsan-unique-traps flag; that will
override -f(no-)sanitize-merge.
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 30 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 3 |
2 files changed, 19 insertions, 14 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 79955f5..d3fa5be 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3546,7 +3546,7 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF, ArrayRef<llvm::Value *> FnArgs, SanitizerHandler CheckHandler, CheckRecoverableKind RecoverKind, bool IsFatal, - llvm::BasicBlock *ContBB) { + llvm::BasicBlock *ContBB, bool NoMerge) { assert(IsFatal || RecoverKind != CheckRecoverableKind::Unrecoverable); std::optional<ApplyDebugLocation> DL; if (!CGF.Builder.getCurrentDebugLocation()) { @@ -3581,10 +3581,9 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF, llvm::AttributeList::FunctionIndex, B), /*Local=*/true); llvm::CallInst *HandlerCall = CGF.EmitNounwindRuntimeCall(Fn, FnArgs); - bool NoMerge = - ClSanitizeDebugDeoptimization || - !CGF.CGM.getCodeGenOpts().OptimizationLevel || - (CGF.CurCodeDecl && CGF.CurCodeDecl->hasAttr<OptimizeNoneAttr>()); + NoMerge = NoMerge || ClSanitizeDebugDeoptimization || + !CGF.CGM.getCodeGenOpts().OptimizationLevel || + (CGF.CurCodeDecl && CGF.CurCodeDecl->hasAttr<OptimizeNoneAttr>()); if (NoMerge) HandlerCall->addFnAttr(llvm::Attribute::NoMerge); if (!MayReturn) { @@ -3608,6 +3607,7 @@ void CodeGenFunction::EmitCheck( llvm::Value *FatalCond = nullptr; llvm::Value *RecoverableCond = nullptr; llvm::Value *TrapCond = nullptr; + bool NoMerge = false; for (int i = 0, n = Checked.size(); i < n; ++i) { llvm::Value *Check = Checked[i].first; // -fsanitize-trap= overrides -fsanitize-recover=. @@ -3618,6 +3618,9 @@ void CodeGenFunction::EmitCheck( ? RecoverableCond : FatalCond; Cond = Cond ? Builder.CreateAnd(Cond, Check) : Check; + + if (!CGM.getCodeGenOpts().SanitizeMergeHandlers.has(Checked[i].second)) + NoMerge = true; } if (ClSanitizeGuardChecks) { @@ -3632,7 +3635,7 @@ void CodeGenFunction::EmitCheck( } if (TrapCond) - EmitTrapCheck(TrapCond, CheckHandler); + EmitTrapCheck(TrapCond, CheckHandler, NoMerge); if (!FatalCond && !RecoverableCond) return; @@ -3698,7 +3701,7 @@ void CodeGenFunction::EmitCheck( // Simple case: we need to generate a single handler call, either // fatal, or non-fatal. emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind, - (FatalCond != nullptr), Cont); + (FatalCond != nullptr), Cont, NoMerge); } else { // Emit two handler calls: first one for set of unrecoverable checks, // another one for recoverable. @@ -3708,10 +3711,10 @@ void CodeGenFunction::EmitCheck( Builder.CreateCondBr(FatalCond, NonFatalHandlerBB, FatalHandlerBB); EmitBlock(FatalHandlerBB); emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind, true, - NonFatalHandlerBB); + NonFatalHandlerBB, NoMerge); EmitBlock(NonFatalHandlerBB); emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind, false, - Cont); + Cont, NoMerge); } EmitBlock(Cont); @@ -3901,7 +3904,8 @@ void CodeGenFunction::EmitUnreachable(SourceLocation Loc) { } void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, - SanitizerHandler CheckHandlerID) { + SanitizerHandler CheckHandlerID, + bool NoMerge) { llvm::BasicBlock *Cont = createBasicBlock("cont"); // If we're optimizing, collapse all calls to trap down to just one per @@ -3911,9 +3915,9 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID]; - bool NoMerge = ClSanitizeDebugDeoptimization || - !CGM.getCodeGenOpts().OptimizationLevel || - (CurCodeDecl && CurCodeDecl->hasAttr<OptimizeNoneAttr>()); + NoMerge = NoMerge || ClSanitizeDebugDeoptimization || + !CGM.getCodeGenOpts().OptimizationLevel || + (CurCodeDecl && CurCodeDecl->hasAttr<OptimizeNoneAttr>()); if (TrapBB && !NoMerge) { auto Call = TrapBB->begin(); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 847999c..4d41391 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -5171,7 +5171,8 @@ public: /// Create a basic block that will call the trap intrinsic, and emit a /// conditional branch to it, for the -ftrapv checks. - void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID); + void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID, + bool NoMerge = false); /// Emit a call to trap or debugtrap and attach function attribute /// "trap-func-name" if specified. |