diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 72 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 34 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 12 |
6 files changed, 85 insertions, 48 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 533d1581e5c..3086de61abc 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -476,8 +476,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, if (SanOpts.has(SanitizerKind::Unreachable)) { SanitizerScope SanScope(this); EmitCheck(Builder.getFalse(), "builtin_unreachable", - EmitCheckSourceLocation(E->getExprLoc()), - None, CRK_Unrecoverable); + EmitCheckSourceLocation(E->getExprLoc()), None, + SanitizerKind::Unreachable); } else Builder.CreateUnreachable(); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 6f2a27f977a..ca5db851df3 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2300,7 +2300,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, EmitCheckSourceLocation(EndLoc), EmitCheckSourceLocation(RetNNAttr->getLocation()), }; - EmitCheck(Cond, "nonnull_return", StaticData, None, CRK_Recoverable); + EmitCheck(Cond, "nonnull_return", StaticData, None, + SanitizerKind::ReturnsNonnullAttribute); } } Ret = Builder.CreateRet(RV); @@ -2636,7 +2637,7 @@ static void emitNonNullArgCheck(CodeGenFunction &CGF, RValue RV, llvm::ConstantInt::get(CGF.Int32Ty, ArgNo + 1), }; CGF.EmitCheck(Cond, "nonnull_arg", StaticData, None, - CodeGenFunction::CRK_Recoverable); + SanitizerKind::NonnullAttribute); } void CodeGenFunction::EmitCallArgs(CallArgList &Args, diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index e1b9b7b3577..389cd000a72 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -475,6 +475,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, if (Address->getType()->getPointerAddressSpace()) return; + SmallVector<SanitizerKind, 3> Kinds; SanitizerScope SanScope(this); llvm::Value *Cond = nullptr; @@ -496,6 +497,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, Builder.CreateCondBr(Cond, Rest, Done); EmitBlock(Rest); Cond = nullptr; + } else { + Kinds.push_back(SanitizerKind::Null); } } @@ -514,6 +517,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, Builder.CreateICmpUGE(Builder.CreateCall2(F, CastAddr, Min), llvm::ConstantInt::get(IntPtrTy, Size)); Cond = Cond ? Builder.CreateAnd(Cond, LargeEnough) : LargeEnough; + Kinds.push_back(SanitizerKind::ObjectSize); } uint64_t AlignVal = 0; @@ -531,6 +535,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, llvm::Value *Aligned = Builder.CreateICmpEQ(Align, llvm::ConstantInt::get(IntPtrTy, 0)); Cond = Cond ? Builder.CreateAnd(Cond, Aligned) : Aligned; + Kinds.push_back(SanitizerKind::Alignment); } } @@ -541,7 +546,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, llvm::ConstantInt::get(SizeTy, AlignVal), llvm::ConstantInt::get(Int8Ty, TCK) }; - EmitCheck(Cond, "type_mismatch", StaticData, Address, CRK_Recoverable); + EmitCheck(Cond, "type_mismatch", StaticData, Address, Kinds); } // If possible, check that the vptr indicates that there is a subobject of @@ -606,9 +611,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, llvm::ConstantInt::get(Int8Ty, TCK) }; llvm::Value *DynamicData[] = { Address, Hash }; - EmitCheck(Builder.CreateICmpEQ(CacheVal, Hash), - "dynamic_type_cache_miss", StaticData, DynamicData, - CRK_AlwaysRecoverable); + EmitCheck(Builder.CreateICmpEQ(CacheVal, Hash), "dynamic_type_cache_miss", + StaticData, DynamicData, SanitizerKind::Vptr); } } @@ -696,7 +700,8 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base, }; llvm::Value *Check = Accessed ? Builder.CreateICmpULT(IndexVal, BoundVal) : Builder.CreateICmpULE(IndexVal, BoundVal); - EmitCheck(Check, "out_of_bounds", StaticData, Index, CRK_Recoverable); + EmitCheck(Check, "out_of_bounds", StaticData, Index, + SanitizerKind::ArrayBounds); } @@ -1151,8 +1156,11 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, CGM.DecorateInstruction(Load, TBAAPath, false/*ConvertTypeToTag*/); } - if ((SanOpts.has(SanitizerKind::Bool) && hasBooleanRepresentation(Ty)) || - (SanOpts.has(SanitizerKind::Enum) && Ty->getAs<EnumType>())) { + bool NeedsBoolCheck = + SanOpts.has(SanitizerKind::Bool) && hasBooleanRepresentation(Ty); + bool NeedsEnumCheck = + SanOpts.has(SanitizerKind::Enum) && Ty->getAs<EnumType>(); + if (NeedsBoolCheck || NeedsEnumCheck) { SanitizerScope SanScope(this); llvm::APInt Min, End; if (getRangeForType(*this, Ty, Min, End, true)) { @@ -1173,7 +1181,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, EmitCheckTypeDescriptor(Ty) }; EmitCheck(Check, "load_invalid_value", StaticArgs, EmitCheckValue(Load), - CRK_Recoverable); + NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool); } } else if (CGM.getCodeGenOpts().OptimizationLevel > 0) if (llvm::MDNode *RangeInfo = getRangeForLoadFromType(Ty)) @@ -2169,14 +2177,45 @@ llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) { return llvm::ConstantStruct::getAnon(Data); } +namespace { +/// \brief Specify under what conditions this check can be recovered +enum class CheckRecoverableKind { + /// Always terminate program execution if this check fails + Unrecoverable, + /// Check supports recovering, allows user to specify which + Recoverable, + /// Runtime conditionally aborts, always need to support recovery. + AlwaysRecoverable +}; +} + +static CheckRecoverableKind getRecoverableKind(SanitizerKind Kind) { + switch (Kind) { + case SanitizerKind::Vptr: + return CheckRecoverableKind::AlwaysRecoverable; + case SanitizerKind::Return: + case SanitizerKind::Unreachable: + return CheckRecoverableKind::Unrecoverable; + default: + return CheckRecoverableKind::Recoverable; + } +} + void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName, ArrayRef<llvm::Constant *> StaticArgs, ArrayRef<llvm::Value *> DynamicArgs, - CheckRecoverableKind RecoverKind) { + ArrayRef<SanitizerKind> Kinds) { assert(IsSanitizerScope); + assert(Kinds.size() > 0); + CheckRecoverableKind RecoverKind = getRecoverableKind(Kinds[0]); + for (int i = 1, n = Kinds.size(); i < n; ++i) + assert(RecoverKind == getRecoverableKind(Kinds[i]) && + "All recoverable kinds in a single check must be same!"); + for (auto Kind : Kinds) + assert(SanOpts.has(Kind)); if (CGM.getCodeGenOpts().SanitizeUndefinedTrapOnError) { - assert (RecoverKind != CRK_AlwaysRecoverable && + assert (RecoverKind != CheckRecoverableKind::AlwaysRecoverable && "Runtime call required for AlwaysRecoverable kind!"); return EmitTrapCheck(Checked); } @@ -2217,8 +2256,8 @@ void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName, ArgTypes.push_back(IntPtrTy); } - bool Recover = RecoverKind == CRK_AlwaysRecoverable || - (RecoverKind == CRK_Recoverable && + bool Recover = RecoverKind == CheckRecoverableKind::AlwaysRecoverable || + (RecoverKind == CheckRecoverableKind::Recoverable && CGM.getCodeGenOpts().SanitizeRecover); llvm::FunctionType *FnType = @@ -2231,7 +2270,7 @@ void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName, B.addAttribute(llvm::Attribute::UWTable); // Checks that have two variants use a suffix to differentiate them - bool NeedsAbortSuffix = RecoverKind != CRK_Unrecoverable && + bool NeedsAbortSuffix = RecoverKind != CheckRecoverableKind::Unrecoverable && !CGM.getCodeGenOpts().SanitizeRecover; std::string FunctionName = ("__ubsan_handle_" + CheckName + (NeedsAbortSuffix? "_abort" : "")).str(); @@ -3260,11 +3299,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee, EmitCheckSourceLocation(E->getLocStart()), EmitCheckTypeDescriptor(CalleeType) }; - EmitCheck(CalleeRTTIMatch, - "function_type_mismatch", - StaticData, - Callee, - CRK_Recoverable); + EmitCheck(CalleeRTTIMatch, "function_type_mismatch", StaticData, Callee, + SanitizerKind::Function); Builder.CreateBr(Cont); EmitBlock(Cont); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 36a001f242b..10094228995 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -85,7 +85,8 @@ public: return CGF.EmitCheckedLValue(E, TCK); } - void EmitBinOpCheck(Value *Check, const BinOpInfo &Info); + void EmitBinOpCheck(Value *Check, const BinOpInfo &Info, + ArrayRef<SanitizerKind> Kinds); Value *EmitLoadOfLValue(LValue LV, SourceLocation Loc) { return CGF.EmitLoadOfLValue(LV, Loc).getScalarVal(); @@ -726,7 +727,7 @@ void ScalarExprEmitter::EmitFloatConversionCheck(Value *OrigSrc, CGF.EmitCheckTypeDescriptor(DstType) }; CGF.EmitCheck(Check, "float_cast_overflow", StaticArgs, OrigSrc, - CodeGenFunction::CRK_Recoverable); + SanitizerKind::FloatCastOverflow); } /// EmitScalarConversion - Emit a conversion from the specified type to the @@ -885,7 +886,8 @@ Value *ScalarExprEmitter::EmitNullValue(QualType Ty) { /// \brief Emit a sanitization check for the given "binary" operation (which /// 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) { +void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info, + ArrayRef<SanitizerKind> Kinds) { assert(CGF.IsSanitizerScope); StringRef CheckName; SmallVector<llvm::Constant *, 4> StaticData; @@ -915,7 +917,7 @@ void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info) { CheckName = "divrem_overflow"; StaticData.push_back(CGF.EmitCheckTypeDescriptor(Info.Ty)); } else { - // Signed arithmetic overflow (+, -, *). + // Arithmetic overflow (+, -, *). switch (Opcode) { case BO_Add: CheckName = "add_overflow"; break; case BO_Sub: CheckName = "sub_overflow"; break; @@ -928,8 +930,7 @@ void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info) { DynamicData.push_back(Info.RHS); } - CGF.EmitCheck(Check, CheckName, StaticData, DynamicData, - CodeGenFunction::CRK_Recoverable); + CGF.EmitCheck(Check, CheckName, StaticData, DynamicData, Kinds); } //===----------------------------------------------------------------------===// @@ -2179,9 +2180,12 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck( const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) { llvm::Value *Cond = nullptr; + SmallVector<SanitizerKind, 2> Kinds; - if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) + if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) { Cond = Builder.CreateICmpNE(Ops.RHS, Zero); + Kinds.push_back(SanitizerKind::IntegerDivideByZero); + } if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) && Ops.Ty->hasSignedIntegerRepresentation()) { @@ -2195,10 +2199,11 @@ void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck( llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne); llvm::Value *Overflow = Builder.CreateOr(LHSCmp, RHSCmp, "or"); Cond = Cond ? Builder.CreateAnd(Cond, Overflow, "and") : Overflow; + Kinds.push_back(SanitizerKind::SignedIntegerOverflow); } if (Cond) - EmitBinOpCheck(Cond, Ops); + EmitBinOpCheck(Cond, Ops, Kinds); } Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) { @@ -2212,7 +2217,8 @@ Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) { } else if (CGF.SanOpts.has(SanitizerKind::FloatDivideByZero) && Ops.Ty->isRealFloatingType()) { llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty)); - EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops); + EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops, + SanitizerKind::FloatDivideByZero); } } @@ -2297,7 +2303,9 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) { // runtime. Otherwise, this is a -ftrapv check, so just emit a trap. if (!isSigned || CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) { CodeGenFunction::SanitizerScope SanScope(&CGF); - EmitBinOpCheck(Builder.CreateNot(overflow), Ops); + EmitBinOpCheck(Builder.CreateNot(overflow), Ops, + isSigned ? SanitizerKind::SignedIntegerOverflow + : SanitizerKind::UnsignedIntegerOverflow); } else CGF.EmitTrapCheck(Builder.CreateNot(overflow)); return result; @@ -2687,7 +2695,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { Valid = P; } - EmitBinOpCheck(Valid, Ops); + EmitBinOpCheck(Valid, Ops, SanitizerKind::Shift); } // OpenCL 6.3j: shift values are effectively % word size of LHS. if (CGF.getLangOpts().OpenCL) @@ -2706,7 +2714,9 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) { if (CGF.SanOpts.has(SanitizerKind::Shift) && !CGF.getLangOpts().OpenCL && isa<llvm::IntegerType>(Ops.LHS->getType())) { CodeGenFunction::SanitizerScope SanScope(&CGF); - EmitBinOpCheck(Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops); + EmitBinOpCheck( + Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops, + SanitizerKind::Shift); } // OpenCL 6.3j: shift values are effectively % word size of LHS. diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 5853e076839..cbedf61c559 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -900,8 +900,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, if (SanOpts.has(SanitizerKind::Return)) { SanitizerScope SanScope(this); EmitCheck(Builder.getFalse(), "missing_return", - EmitCheckSourceLocation(FD->getLocation()), - None, CRK_Unrecoverable); + EmitCheckSourceLocation(FD->getLocation()), None, + SanitizerKind::Return); } else if (CGM.getCodeGenOpts().OptimizationLevel == 0) Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap)); Builder.CreateUnreachable(); @@ -1562,7 +1562,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { }; EmitCheck(Builder.CreateICmpSGT(Size, Zero), "vla_bound_not_positive", StaticArgs, Size, - CRK_Recoverable); + SanitizerKind::VLABound); } // Always zexting here would be wrong if it weren't diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index a683e88783f..de2f4daed9b 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2649,23 +2649,13 @@ public: /// passing to a runtime sanitizer handler. llvm::Constant *EmitCheckSourceLocation(SourceLocation Loc); - /// \brief Specify under what conditions this check can be recovered - enum CheckRecoverableKind { - /// Always terminate program execution if this check fails - CRK_Unrecoverable, - /// Check supports recovering, allows user to specify which - CRK_Recoverable, - /// Runtime conditionally aborts, always need to support recovery. - CRK_AlwaysRecoverable - }; - /// \brief Create a basic block that will call a handler function in a /// sanitizer runtime with the provided arguments, and create a conditional /// branch to it. void EmitCheck(llvm::Value *Checked, StringRef CheckName, ArrayRef<llvm::Constant *> StaticArgs, ArrayRef<llvm::Value *> DynamicArgs, - CheckRecoverableKind Recoverable); + ArrayRef<SanitizerKind> Kinds); /// \brief Create a basic block that will call the trap intrinsic, and emit a /// conditional branch to it, for the -ftrapv checks. |