From: Alexey Samsonov Date: Thu, 17 Jul 2014 18:46:27 +0000 (+0000) Subject: [UBSan] Add !nosanitize metadata to the code generated by UBSan. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=24cad9930709a6448c4b23194ac06bf233ed18a6;p=platform%2Fupstream%2Fllvm.git [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 llvm-svn: 213291 --- diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 4bdc87e..4f68b34 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/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(), CRK_Unrecoverable); - else + } else Builder.CreateUnreachable(); // We do need to preserve an insertion point. diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index a43cf30..63731b7 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/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())) { + 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 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(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/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 86f4787..9e0fbcf 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/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 StaticData; SmallVector 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(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(Ops.LHS->getType())) + isa(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/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 0987673..5ca3a78 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/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(), 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())); + } } template diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index d6675f3..f7a9168 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/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/clang/test/CodeGen/catch-undef-behavior.c b/clang/test/CodeGen/catch-undef-behavior.c index 9be2614..724194e 100644 --- a/clang/test/CodeGen/catch-undef-behavior.c +++ b/clang/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]]