aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorThurston Dang <thurston@google.com>2025-06-06 14:59:32 -0700
committerGitHub <noreply@github.com>2025-06-06 14:59:32 -0700
commit428afa62b0aa1bb0ac344cbfc62429a60c42b265 (patch)
tree8ecd95edfec80811713ecd9dc8560d1e99c52d47 /clang/lib/CodeGen
parenta42bb8b57a6dcf298789ae88b36bbbba19e151fb (diff)
downloadllvm-428afa62b0aa1bb0ac344cbfc62429a60c42b265.zip
llvm-428afa62b0aa1bb0ac344cbfc62429a60c42b265.tar.gz
llvm-428afa62b0aa1bb0ac344cbfc62429a60c42b265.tar.bz2
[ubsan] Add more -fsanitize-annotate-debug-info checks (#141997)
This extends https://github.com/llvm/llvm-project/pull/138577 to more UBSan checks, by changing SanitizerDebugLocation (formerly SanitizerScope) to add annotations if enabled for the specified ordinals. Annotations will use the ordinal name if there is exactly one ordinal specified in the SanitizerDebugLocation; otherwise, it will use the handler name. Updates the tests from https://github.com/llvm/llvm-project/pull/141814. --------- Co-authored-by: Vitaly Buka <vitalybuka@google.com>
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp28
-rw-r--r--clang/lib/CodeGen/CGCall.cpp4
-rw-r--r--clang/lib/CodeGen/CGClass.cpp18
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp82
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.h12
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp7
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp291
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp100
-rw-r--r--clang/lib/CodeGen/CGObjC.cpp7
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp24
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h8
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp22
12 files changed, 376 insertions, 227 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index dff2334..c0b02a1 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2009,11 +2009,12 @@ Value *CodeGenFunction::EmitCheckedArgForBuiltin(const Expr *E,
if (!SanOpts.has(SanitizerKind::Builtin))
return ArgValue;
- SanitizerScope SanScope(this);
+ auto CheckOrdinal = SanitizerKind::SO_Builtin;
+ auto CheckHandler = SanitizerHandler::InvalidBuiltin;
+ SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
Value *Cond = Builder.CreateICmpNE(
ArgValue, llvm::Constant::getNullValue(ArgValue->getType()));
- EmitCheck(std::make_pair(Cond, SanitizerKind::SO_Builtin),
- SanitizerHandler::InvalidBuiltin,
+ EmitCheck(std::make_pair(Cond, CheckOrdinal), CheckHandler,
{EmitCheckSourceLocation(E->getExprLoc()),
llvm::ConstantInt::get(Builder.getInt8Ty(), Kind)},
{});
@@ -2025,10 +2026,11 @@ Value *CodeGenFunction::EmitCheckedArgForAssume(const Expr *E) {
if (!SanOpts.has(SanitizerKind::Builtin))
return ArgValue;
- SanitizerScope SanScope(this);
+ auto CheckOrdinal = SanitizerKind::SO_Builtin;
+ auto CheckHandler = SanitizerHandler::InvalidBuiltin;
+ SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
EmitCheck(
- std::make_pair(ArgValue, SanitizerKind::SO_Builtin),
- SanitizerHandler::InvalidBuiltin,
+ std::make_pair(ArgValue, CheckOrdinal), CheckHandler,
{EmitCheckSourceLocation(E->getExprLoc()),
llvm::ConstantInt::get(Builder.getInt8Ty(), BCK_AssumePassedFalse)},
std::nullopt);
@@ -2051,7 +2053,15 @@ static Value *EmitOverflowCheckedAbs(CodeGenFunction &CGF, const CallExpr *E,
return EmitAbs(CGF, ArgValue, true);
}
- CodeGenFunction::SanitizerScope SanScope(&CGF);
+ SmallVector<SanitizerKind::SanitizerOrdinal, 1> Ordinals;
+ SanitizerHandler CheckHandler;
+ if (SanitizeOverflow) {
+ Ordinals.push_back(SanitizerKind::SO_SignedIntegerOverflow);
+ CheckHandler = SanitizerHandler::NegateOverflow;
+ } else
+ CheckHandler = SanitizerHandler::SubOverflow;
+
+ SanitizerDebugLocation SanScope(&CGF, Ordinals, CheckHandler);
Constant *Zero = Constant::getNullValue(ArgValue->getType());
Value *ResultAndOverflow = CGF.Builder.CreateBinaryIntrinsic(
@@ -2063,12 +2073,12 @@ static Value *EmitOverflowCheckedAbs(CodeGenFunction &CGF, const CallExpr *E,
// TODO: support -ftrapv-handler.
if (SanitizeOverflow) {
CGF.EmitCheck({{NotOverflow, SanitizerKind::SO_SignedIntegerOverflow}},
- SanitizerHandler::NegateOverflow,
+ CheckHandler,
{CGF.EmitCheckSourceLocation(E->getArg(0)->getExprLoc()),
CGF.EmitCheckTypeDescriptor(E->getType())},
{ArgValue});
} else
- CGF.EmitTrapCheck(NotOverflow, SanitizerHandler::SubOverflow);
+ CGF.EmitTrapCheck(NotOverflow, CheckHandler);
Value *CmpResult = CGF.Builder.CreateICmpSLT(ArgValue, Zero, "abscond");
return CGF.Builder.CreateSelect(CmpResult, Result, ArgValue, "abs");
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 46a5d64..75df821e 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -4184,7 +4184,7 @@ void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) {
Handler = SanitizerHandler::NullabilityReturn;
}
- SanitizerScope SanScope(this);
+ SanitizerDebugLocation SanScope(this, {CheckKind}, Handler);
// Make sure the "return" source location is valid. If we're checking a
// nullability annotation, make sure the preconditions for the check are met.
@@ -4569,7 +4569,7 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
Handler = SanitizerHandler::NullabilityArg;
}
- SanitizerScope SanScope(this);
+ SanitizerDebugLocation SanScope(this, {CheckKind}, Handler);
llvm::Value *Cond = EmitNonNullRValueCheck(RV, ArgType);
llvm::Constant *StaticData[] = {
EmitCheckSourceLocation(ArgLoc),
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 251b059..13792c1 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -2817,7 +2817,8 @@ void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXRecordDecl *RD,
RD = LeastDerivedClassWithSameLayout(RD);
auto [Ordinal, _] = SanitizerInfoFromCFICheckKind(TCK);
- ApplyDebugLocation ApplyTrapDI(*this, SanitizerAnnotateDebugInfo(Ordinal));
+ SanitizerDebugLocation SanScope(this, {Ordinal},
+ SanitizerHandler::CFICheckFail);
EmitVTablePtrCheck(RD, VTable, TCK, Loc);
}
@@ -2842,7 +2843,8 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, Address Derived,
ClassDecl = LeastDerivedClassWithSameLayout(ClassDecl);
auto [Ordinal, _] = SanitizerInfoFromCFICheckKind(TCK);
- ApplyDebugLocation ApplyTrapDI(*this, SanitizerAnnotateDebugInfo(Ordinal));
+ SanitizerDebugLocation SanScope(this, {Ordinal},
+ SanitizerHandler::CFICheckFail);
llvm::BasicBlock *ContBlock = nullptr;
@@ -2874,6 +2876,8 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
llvm::Value *VTable,
CFITypeCheckKind TCK,
SourceLocation Loc) {
+ assert(IsSanitizerScope);
+
if (!CGM.getCodeGenOpts().SanitizeCfiCrossDso &&
!CGM.HasHiddenLTOVisibility(RD))
return;
@@ -2885,7 +2889,6 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
SanitizerMask::bitPosToMask(M), TypeName))
return;
- SanitizerScope SanScope(this);
EmitSanitizerStatReport(SSK);
llvm::Metadata *MD =
@@ -2942,11 +2945,11 @@ bool CodeGenFunction::ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD) {
llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy,
uint64_t VTableByteOffset) {
- SanitizerScope SanScope(this);
+ auto CheckOrdinal = SanitizerKind::SO_CFIVCall;
+ auto CheckHandler = SanitizerHandler::CFICheckFail;
+ SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
EmitSanitizerStatReport(llvm::SanStat_CFI_VCall);
- ApplyDebugLocation ApplyTrapDI(
- *this, SanitizerAnnotateDebugInfo(SanitizerKind::SO_CFIVCall));
llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
@@ -2965,8 +2968,7 @@ llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
if (SanOpts.has(SanitizerKind::CFIVCall) &&
!getContext().getNoSanitizeList().containsType(SanitizerKind::CFIVCall,
TypeName)) {
- EmitCheck(std::make_pair(CheckResult, SanitizerKind::SO_CFIVCall),
- SanitizerHandler::CFICheckFail, {}, {});
+ EmitCheck(std::make_pair(CheckResult, CheckOrdinal), CheckHandler, {}, {});
}
return Builder.CreateBitCast(Builder.CreateExtractValue(CheckedLoad, 0),
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index fbcc330a..001b208 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -58,6 +58,13 @@
using namespace clang;
using namespace clang::CodeGen;
+// TODO: consider deprecating ClArrayBoundsPseudoFn; functionality is subsumed
+// by -fsanitize-annotate-debug-info
+static llvm::cl::opt<bool> ClArrayBoundsPseudoFn(
+ "array-bounds-pseudofn", llvm::cl::Hidden, llvm::cl::Optional,
+ llvm::cl::desc("Emit debug info that places array-bounds instrumentation "
+ "in an inline function called __ubsan_check_array_bounds."));
+
static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) {
auto TI = Ctx.getTypeInfo(Ty);
if (TI.isAlignRequired())
@@ -6412,3 +6419,78 @@ CodeGenFunction::LexicalScope::~LexicalScope() {
ForceCleanup();
}
}
+
+static std::string SanitizerHandlerToCheckLabel(SanitizerHandler Handler) {
+ std::string Label;
+ switch (Handler) {
+#define SANITIZER_CHECK(Enum, Name, Version) \
+ case Enum: \
+ Label = "__ubsan_check_" #Name; \
+ break;
+
+ LIST_SANITIZER_CHECKS
+#undef SANITIZER_CHECK
+ };
+
+ // Label doesn't require sanitization
+ return Label;
+}
+
+static std::string
+SanitizerOrdinalToCheckLabel(SanitizerKind::SanitizerOrdinal Ordinal) {
+ std::string Label;
+ switch (Ordinal) {
+#define SANITIZER(NAME, ID) \
+ case SanitizerKind::SO_##ID: \
+ Label = "__ubsan_check_" NAME; \
+ break;
+#include "clang/Basic/Sanitizers.def"
+ default:
+ llvm_unreachable("unexpected sanitizer kind");
+ }
+
+ // Sanitize label (convert hyphens to underscores; also futureproof against
+ // non-alpha)
+ for (unsigned int i = 0; i < Label.length(); i++)
+ if (!std::isalpha(Label[i]))
+ Label[i] = '_';
+
+ return Label;
+}
+
+llvm::DILocation *CodeGenFunction::SanitizerAnnotateDebugInfo(
+ ArrayRef<SanitizerKind::SanitizerOrdinal> Ordinals,
+ SanitizerHandler Handler) {
+ std::string Label;
+ if (Ordinals.size() == 1)
+ Label = SanitizerOrdinalToCheckLabel(Ordinals[0]);
+ else
+ Label = SanitizerHandlerToCheckLabel(Handler);
+
+ llvm::DILocation *CheckDI = Builder.getCurrentDebugLocation();
+
+ for (auto Ord : Ordinals) {
+ // TODO: deprecate ClArrayBoundsPseudoFn
+ if (((ClArrayBoundsPseudoFn && Ord == SanitizerKind::SO_ArrayBounds) ||
+ CGM.getCodeGenOpts().SanitizeAnnotateDebugInfo.has(Ord)) &&
+ CheckDI) {
+ return getDebugInfo()->CreateSyntheticInlineAt(CheckDI, Label);
+ }
+ }
+
+ return CheckDI;
+}
+
+SanitizerDebugLocation::SanitizerDebugLocation(
+ CodeGenFunction *CGF, ArrayRef<SanitizerKind::SanitizerOrdinal> Ordinals,
+ SanitizerHandler Handler)
+ : CGF(CGF),
+ Apply(*CGF, CGF->SanitizerAnnotateDebugInfo(Ordinals, Handler)) {
+ assert(!CGF->IsSanitizerScope);
+ CGF->IsSanitizerScope = true;
+}
+
+SanitizerDebugLocation::~SanitizerDebugLocation() {
+ assert(CGF->IsSanitizerScope);
+ CGF->IsSanitizerScope = false;
+}
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 8558817..16759f2 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -14,6 +14,7 @@
#define LLVM_CLANG_LIB_CODEGEN_CGDEBUGINFO_H
#include "CGBuilder.h"
+#include "SanitizerHandler.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExternalASTSource.h"
@@ -974,6 +975,17 @@ public:
~ApplyInlineDebugLocation();
};
+class SanitizerDebugLocation {
+ CodeGenFunction *CGF;
+ ApplyDebugLocation Apply;
+
+public:
+ SanitizerDebugLocation(CodeGenFunction *CGF,
+ ArrayRef<SanitizerKind::SanitizerOrdinal> Ordinals,
+ SanitizerHandler Handler);
+ ~SanitizerDebugLocation();
+};
+
} // namespace CodeGen
} // namespace clang
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index e487a2b..04f13c7 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -766,14 +766,15 @@ void CodeGenFunction::EmitNullabilityCheck(LValue LHS, llvm::Value *RHS,
// Check if the right hand side of the assignment is nonnull, if the left
// hand side must be nonnull.
- SanitizerScope SanScope(this);
+ auto CheckOrdinal = SanitizerKind::SO_NullabilityAssign;
+ auto CheckHandler = SanitizerHandler::TypeMismatch;
+ SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
llvm::Value *IsNotNull = Builder.CreateIsNotNull(RHS);
llvm::Constant *StaticData[] = {
EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(LHS.getType()),
llvm::ConstantInt::get(Int8Ty, 0), // The LogAlignment info is unused.
llvm::ConstantInt::get(Int8Ty, TCK_NonnullAssign)};
- EmitCheck({{IsNotNull, SanitizerKind::SO_NullabilityAssign}},
- SanitizerHandler::TypeMismatch, StaticData, RHS);
+ EmitCheck({{IsNotNull, CheckOrdinal}}, CheckHandler, StaticData, RHS);
}
void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 1099a54..6cb348f 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -65,13 +65,6 @@ llvm::cl::opt<bool> ClSanitizeGuardChecks(
} // namespace clang
-// TODO: consider deprecating ClArrayBoundsPseudoFn; functionality is subsumed
-// by -fsanitize-annotate-debug-info
-static llvm::cl::opt<bool> ClArrayBoundsPseudoFn(
- "array-bounds-pseudofn", llvm::cl::Hidden, llvm::cl::Optional,
- llvm::cl::desc("Emit debug info that places array-bounds instrumentation "
- "in an inline function called __ubsan_check_array_bounds."));
-
//===--------------------------------------------------------------------===//
// Defines for metadata
//===--------------------------------------------------------------------===//
@@ -751,104 +744,116 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
if (Ty.isVolatileQualified())
return;
- SanitizerScope SanScope(this);
-
- SmallVector<std::pair<llvm::Value *, SanitizerKind::SanitizerOrdinal>, 3>
- Checks;
- llvm::BasicBlock *Done = nullptr;
-
// Quickly determine whether we have a pointer to an alloca. It's possible
// to skip null checks, and some alignment checks, for these pointers. This
// can reduce compile-time significantly.
auto PtrToAlloca = dyn_cast<llvm::AllocaInst>(Ptr->stripPointerCasts());
- llvm::Value *True = llvm::ConstantInt::getTrue(getLLVMContext());
llvm::Value *IsNonNull = nullptr;
bool IsGuaranteedNonNull =
SkippedChecks.has(SanitizerKind::Null) || PtrToAlloca;
- bool AllowNullPointers = isNullPointerAllowed(TCK);
- if ((SanOpts.has(SanitizerKind::Null) || AllowNullPointers) &&
- !IsGuaranteedNonNull) {
- // The glvalue must not be an empty glvalue.
- IsNonNull = Builder.CreateIsNotNull(Ptr);
- // The IR builder can constant-fold the null check if the pointer points to
- // a constant.
- IsGuaranteedNonNull = IsNonNull == True;
-
- // Skip the null check if the pointer is known to be non-null.
- if (!IsGuaranteedNonNull) {
- if (AllowNullPointers) {
- // When performing pointer casts, it's OK if the value is null.
- // Skip the remaining checks in that case.
- Done = createBasicBlock("null");
- llvm::BasicBlock *Rest = createBasicBlock("not.null");
- Builder.CreateCondBr(IsNonNull, Rest, Done);
- EmitBlock(Rest);
- } else {
- Checks.push_back(std::make_pair(IsNonNull, SanitizerKind::SO_Null));
+ llvm::BasicBlock *Done = nullptr;
+ bool DoneViaNullSanitize = false;
+
+ {
+ auto CheckHandler = SanitizerHandler::TypeMismatch;
+ SanitizerDebugLocation SanScope(this,
+ {SanitizerKind::SO_Null,
+ SanitizerKind::SO_ObjectSize,
+ SanitizerKind::SO_Alignment},
+ CheckHandler);
+
+ SmallVector<std::pair<llvm::Value *, SanitizerKind::SanitizerOrdinal>, 3>
+ Checks;
+
+ llvm::Value *True = llvm::ConstantInt::getTrue(getLLVMContext());
+ bool AllowNullPointers = isNullPointerAllowed(TCK);
+ if ((SanOpts.has(SanitizerKind::Null) || AllowNullPointers) &&
+ !IsGuaranteedNonNull) {
+ // The glvalue must not be an empty glvalue.
+ IsNonNull = Builder.CreateIsNotNull(Ptr);
+
+ // The IR builder can constant-fold the null check if the pointer points
+ // to a constant.
+ IsGuaranteedNonNull = IsNonNull == True;
+
+ // Skip the null check if the pointer is known to be non-null.
+ if (!IsGuaranteedNonNull) {
+ if (AllowNullPointers) {
+ // When performing pointer casts, it's OK if the value is null.
+ // Skip the remaining checks in that case.
+ Done = createBasicBlock("null");
+ DoneViaNullSanitize = true;
+ llvm::BasicBlock *Rest = createBasicBlock("not.null");
+ Builder.CreateCondBr(IsNonNull, Rest, Done);
+ EmitBlock(Rest);
+ } else {
+ Checks.push_back(std::make_pair(IsNonNull, SanitizerKind::SO_Null));
+ }
}
}
- }
- if (SanOpts.has(SanitizerKind::ObjectSize) &&
- !SkippedChecks.has(SanitizerKind::ObjectSize) &&
- !Ty->isIncompleteType()) {
- uint64_t TySize = CGM.getMinimumObjectSize(Ty).getQuantity();
- llvm::Value *Size = llvm::ConstantInt::get(IntPtrTy, TySize);
- if (ArraySize)
- Size = Builder.CreateMul(Size, ArraySize);
-
- // Degenerate case: new X[0] does not need an objectsize check.
- llvm::Constant *ConstantSize = dyn_cast<llvm::Constant>(Size);
- if (!ConstantSize || !ConstantSize->isNullValue()) {
- // The glvalue must refer to a large enough storage region.
- // FIXME: If Address Sanitizer is enabled, insert dynamic instrumentation
- // to check this.
- // FIXME: Get object address space
- llvm::Type *Tys[2] = { IntPtrTy, Int8PtrTy };
- llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, Tys);
- llvm::Value *Min = Builder.getFalse();
- llvm::Value *NullIsUnknown = Builder.getFalse();
- llvm::Value *Dynamic = Builder.getFalse();
- llvm::Value *LargeEnough = Builder.CreateICmpUGE(
- Builder.CreateCall(F, {Ptr, Min, NullIsUnknown, Dynamic}), Size);
- Checks.push_back(
- std::make_pair(LargeEnough, SanitizerKind::SO_ObjectSize));
+ if (SanOpts.has(SanitizerKind::ObjectSize) &&
+ !SkippedChecks.has(SanitizerKind::ObjectSize) &&
+ !Ty->isIncompleteType()) {
+ uint64_t TySize = CGM.getMinimumObjectSize(Ty).getQuantity();
+ llvm::Value *Size = llvm::ConstantInt::get(IntPtrTy, TySize);
+ if (ArraySize)
+ Size = Builder.CreateMul(Size, ArraySize);
+
+ // Degenerate case: new X[0] does not need an objectsize check.
+ llvm::Constant *ConstantSize = dyn_cast<llvm::Constant>(Size);
+ if (!ConstantSize || !ConstantSize->isNullValue()) {
+ // The glvalue must refer to a large enough storage region.
+ // FIXME: If Address Sanitizer is enabled, insert dynamic
+ // instrumentation
+ // to check this.
+ // FIXME: Get object address space
+ llvm::Type *Tys[2] = {IntPtrTy, Int8PtrTy};
+ llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, Tys);
+ llvm::Value *Min = Builder.getFalse();
+ llvm::Value *NullIsUnknown = Builder.getFalse();
+ llvm::Value *Dynamic = Builder.getFalse();
+ llvm::Value *LargeEnough = Builder.CreateICmpUGE(
+ Builder.CreateCall(F, {Ptr, Min, NullIsUnknown, Dynamic}), Size);
+ Checks.push_back(
+ std::make_pair(LargeEnough, SanitizerKind::SO_ObjectSize));
+ }
}
- }
- llvm::MaybeAlign AlignVal;
- llvm::Value *PtrAsInt = nullptr;
-
- if (SanOpts.has(SanitizerKind::Alignment) &&
- !SkippedChecks.has(SanitizerKind::Alignment)) {
- AlignVal = Alignment.getAsMaybeAlign();
- if (!Ty->isIncompleteType() && !AlignVal)
- AlignVal = CGM.getNaturalTypeAlignment(Ty, nullptr, nullptr,
- /*ForPointeeType=*/true)
- .getAsMaybeAlign();
-
- // The glvalue must be suitably aligned.
- if (AlignVal && *AlignVal > llvm::Align(1) &&
- (!PtrToAlloca || PtrToAlloca->getAlign() < *AlignVal)) {
- PtrAsInt = Builder.CreatePtrToInt(Ptr, IntPtrTy);
- llvm::Value *Align = Builder.CreateAnd(
- PtrAsInt, llvm::ConstantInt::get(IntPtrTy, AlignVal->value() - 1));
- llvm::Value *Aligned =
- Builder.CreateICmpEQ(Align, llvm::ConstantInt::get(IntPtrTy, 0));
- if (Aligned != True)
- Checks.push_back(std::make_pair(Aligned, SanitizerKind::SO_Alignment));
+ llvm::MaybeAlign AlignVal;
+ llvm::Value *PtrAsInt = nullptr;
+
+ if (SanOpts.has(SanitizerKind::Alignment) &&
+ !SkippedChecks.has(SanitizerKind::Alignment)) {
+ AlignVal = Alignment.getAsMaybeAlign();
+ if (!Ty->isIncompleteType() && !AlignVal)
+ AlignVal = CGM.getNaturalTypeAlignment(Ty, nullptr, nullptr,
+ /*ForPointeeType=*/true)
+ .getAsMaybeAlign();
+
+ // The glvalue must be suitably aligned.
+ if (AlignVal && *AlignVal > llvm::Align(1) &&
+ (!PtrToAlloca || PtrToAlloca->getAlign() < *AlignVal)) {
+ PtrAsInt = Builder.CreatePtrToInt(Ptr, IntPtrTy);
+ llvm::Value *Align = Builder.CreateAnd(
+ PtrAsInt, llvm::ConstantInt::get(IntPtrTy, AlignVal->value() - 1));
+ llvm::Value *Aligned =
+ Builder.CreateICmpEQ(Align, llvm::ConstantInt::get(IntPtrTy, 0));
+ if (Aligned != True)
+ Checks.push_back(
+ std::make_pair(Aligned, SanitizerKind::SO_Alignment));
+ }
}
- }
- if (Checks.size() > 0) {
- llvm::Constant *StaticData[] = {
- EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(Ty),
- llvm::ConstantInt::get(Int8Ty, AlignVal ? llvm::Log2(*AlignVal) : 1),
- llvm::ConstantInt::get(Int8Ty, TCK)};
- EmitCheck(Checks, SanitizerHandler::TypeMismatch, StaticData,
- PtrAsInt ? PtrAsInt : Ptr);
+ if (Checks.size() > 0) {
+ llvm::Constant *StaticData[] = {
+ EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(Ty),
+ llvm::ConstantInt::get(Int8Ty, AlignVal ? llvm::Log2(*AlignVal) : 1),
+ llvm::ConstantInt::get(Int8Ty, TCK)};
+ EmitCheck(Checks, CheckHandler, StaticData, PtrAsInt ? PtrAsInt : Ptr);
+ }
}
// If possible, check that the vptr indicates that there is a subobject of
@@ -861,6 +866,9 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// or call a non-static member function
if (SanOpts.has(SanitizerKind::Vptr) &&
!SkippedChecks.has(SanitizerKind::Vptr) && isVptrCheckRequired(TCK, Ty)) {
+ SanitizerDebugLocation SanScope(this, {SanitizerKind::SO_Vptr},
+ SanitizerHandler::DynamicTypeCacheMiss);
+
// Ensure that the pointer is non-null before loading it. If there is no
// compile-time guarantee, reuse the run-time null check or emit a new one.
if (!IsGuaranteedNonNull) {
@@ -929,6 +937,11 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
}
if (Done) {
+ SanitizerDebugLocation SanScope(
+ this,
+ {DoneViaNullSanitize ? SanitizerKind::SO_Null : SanitizerKind::SO_Vptr},
+ DoneViaNullSanitize ? SanitizerHandler::TypeMismatch
+ : SanitizerHandler::DynamicTypeCacheMiss);
Builder.CreateBr(Done);
EmitBlock(Done);
}
@@ -1227,10 +1240,9 @@ void CodeGenFunction::EmitBoundsCheckImpl(const Expr *E, llvm::Value *Bound,
if (!Bound)
return;
- SanitizerScope SanScope(this);
-
auto CheckKind = SanitizerKind::SO_ArrayBounds;
- ApplyDebugLocation ApplyTrapDI(*this, SanitizerAnnotateDebugInfo(CheckKind));
+ auto CheckHandler = SanitizerHandler::OutOfBounds;
+ SanitizerDebugLocation SanScope(this, {CheckKind}, CheckHandler);
bool IndexSigned = IndexType->isSignedIntegerOrEnumerationType();
llvm::Value *IndexVal = Builder.CreateIntCast(Index, SizeTy, IndexSigned);
@@ -1243,37 +1255,7 @@ void CodeGenFunction::EmitBoundsCheckImpl(const Expr *E, llvm::Value *Bound,
};
llvm::Value *Check = Accessed ? Builder.CreateICmpULT(IndexVal, BoundVal)
: Builder.CreateICmpULE(IndexVal, BoundVal);
- EmitCheck(std::make_pair(Check, CheckKind), SanitizerHandler::OutOfBounds,
- StaticData, Index);
-}
-
-llvm::DILocation *CodeGenFunction::SanitizerAnnotateDebugInfo(
- SanitizerKind::SanitizerOrdinal CheckKindOrdinal) {
- std::string Label;
- switch (CheckKindOrdinal) {
-#define SANITIZER(NAME, ID) \
- case SanitizerKind::SO_##ID: \
- Label = "__ubsan_check_" NAME; \
- break;
-#include "clang/Basic/Sanitizers.def"
- default:
- llvm_unreachable("unexpected sanitizer kind");
- }
-
- // Sanitize label
- for (unsigned int i = 0; i < Label.length(); i++)
- if (!std::isalpha(Label[i]))
- Label[i] = '_';
-
- llvm::DILocation *CheckDI = Builder.getCurrentDebugLocation();
- // TODO: deprecate ClArrayBoundsPseudoFn
- if (((ClArrayBoundsPseudoFn &&
- CheckKindOrdinal == SanitizerKind::SO_ArrayBounds) ||
- CGM.getCodeGenOpts().SanitizeAnnotateDebugInfo.has(CheckKindOrdinal)) &&
- CheckDI)
- CheckDI = getDebugInfo()->CreateSyntheticInlineAt(CheckDI, Label);
-
- return CheckDI;
+ EmitCheck(std::make_pair(Check, CheckKind), CheckHandler, StaticData, Index);
}
CodeGenFunction::ComplexPairTy CodeGenFunction::
@@ -1997,8 +1979,12 @@ bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty,
if (!getRangeForType(*this, Ty, Min, End, /*StrictEnums=*/true, IsBool))
return true;
+ SanitizerKind::SanitizerOrdinal Kind =
+ NeedsEnumCheck ? SanitizerKind::SO_Enum : SanitizerKind::SO_Bool;
+
auto &Ctx = getLLVMContext();
- SanitizerScope SanScope(this);
+ auto CheckHandler = SanitizerHandler::LoadInvalidValue;
+ SanitizerDebugLocation SanScope(this, {Kind}, CheckHandler);
llvm::Value *Check;
--End;
if (!Min) {
@@ -2012,10 +1998,7 @@ bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty,
}
llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(Loc),
EmitCheckTypeDescriptor(Ty)};
- SanitizerKind::SanitizerOrdinal Kind =
- NeedsEnumCheck ? SanitizerKind::SO_Enum : SanitizerKind::SO_Bool;
- EmitCheck(std::make_pair(Check, Kind), SanitizerHandler::LoadInvalidValue,
- StaticArgs, Value);
+ EmitCheck(std::make_pair(Check, Kind), CheckHandler, StaticArgs, Value);
return true;
}
@@ -3938,7 +3921,17 @@ void CodeGenFunction::EmitCfiCheckStub() {
// can be nullptr if the calling module has -fsanitize-trap behavior for this
// check kind; in this case __cfi_check_fail traps as well.
void CodeGenFunction::EmitCfiCheckFail() {
- SanitizerScope SanScope(this);
+ auto CheckHandler = SanitizerHandler::CFICheckFail;
+ // TODO: the SanitizerKind is not yet determined for this check (and might
+ // not even be available, if Data == nullptr). However, we still want to
+ // annotate the instrumentation. We approximate this by using all the CFI
+ // kinds.
+ SanitizerDebugLocation SanScope(
+ this,
+ {SanitizerKind::SO_CFIVCall, SanitizerKind::SO_CFINVCall,
+ SanitizerKind::SO_CFIDerivedCast, SanitizerKind::SO_CFIUnrelatedCast,
+ SanitizerKind::SO_CFIICall},
+ CheckHandler);
FunctionArgList Args;
ImplicitParamDecl ArgData(getContext(), getContext().VoidPtrTy,
ImplicitParamKind::Other);
@@ -4001,8 +3994,6 @@ void CodeGenFunction::EmitCfiCheckFail() {
{Addr, AllVtables}),
IntPtrTy);
- // TODO: the instructions above are not annotated with debug info. It is
- // inconvenient to do so because we have not determined SanitizerKind yet.
const std::pair<int, SanitizerKind::SanitizerOrdinal> CheckKinds[] = {
{CFITCK_VCall, SanitizerKind::SO_CFIVCall},
{CFITCK_NVCall, SanitizerKind::SO_CFINVCall},
@@ -4014,7 +4005,8 @@ void CodeGenFunction::EmitCfiCheckFail() {
int Kind = CheckKindOrdinalPair.first;
SanitizerKind::SanitizerOrdinal Ordinal = CheckKindOrdinalPair.second;
- ApplyDebugLocation ApplyTrapDI(*this, SanitizerAnnotateDebugInfo(Ordinal));
+ // TODO: we could apply SanitizerAnnotateDebugInfo(Ordinal) instead of
+ // relying on the SanitizerScope with all CFI ordinals
llvm::Value *Cond =
Builder.CreateICmpNE(CheckKind, llvm::ConstantInt::get(Int8Ty, Kind));
@@ -4026,7 +4018,7 @@ void CodeGenFunction::EmitCfiCheckFail() {
// Although the compiler allows SanitizeMergeHandlers to be set
// independently of CGM.getLangOpts().Sanitize, Driver/SanitizerArgs.cpp
// requires that SanitizeMergeHandlers is a subset of Sanitize.
- EmitTrapCheck(Cond, SanitizerHandler::CFICheckFail, /*NoMerge=*/false);
+ EmitTrapCheck(Cond, CheckHandler, /*NoMerge=*/false);
}
FinishFunction();
@@ -4037,11 +4029,12 @@ void CodeGenFunction::EmitCfiCheckFail() {
void CodeGenFunction::EmitUnreachable(SourceLocation Loc) {
if (SanOpts.has(SanitizerKind::Unreachable)) {
- SanitizerScope SanScope(this);
+ auto CheckOrdinal = SanitizerKind::SO_Unreachable;
+ auto CheckHandler = SanitizerHandler::BuiltinUnreachable;
+ SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
EmitCheck(std::make_pair(static_cast<llvm::Value *>(Builder.getFalse()),
- SanitizerKind::SO_Unreachable),
- SanitizerHandler::BuiltinUnreachable,
- EmitCheckSourceLocation(Loc), {});
+ CheckOrdinal),
+ CheckHandler, EmitCheckSourceLocation(Loc), {});
}
Builder.CreateUnreachable();
}
@@ -6303,7 +6296,9 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
!isa<FunctionNoProtoType>(PointeeType)) {
if (llvm::Constant *PrefixSig =
CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) {
- SanitizerScope SanScope(this);
+ auto CheckOrdinal = SanitizerKind::SO_Function;
+ auto CheckHandler = SanitizerHandler::FunctionTypeMismatch;
+ SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
auto *TypeHash = getUBSanFunctionTypeHash(PointeeType);
llvm::Type *PrefixSigType = PrefixSig->getType();
@@ -6363,9 +6358,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
Builder.CreateICmpEQ(CalleeTypeHash, TypeHash);
llvm::Constant *StaticData[] = {EmitCheckSourceLocation(E->getBeginLoc()),
EmitCheckTypeDescriptor(CalleeType)};
- EmitCheck(std::make_pair(CalleeTypeHashMatch, SanitizerKind::SO_Function),
- SanitizerHandler::FunctionTypeMismatch, StaticData,
- {CalleePtr});
+ EmitCheck(std::make_pair(CalleeTypeHashMatch, CheckOrdinal), CheckHandler,
+ StaticData, {CalleePtr});
Builder.CreateBr(Cont);
EmitBlock(Cont);
@@ -6385,10 +6379,10 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
// function pointer is a member of the bit set for the function type.
if (SanOpts.has(SanitizerKind::CFIICall) &&
(!TargetDecl || !isa<FunctionDecl>(TargetDecl)) && !CFIUnchecked) {
- SanitizerScope SanScope(this);
+ auto CheckOrdinal = SanitizerKind::SO_CFIICall;
+ auto CheckHandler = SanitizerHandler::CFICheckFail;
+ SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
EmitSanitizerStatReport(llvm::SanStat_CFI_ICall);
- ApplyDebugLocation ApplyTrapDI(
- *this, SanitizerAnnotateDebugInfo(SanitizerKind::SO_CFIICall));
llvm::Metadata *MD;
if (CGM.getCodeGenOpts().SanitizeCfiICallGeneralizePointers)
@@ -6409,12 +6403,11 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
EmitCheckTypeDescriptor(QualType(FnType, 0)),
};
if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {
- EmitCfiSlowPathCheck(SanitizerKind::SO_CFIICall, TypeTest, CrossDsoTypeId,
- CalleePtr, StaticData);
+ EmitCfiSlowPathCheck(CheckOrdinal, TypeTest, CrossDsoTypeId, CalleePtr,
+ StaticData);
} else {
- EmitCheck(std::make_pair(TypeTest, SanitizerKind::SO_CFIICall),
- SanitizerHandler::CFICheckFail, StaticData,
- {CalleePtr, llvm::UndefValue::get(IntPtrTy)});
+ EmitCheck(std::make_pair(TypeTest, CheckOrdinal), CheckHandler,
+ StaticData, {CalleePtr, llvm::UndefValue::get(IntPtrTy)});
}
}
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 111b580..193710b 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -999,7 +999,9 @@ void ScalarExprEmitter::EmitFloatConversionCheck(
if (!isa<llvm::IntegerType>(DstTy))
return;
- CodeGenFunction::SanitizerScope SanScope(&CGF);
+ auto CheckOrdinal = SanitizerKind::SO_FloatCastOverflow;
+ auto CheckHandler = SanitizerHandler::FloatCastOverflow;
+ SanitizerDebugLocation SanScope(&CGF, {CheckOrdinal}, CheckHandler);
using llvm::APFloat;
using llvm::APSInt;
@@ -1056,8 +1058,8 @@ void ScalarExprEmitter::EmitFloatConversionCheck(
llvm::Constant *StaticArgs[] = {CGF.EmitCheckSourceLocation(Loc),
CGF.EmitCheckTypeDescriptor(OrigSrcType),
CGF.EmitCheckTypeDescriptor(DstType)};
- CGF.EmitCheck(std::make_pair(Check, SanitizerKind::SO_FloatCastOverflow),
- SanitizerHandler::FloatCastOverflow, StaticArgs, OrigSrc);
+ CGF.EmitCheck(std::make_pair(Check, CheckOrdinal), CheckHandler, StaticArgs,
+ OrigSrc);
}
// Should be called within CodeGenFunction::SanitizerScope RAII scope.
@@ -1134,18 +1136,31 @@ void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType,
(!SrcSigned && DstSigned))
return;
- CodeGenFunction::SanitizerScope SanScope(&CGF);
-
std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
std::pair<llvm::Value *, SanitizerKind::SanitizerOrdinal>>
- Check =
- EmitIntegerTruncationCheckHelper(Src, SrcType, Dst, DstType, Builder);
- // If the comparison result is 'i1 false', then the truncation was lossy.
+ Check;
+
+ auto CheckHandler = SanitizerHandler::ImplicitConversion;
+ {
+ // We don't know the check kind until we call
+ // EmitIntegerTruncationCheckHelper, but we want to annotate
+ // EmitIntegerTruncationCheckHelper's instructions too.
+ SanitizerDebugLocation SanScope(
+ &CGF,
+ {SanitizerKind::SO_ImplicitUnsignedIntegerTruncation,
+ SanitizerKind::SO_ImplicitSignedIntegerTruncation},
+ CheckHandler);
+ Check =
+ EmitIntegerTruncationCheckHelper(Src, SrcType, Dst, DstType, Builder);
+ // If the comparison result is 'i1 false', then the truncation was lossy.
+ }
// Do we care about this type of truncation?
if (!CGF.SanOpts.has(Check.second.second))
return;
+ SanitizerDebugLocation SanScope(&CGF, {Check.second.second}, CheckHandler);
+
// Does some SSCL ignore this type?
if (CGF.getContext().isTypeIgnoredBySanitizer(
SanitizerMask::bitPosToMask(Check.second.second), DstType))
@@ -1157,8 +1172,7 @@ void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType,
llvm::ConstantInt::get(Builder.getInt8Ty(), Check.first),
llvm::ConstantInt::get(Builder.getInt32Ty(), 0)};
- CGF.EmitCheck(Check.second, SanitizerHandler::ImplicitConversion, StaticArgs,
- {Src, Dst});
+ CGF.EmitCheck(Check.second, CheckHandler, StaticArgs, {Src, Dst});
}
static llvm::Value *EmitIsNegativeTestHelper(Value *V, QualType VType,
@@ -1272,7 +1286,13 @@ void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType,
return;
// That's it. We can't rule out any more cases with the data we have.
- CodeGenFunction::SanitizerScope SanScope(&CGF);
+ auto CheckHandler = SanitizerHandler::ImplicitConversion;
+ SanitizerDebugLocation SanScope(
+ &CGF,
+ {SanitizerKind::SO_ImplicitIntegerSignChange,
+ SanitizerKind::SO_ImplicitUnsignedIntegerTruncation,
+ SanitizerKind::SO_ImplicitSignedIntegerTruncation},
+ CheckHandler);
std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
std::pair<llvm::Value *, SanitizerKind::SanitizerOrdinal>>
@@ -1308,8 +1328,7 @@ void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType,
llvm::ConstantInt::get(Builder.getInt8Ty(), CheckKind),
llvm::ConstantInt::get(Builder.getInt32Ty(), 0)};
// EmitCheck() will 'and' all the checks together.
- CGF.EmitCheck(Checks, SanitizerHandler::ImplicitConversion, StaticArgs,
- {Src, Dst});
+ CGF.EmitCheck(Checks, CheckHandler, StaticArgs, {Src, Dst});
}
// Should be called within CodeGenFunction::SanitizerScope RAII scope.
@@ -1393,7 +1412,9 @@ void CodeGenFunction::EmitBitfieldConversionCheck(Value *Src, QualType SrcType,
bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType();
bool DstSigned = DstType->isSignedIntegerOrEnumerationType();
- CodeGenFunction::SanitizerScope SanScope(this);
+ auto CheckHandler = SanitizerHandler::ImplicitConversion;
+ SanitizerDebugLocation SanScope(
+ this, {SanitizerKind::SO_ImplicitBitfieldConversion}, CheckHandler);
std::pair<ScalarExprEmitter::ImplicitConversionCheckKind,
std::pair<llvm::Value *, SanitizerKind::SanitizerOrdinal>>
@@ -1439,8 +1460,7 @@ void CodeGenFunction::EmitBitfieldConversionCheck(Value *Src, QualType SrcType,
llvm::ConstantInt::get(Builder.getInt8Ty(), CheckKind),
llvm::ConstantInt::get(Builder.getInt32Ty(), Info.Size)};
- EmitCheck(Check.second, SanitizerHandler::ImplicitConversion, StaticArgs,
- {Src, Dst});
+ EmitCheck(Check.second, CheckHandler, StaticArgs, {Src, Dst});
}
Value *ScalarExprEmitter::EmitScalarCast(Value *Src, QualType SrcType,
@@ -3975,7 +3995,11 @@ void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
{
- CodeGenFunction::SanitizerScope SanScope(&CGF);
+ SanitizerDebugLocation SanScope(&CGF,
+ {SanitizerKind::SO_IntegerDivideByZero,
+ SanitizerKind::SO_SignedIntegerOverflow,
+ SanitizerKind::SO_FloatDivideByZero},
+ SanitizerHandler::DivremOverflow);
if ((CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero) ||
CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) &&
Ops.Ty->isIntegerType() &&
@@ -4029,7 +4053,10 @@ Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) {
CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) &&
Ops.Ty->isIntegerType() &&
(Ops.mayHaveIntegerDivisionByZero() || Ops.mayHaveIntegerOverflow())) {
- CodeGenFunction::SanitizerScope SanScope(&CGF);
+ SanitizerDebugLocation SanScope(&CGF,
+ {SanitizerKind::SO_IntegerDivideByZero,
+ SanitizerKind::SO_SignedIntegerOverflow},
+ SanitizerHandler::DivremOverflow);
llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, false);
}
@@ -4078,7 +4105,10 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
if (isSigned)
OpID |= 1;
- CodeGenFunction::SanitizerScope SanScope(&CGF);
+ SanitizerDebugLocation SanScope(&CGF,
+ {SanitizerKind::SO_SignedIntegerOverflow,
+ SanitizerKind::SO_UnsignedIntegerOverflow},
+ OverflowKind);
llvm::Type *opTy = CGF.CGM.getTypes().ConvertType(Ops.Ty);
llvm::Function *intrinsic = CGF.CGM.getIntrinsic(IID, opTy);
@@ -4204,7 +4234,9 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
PtrTy->getPointerAddressSpace()))
return Ptr;
// The inbounds GEP of null is valid iff the index is zero.
- CodeGenFunction::SanitizerScope SanScope(&CGF);
+ auto CheckOrdinal = SanitizerKind::SO_PointerOverflow;
+ auto CheckHandler = SanitizerHandler::PointerOverflow;
+ SanitizerDebugLocation SanScope(&CGF, {CheckOrdinal}, CheckHandler);
Value *IsZeroIndex = CGF.Builder.CreateIsNull(index);
llvm::Constant *StaticArgs[] = {
CGF.EmitCheckSourceLocation(op.E->getExprLoc())};
@@ -4212,8 +4244,8 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
Value *IntPtr = llvm::Constant::getNullValue(IntPtrTy);
Value *ComputedGEP = CGF.Builder.CreateZExtOrTrunc(index, IntPtrTy);
Value *DynamicArgs[] = {IntPtr, ComputedGEP};
- CGF.EmitCheck({{IsZeroIndex, SanitizerKind::SO_PointerOverflow}},
- SanitizerHandler::PointerOverflow, StaticArgs, DynamicArgs);
+ CGF.EmitCheck({{IsZeroIndex, CheckOrdinal}}, CheckHandler, StaticArgs,
+ DynamicArgs);
return Ptr;
}
@@ -4734,7 +4766,16 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
RHS = ConstrainShiftValue(Ops.LHS, RHS, "shl.mask");
else if ((SanitizeBase || SanitizeExponent) &&
isa<llvm::IntegerType>(Ops.LHS->getType())) {
- CodeGenFunction::SanitizerScope SanScope(&CGF);
+ SmallVector<SanitizerKind::SanitizerOrdinal, 3> Ordinals;
+ if (SanitizeSignedBase)
+ Ordinals.push_back(SanitizerKind::SO_ShiftBase);
+ if (SanitizeUnsignedBase)
+ Ordinals.push_back(SanitizerKind::SO_UnsignedShiftBase);
+ if (SanitizeExponent)
+ Ordinals.push_back(SanitizerKind::SO_ShiftExponent);
+
+ SanitizerDebugLocation SanScope(&CGF, Ordinals,
+ SanitizerHandler::ShiftOutOfBounds);
SmallVector<std::pair<Value *, SanitizerKind::SanitizerOrdinal>, 2> Checks;
bool RHSIsSigned = Ops.rhsHasSignedIntegerRepresentation();
llvm::Value *WidthMinusOne =
@@ -4805,7 +4846,8 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
RHS = ConstrainShiftValue(Ops.LHS, RHS, "shr.mask");
else if (CGF.SanOpts.has(SanitizerKind::ShiftExponent) &&
isa<llvm::IntegerType>(Ops.LHS->getType())) {
- CodeGenFunction::SanitizerScope SanScope(&CGF);
+ SanitizerDebugLocation SanScope(&CGF, {SanitizerKind::SO_ShiftExponent},
+ SanitizerHandler::ShiftOutOfBounds);
bool RHSIsSigned = Ops.rhsHasSignedIntegerRepresentation();
llvm::Value *Valid = Builder.CreateICmpULE(
Ops.RHS, GetMaximumShiftAmount(Ops.LHS, Ops.RHS, RHSIsSigned));
@@ -6037,7 +6079,9 @@ CodeGenFunction::EmitCheckedInBoundsGEP(llvm::Type *ElemTy, Value *Ptr,
const auto &DL = CGM.getDataLayout();
- SanitizerScope SanScope(this);
+ auto CheckOrdinal = SanitizerKind::SO_PointerOverflow;
+ auto CheckHandler = SanitizerHandler::PointerOverflow;
+ SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
llvm::Type *IntPtrTy = DL.getIntPtrType(PtrTy);
GEPOffsetAndOverflow EvaluatedGEP =
@@ -6074,7 +6118,7 @@ CodeGenFunction::EmitCheckedInBoundsGEP(llvm::Type *ElemTy, Value *Ptr,
auto *BaseIsNotNullptr = Builder.CreateIsNotNull(Ptr);
auto *ResultIsNotNullptr = Builder.CreateIsNotNull(ComputedGEP);
auto *Valid = Builder.CreateICmpEQ(BaseIsNotNullptr, ResultIsNotNullptr);
- Checks.emplace_back(Valid, SanitizerKind::SO_PointerOverflow);
+ Checks.emplace_back(Valid, CheckOrdinal);
}
if (PerformOverflowCheck) {
@@ -6110,7 +6154,7 @@ CodeGenFunction::EmitCheckedInBoundsGEP(llvm::Type *ElemTy, Value *Ptr,
ValidGEP = Builder.CreateICmpULE(ComputedGEP, IntPtr);
}
ValidGEP = Builder.CreateAnd(ValidGEP, NoOffsetOverflow);
- Checks.emplace_back(ValidGEP, SanitizerKind::SO_PointerOverflow);
+ Checks.emplace_back(ValidGEP, CheckOrdinal);
}
assert(!Checks.empty() && "Should have produced some checks.");
@@ -6118,7 +6162,7 @@ CodeGenFunction::EmitCheckedInBoundsGEP(llvm::Type *ElemTy, Value *Ptr,
llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(Loc)};
// Pass the computed GEP to the runtime to avoid emitting poisoned arguments.
llvm::Value *DynamicArgs[] = {IntPtr, ComputedGEP};
- EmitCheck(Checks, SanitizerHandler::PointerOverflow, StaticArgs, DynamicArgs);
+ EmitCheck(Checks, CheckHandler, StaticArgs, DynamicArgs);
return GEPVal;
}
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index ff1dae7..8a1b44a 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -1968,7 +1968,9 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
const ObjCInterfaceType *InterfaceTy =
ObjPtrTy ? ObjPtrTy->getInterfaceType() : nullptr;
if (InterfaceTy) {
- SanitizerScope SanScope(this);
+ auto CheckOrdinal = SanitizerKind::SO_ObjCCast;
+ auto CheckHandler = SanitizerHandler::InvalidObjCCast;
+ SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
auto &C = CGM.getContext();
assert(InterfaceTy->getDecl() && "No decl for ObjC interface type");
Selector IsKindOfClassSel = GetUnarySelector("isKindOfClass", C);
@@ -1985,8 +1987,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
llvm::Constant *StaticData[] = {
EmitCheckSourceLocation(S.getBeginLoc()),
EmitCheckTypeDescriptor(QualType(InterfaceTy, 0))};
- EmitCheck({{IsClass, SanitizerKind::SO_ObjCCast}},
- SanitizerHandler::InvalidObjCCast,
+ EmitCheck({{IsClass, CheckOrdinal}}, CheckHandler,
ArrayRef<llvm::Constant *>(StaticData), CurrentItem);
}
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 3302abad..5656200 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1636,10 +1636,11 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
CGM.getCodeGenOpts().StrictReturn ||
!CGM.MayDropFunctionReturn(FD->getASTContext(), FD->getReturnType());
if (SanOpts.has(SanitizerKind::Return)) {
- SanitizerScope SanScope(this);
+ auto CheckOrdinal = SanitizerKind::SO_Return;
+ auto CheckHandler = SanitizerHandler::MissingReturn;
+ SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
llvm::Value *IsFalse = Builder.getFalse();
- EmitCheck(std::make_pair(IsFalse, SanitizerKind::SO_Return),
- SanitizerHandler::MissingReturn,
+ EmitCheck(std::make_pair(IsFalse, CheckOrdinal), CheckHandler,
EmitCheckSourceLocation(FD->getLocation()), {});
} else if (ShouldEmitUnreachable) {
if (CGM.getCodeGenOpts().OptimizationLevel == 0)
@@ -2541,7 +2542,9 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
// expression [...] each time it is evaluated it shall have a value
// greater than zero.
if (SanOpts.has(SanitizerKind::VLABound)) {
- SanitizerScope SanScope(this);
+ auto CheckOrdinal = SanitizerKind::SO_VLABound;
+ auto CheckHandler = SanitizerHandler::VLABoundNotPositive;
+ SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
llvm::Value *Zero = llvm::Constant::getNullValue(size->getType());
clang::QualType SEType = sizeExpr->getType();
llvm::Value *CheckCondition =
@@ -2551,9 +2554,8 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
llvm::Constant *StaticArgs[] = {
EmitCheckSourceLocation(sizeExpr->getBeginLoc()),
EmitCheckTypeDescriptor(SEType)};
- EmitCheck(
- std::make_pair(CheckCondition, SanitizerKind::SO_VLABound),
- SanitizerHandler::VLABoundNotPositive, StaticArgs, size);
+ EmitCheck(std::make_pair(CheckCondition, CheckOrdinal),
+ CheckHandler, StaticArgs, size);
}
// Always zexting here would be wrong if it weren't
@@ -3196,7 +3198,9 @@ void CodeGenFunction::emitAlignmentAssumptionCheck(
Assumption->removeFromParent();
{
- SanitizerScope SanScope(this);
+ auto CheckOrdinal = SanitizerKind::SO_Alignment;
+ auto CheckHandler = SanitizerHandler::AlignmentAssumption;
+ SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
if (!OffsetValue)
OffsetValue = Builder.getInt1(false); // no offset.
@@ -3205,8 +3209,8 @@ void CodeGenFunction::emitAlignmentAssumptionCheck(
EmitCheckSourceLocation(SecondaryLoc),
EmitCheckTypeDescriptor(Ty)};
llvm::Value *DynamicData[] = {Ptr, Alignment, OffsetValue};
- EmitCheck({std::make_pair(TheCheck, SanitizerKind::SO_Alignment)},
- SanitizerHandler::AlignmentAssumption, StaticData, DynamicData);
+ EmitCheck({std::make_pair(TheCheck, CheckOrdinal)}, CheckHandler,
+ StaticData, DynamicData);
}
// We are now in the (new, empty) "cont" basic block.
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index cecc8c0..a5ab9df 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -3332,10 +3332,12 @@ public:
llvm::Value *Index, QualType IndexType,
QualType IndexedType, bool Accessed);
- /// Returns debug info, with additional annotation if enabled by
- /// CGM.getCodeGenOpts().SanitizeAnnotateDebugInfo[CheckKindOrdinal].
+ /// Returns debug info, with additional annotation if
+ /// CGM.getCodeGenOpts().SanitizeAnnotateDebugInfo[Ordinal] is enabled for
+ /// any of the ordinals.
llvm::DILocation *
- SanitizerAnnotateDebugInfo(SanitizerKind::SanitizerOrdinal CheckKindOrdinal);
+ SanitizerAnnotateDebugInfo(ArrayRef<SanitizerKind::SanitizerOrdinal> Ordinals,
+ SanitizerHandler Handler);
llvm::Value *GetCountedByFieldExprGEP(const Expr *Base, const FieldDecl *FD,
const FieldDecl *CountDecl);
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index aac7bb7..f4a9946 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -713,9 +713,9 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
llvm::Value *VirtualFn = nullptr;
{
- CodeGenFunction::SanitizerScope SanScope(&CGF);
- ApplyDebugLocation ApplyTrapDI(
- CGF, CGF.SanitizerAnnotateDebugInfo(SanitizerKind::SO_CFIMFCall));
+ auto CheckOrdinal = SanitizerKind::SO_CFIMFCall;
+ auto CheckHandler = SanitizerHandler::CFICheckFail;
+ SanitizerDebugLocation SanScope(&CGF, {CheckOrdinal}, CheckHandler);
llvm::Value *TypeId = nullptr;
llvm::Value *CheckResult = nullptr;
@@ -785,16 +785,15 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
};
if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) {
- CGF.EmitTrapCheck(CheckResult, SanitizerHandler::CFICheckFail);
+ CGF.EmitTrapCheck(CheckResult, CheckHandler);
} else {
llvm::Value *AllVtables = llvm::MetadataAsValue::get(
CGM.getLLVMContext(),
llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
llvm::Value *ValidVtable = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
- CGF.EmitCheck(std::make_pair(CheckResult, SanitizerKind::SO_CFIMFCall),
- SanitizerHandler::CFICheckFail, StaticData,
- {VTable, ValidVtable});
+ CGF.EmitCheck(std::make_pair(CheckResult, CheckOrdinal), CheckHandler,
+ StaticData, {VTable, ValidVtable});
}
FnVirtual = Builder.GetInsertBlock();
@@ -813,9 +812,9 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
if (ShouldEmitCFICheck) {
CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
if (RD->hasDefinition()) {
- CodeGenFunction::SanitizerScope SanScope(&CGF);
- ApplyDebugLocation ApplyTrapDI(
- CGF, CGF.SanitizerAnnotateDebugInfo(SanitizerKind::SO_CFIMFCall));
+ auto CheckOrdinal = SanitizerKind::SO_CFIMFCall;
+ auto CheckHandler = SanitizerHandler::CFICheckFail;
+ SanitizerDebugLocation SanScope(&CGF, {CheckOrdinal}, CheckHandler);
llvm::Constant *StaticData[] = {
llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_NVMFCall),
@@ -838,8 +837,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
Bit = Builder.CreateOr(Bit, TypeTest);
}
- CGF.EmitCheck(std::make_pair(Bit, SanitizerKind::SO_CFIMFCall),
- SanitizerHandler::CFICheckFail, StaticData,
+ CGF.EmitCheck(std::make_pair(Bit, CheckOrdinal), CheckHandler, StaticData,
{NonVirtualFn, llvm::UndefValue::get(CGF.IntPtrTy)});
FnNonVirtual = Builder.GetInsertBlock();