From: Alexey Samsonov <vonosmas@gmail.com> Date: Thu, 17 Jul 2014 18:46:27 +0000 (+0000) Subject: [UBSan] Add !nosanitize metadata to the code generated by UBSan. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f35aa7813bafa9c5ab3ff526f0395974a683f600;p=clang [UBSan] Add !nosanitize metadata to the code generated by UBSan. This is used to mark the instructions emitted by Clang to implement variety of UBSan checks. Generally, we don't want to instrument these instructions with another sanitizers (like ASan). Reviewed in http://reviews.llvm.org/D4544 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@213291 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 4bdc87e2d4..4f68b347db 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -447,11 +447,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(Builder.CreateCall(F)); } case Builtin::BI__builtin_unreachable: { - if (SanOpts->Unreachable) + if (SanOpts->Unreachable) { + SanitizerScope SanScope(this); EmitCheck(Builder.getFalse(), "builtin_unreachable", EmitCheckSourceLocation(E->getExprLoc()), ArrayRef<llvm::Value *>(), CRK_Unrecoverable); - else + } else Builder.CreateUnreachable(); // We do need to preserve an insertion point. diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index a43cf30da7..63731b7b7d 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -458,6 +458,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, if (Address->getType()->getPointerAddressSpace()) return; + SanitizerScope SanScope(this); + llvm::Value *Cond = nullptr; llvm::BasicBlock *Done = nullptr; @@ -654,6 +656,7 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base, bool Accessed) { assert(SanOpts->ArrayBounds && "should not be called unless adding bounds checks"); + SanitizerScope SanScope(this); QualType IndexedType; llvm::Value *Bound = getArrayIndexingBound(*this, Base, IndexedType); @@ -1129,6 +1132,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, if ((SanOpts->Bool && hasBooleanRepresentation(Ty)) || (SanOpts->Enum && Ty->getAs<EnumType>())) { + SanitizerScope SanScope(this); llvm::APInt Min, End; if (getRangeForType(*this, Ty, Min, End, true)) { --End; @@ -2183,6 +2187,7 @@ void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName, ArrayRef<llvm::Value *> DynamicArgs, CheckRecoverableKind RecoverKind) { assert(SanOpts != &SanitizerOptions::Disabled); + assert(IsSanitizerScope); if (CGM.getCodeGenOpts().SanitizeUndefinedTrapOnError) { assert (RecoverKind != CRK_AlwaysRecoverable && @@ -3231,6 +3236,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee, (!TargetDecl || !isa<FunctionDecl>(TargetDecl))) { if (llvm::Constant *PrefixSig = CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) { + SanitizerScope SanScope(this); llvm::Constant *FTRTTIConst = CGM.GetAddrOfRTTIDescriptor(QualType(FnType, 0), /*ForEH=*/true); llvm::Type *PrefixStructTyElems[] = { diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 86f47872ae..9e0fbcfd18 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -554,6 +554,7 @@ void ScalarExprEmitter::EmitFloatConversionCheck(Value *OrigSrc, Value *Src, QualType SrcType, QualType DstType, llvm::Type *DstTy) { + CodeGenFunction::SanitizerScope SanScope(&CGF); using llvm::APFloat; using llvm::APSInt; @@ -840,6 +841,7 @@ Value *ScalarExprEmitter::EmitNullValue(QualType Ty) { /// might actually be a unary increment which has been lowered to a binary /// operation). The check passes if \p Check, which is an \c i1, is \c true. void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info) { + assert(CGF.IsSanitizerScope); StringRef CheckName; SmallVector<llvm::Constant *, 4> StaticData; SmallVector<llvm::Value *, 2> DynamicData; @@ -2153,15 +2155,18 @@ void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck( } Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) { - if ((CGF.SanOpts->IntegerDivideByZero || - CGF.SanOpts->SignedIntegerOverflow) && - Ops.Ty->isIntegerType()) { - llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); - EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, true); - } else if (CGF.SanOpts->FloatDivideByZero && - Ops.Ty->isRealFloatingType()) { - llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); - EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops); + { + CodeGenFunction::SanitizerScope SanScope(&CGF); + if ((CGF.SanOpts->IntegerDivideByZero || + CGF.SanOpts->SignedIntegerOverflow) && + Ops.Ty->isIntegerType()) { + llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); + EmitUndefinedBehaviorIntegerDivAndRemCheck(Ops, Zero, true); + } else if (CGF.SanOpts->FloatDivideByZero && + Ops.Ty->isRealFloatingType()) { + llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); + EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops); + } } if (Ops.LHS->getType()->isFPOrFPVectorTy()) { @@ -2185,6 +2190,7 @@ Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) { Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) { // Rem in C can't be a floating point type: C99 6.5.5p2. if (CGF.SanOpts->IntegerDivideByZero) { + CodeGenFunction::SanitizerScope SanScope(&CGF); llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); if (Ops.Ty->isIntegerType()) @@ -2242,9 +2248,10 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) { if (handlerName->empty()) { // If the signed-integer-overflow sanitizer is enabled, emit a call to its // runtime. Otherwise, this is a -ftrapv check, so just emit a trap. - if (!isSigned || CGF.SanOpts->SignedIntegerOverflow) + if (!isSigned || CGF.SanOpts->SignedIntegerOverflow) { + CodeGenFunction::SanitizerScope SanScope(&CGF); EmitBinOpCheck(Builder.CreateNot(overflow), Ops); - else + } else CGF.EmitTrapCheck(Builder.CreateNot(overflow)); return result; } @@ -2596,6 +2603,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { if (CGF.SanOpts->Shift && !CGF.getLangOpts().OpenCL && isa<llvm::IntegerType>(Ops.LHS->getType())) { + CodeGenFunction::SanitizerScope SanScope(&CGF); llvm::Value *WidthMinusOne = GetWidthMinusOneValue(Ops.LHS, RHS); llvm::Value *Valid = Builder.CreateICmpULE(RHS, WidthMinusOne); @@ -2647,8 +2655,10 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) { RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom"); if (CGF.SanOpts->Shift && !CGF.getLangOpts().OpenCL && - isa<llvm::IntegerType>(Ops.LHS->getType())) + isa<llvm::IntegerType>(Ops.LHS->getType())) { + CodeGenFunction::SanitizerScope SanScope(&CGF); EmitBinOpCheck(Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops); + } // OpenCL 6.3j: shift values are effectively % word size of LHS. if (CGF.getLangOpts().OpenCL) diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 0987673bb2..5ca3a78bb4 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -36,8 +36,9 @@ using namespace CodeGen; CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) : CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()), Builder(cgm.getModule().getContext(), llvm::ConstantFolder(), - CGBuilderInserterTy(this)), CapturedStmtInfo(nullptr), - SanOpts(&CGM.getLangOpts().Sanitize), AutoreleaseResult(false), BlockInfo(nullptr), + CGBuilderInserterTy(this)), + CapturedStmtInfo(nullptr), SanOpts(&CGM.getLangOpts().Sanitize), + IsSanitizerScope(false), AutoreleaseResult(false), BlockInfo(nullptr), BlockPointer(nullptr), LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr), NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr), @@ -843,11 +844,12 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, // function call is used by the caller, the behavior is undefined. if (getLangOpts().CPlusPlus && !FD->hasImplicitReturnZero() && !FD->getReturnType()->isVoidType() && Builder.GetInsertBlock()) { - if (SanOpts->Return) + if (SanOpts->Return) { + SanitizerScope SanScope(this); EmitCheck(Builder.getFalse(), "missing_return", EmitCheckSourceLocation(FD->getLocation()), ArrayRef<llvm::Value *>(), CRK_Unrecoverable); - else if (CGM.getCodeGenOpts().OptimizationLevel == 0) + } else if (CGM.getCodeGenOpts().OptimizationLevel == 0) Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap)); Builder.CreateUnreachable(); Builder.ClearInsertionPoint(); @@ -1499,6 +1501,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { // greater than zero. if (SanOpts->VLABound && size->getType()->isSignedIntegerType()) { + SanitizerScope SanScope(this); llvm::Value *Zero = llvm::Constant::getNullValue(Size->getType()); llvm::Constant *StaticArgs[] = { EmitCheckSourceLocation(size->getLocStart()), @@ -1637,11 +1640,26 @@ llvm::Value *CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D, CodeGenFunction::CGCapturedStmtInfo::~CGCapturedStmtInfo() { } +CodeGenFunction::SanitizerScope::SanitizerScope(CodeGenFunction *CGF) + : CGF(CGF) { + assert(!CGF->IsSanitizerScope); + CGF->IsSanitizerScope = true; +} + +CodeGenFunction::SanitizerScope::~SanitizerScope() { + CGF->IsSanitizerScope = false; +} + void CodeGenFunction::InsertHelper(llvm::Instruction *I, const llvm::Twine &Name, llvm::BasicBlock *BB, llvm::BasicBlock::iterator InsertPt) const { LoopStack.InsertHelper(I); + if (IsSanitizerScope) { + I->setMetadata( + CGM.getModule().getMDKindID("nosanitize"), + llvm::MDNode::get(CGM.getLLVMContext(), ArrayRef<llvm::Value *>())); + } } template <bool PreserveNames> diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index d6675f39c7..f7a91686e3 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -247,6 +247,17 @@ public: /// \brief Sanitizer options to use for this function. const SanitizerOptions *SanOpts; + /// \brief True if CodeGen currently emits code implementing sanitizer checks. + bool IsSanitizerScope; + + /// \brief RAII object to set/unset CodeGenFunction::IsSanitizerScope. + class SanitizerScope { + CodeGenFunction *CGF; + public: + SanitizerScope(CodeGenFunction *CGF); + ~SanitizerScope(); + }; + /// In ARC, whether we should autorelease the return value. bool AutoreleaseResult; diff --git a/test/CodeGen/catch-undef-behavior.c b/test/CodeGen/catch-undef-behavior.c index 9be261467d..724194e1ff 100644 --- a/test/CodeGen/catch-undef-behavior.c +++ b/test/CodeGen/catch-undef-behavior.c @@ -49,7 +49,7 @@ void foo() { // CHECK-TRAP-NEXT: %[[CHECK2:.*]] = icmp eq i64 %[[MISALIGN]], 0 // CHECK: %[[OK:.*]] = and i1 %[[CHECK01]], %[[CHECK2]] - // CHECK-NEXT: br i1 %[[OK]], {{.*}} !prof ![[WEIGHT_MD:.*]] + // CHECK-NEXT: br i1 %[[OK]], {{.*}} !prof ![[WEIGHT_MD:.*]], !nosanitize // CHECK-TRAP: %[[OK:.*]] = and i1 %[[CHECK01]], %[[CHECK2]] // CHECK-TRAP-NEXT: br i1 %[[OK]], {{.*}} @@ -311,7 +311,7 @@ int long_double_int_overflow(long double ld) { // CHECK: %[[LE:.*]] = fcmp olt x86_fp80 %[[F]], 0xK401E8000000000000000 // CHECK: and i1 %[[GE]], %[[LE]] - // CHECK: store x86_fp80 %[[F]], x86_fp80* %[[ALLOCA:.*]] + // CHECK: store x86_fp80 %[[F]], x86_fp80* %[[ALLOCA:.*]], !nosanitize // CHECK: %[[ARG:.*]] = ptrtoint x86_fp80* %[[ALLOCA]] to i64 // CHECK: call void @__ubsan_handle_float_cast_overflow({{.*}}, i64 %[[ARG]]