diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCUDARuntime.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 50 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 17 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 16 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.h | 8 |
8 files changed, 95 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 489580e89f3..8c82eb2d912 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -165,7 +165,7 @@ static Value *EmitFAbs(CodeGenFunction &CGF, Value *V, QualType ValTy) { static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *Fn, const CallExpr *E, llvm::Value *calleeValue) { - return CGF.EmitCall(E->getCallee()->getType(), calleeValue, + return CGF.EmitCall(E->getCallee()->getType(), calleeValue, E->getLocStart(), ReturnValueSlot(), E->arg_begin(), E->arg_end(), Fn); } diff --git a/clang/lib/CodeGen/CGCUDARuntime.cpp b/clang/lib/CodeGen/CGCUDARuntime.cpp index fc72008af88..eaf31bb6f67 100644 --- a/clang/lib/CodeGen/CGCUDARuntime.cpp +++ b/clang/lib/CodeGen/CGCUDARuntime.cpp @@ -44,8 +44,8 @@ RValue CGCUDARuntime::EmitCUDAKernelCallExpr(CodeGenFunction &CGF, } llvm::Value *Callee = CGF.EmitScalarExpr(E->getCallee()); - CGF.EmitCall(E->getCallee()->getType(), Callee, ReturnValue, - E->arg_begin(), E->arg_end(), TargetDecl); + CGF.EmitCall(E->getCallee()->getType(), Callee, E->getLocStart(), + ReturnValue, E->arg_begin(), E->arg_end(), TargetDecl); CGF.EmitBranch(ContBlock); CGF.EmitBlock(ContBlock); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 3fd109dcb25..4397c2dabef 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -2931,8 +2931,8 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E, } llvm::Value *Callee = EmitScalarExpr(E->getCallee()); - return EmitCall(E->getCallee()->getType(), Callee, ReturnValue, - E->arg_begin(), E->arg_end(), TargetDecl); + return EmitCall(E->getCallee()->getType(), Callee, E->getLocStart(), + ReturnValue, E->arg_begin(), E->arg_end(), TargetDecl); } LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { @@ -3103,6 +3103,7 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) { } RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee, + SourceLocation CallLoc, ReturnValueSlot ReturnValue, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd, @@ -3123,6 +3124,51 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee, if (const FunctionDecl* FD = dyn_cast_or_null<const FunctionDecl>(TargetDecl)) ForceColumnInfo = FD->isInlineSpecified(); + if (getLangOpts().CPlusPlus && SanOpts->Function && + (!TargetDecl || !isa<FunctionDecl>(TargetDecl))) { + if (llvm::Constant *PrefixSig = + CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) { + llvm::Constant *FTRTTIConst = + CGM.GetAddrOfRTTIDescriptor(QualType(FnType, 0), /*ForEH=*/true); + llvm::Type *PrefixStructTyElems[] = { + PrefixSig->getType(), + FTRTTIConst->getType() + }; + llvm::StructType *PrefixStructTy = llvm::StructType::get( + CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true); + + llvm::Value *CalleePrefixStruct = Builder.CreateBitCast( + Callee, llvm::PointerType::getUnqual(PrefixStructTy)); + llvm::Value *CalleeSigPtr = + Builder.CreateConstGEP2_32(CalleePrefixStruct, 0, 0); + llvm::Value *CalleeSig = Builder.CreateLoad(CalleeSigPtr); + llvm::Value *CalleeSigMatch = Builder.CreateICmpEQ(CalleeSig, PrefixSig); + + llvm::BasicBlock *Cont = createBasicBlock("cont"); + llvm::BasicBlock *TypeCheck = createBasicBlock("typecheck"); + Builder.CreateCondBr(CalleeSigMatch, TypeCheck, Cont); + + EmitBlock(TypeCheck); + llvm::Value *CalleeRTTIPtr = + Builder.CreateConstGEP2_32(CalleePrefixStruct, 0, 1); + llvm::Value *CalleeRTTI = Builder.CreateLoad(CalleeRTTIPtr); + llvm::Value *CalleeRTTIMatch = + Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst); + llvm::Constant *StaticData[] = { + EmitCheckSourceLocation(CallLoc), + EmitCheckTypeDescriptor(CalleeType) + }; + EmitCheck(CalleeRTTIMatch, + "function_type_mismatch", + StaticData, + Callee, + CRK_Recoverable); + + Builder.CreateBr(Cont); + EmitBlock(Cont); + } + } + CallArgList Args; EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), ArgBeg, ArgEnd, ForceColumnInfo); diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 2844fe2091b..567444253c9 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -86,7 +86,8 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, // The method is static, emit it as we would a regular call. llvm::Value *Callee = CGM.GetAddrOfFunction(MD); return EmitCall(getContext().getPointerType(MD->getType()), Callee, - ReturnValue, CE->arg_begin(), CE->arg_end()); + CE->getLocStart(), ReturnValue, CE->arg_begin(), + CE->arg_end()); } // Compute the object pointer. diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 4ae0bdd97ce..03a24eb5f78 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -16,6 +16,7 @@ #include "CGCXXABI.h" #include "CGDebugInfo.h" #include "CodeGenModule.h" +#include "TargetInfo.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" @@ -519,6 +520,22 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, EmitOpenCLKernelMetadata(FD, Fn); } + // If we are checking function types, emit a function type signature as + // prefix data. + if (getLangOpts().CPlusPlus && SanOpts->Function) { + if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) { + if (llvm::Constant *PrefixSig = + CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) { + llvm::Constant *FTRTTIConst = + CGM.GetAddrOfRTTIDescriptor(FD->getType(), /*ForEH=*/true); + llvm::Constant *PrefixStructElems[] = { PrefixSig, FTRTTIConst }; + llvm::Constant *PrefixStructConst = + llvm::ConstantStruct::getAnon(PrefixStructElems, /*Packed=*/true); + Fn->setPrefixData(PrefixStructConst); + } + } + } + llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn); // Create a marker to make it easy to insert allocas into the entryblock diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 19c64b71a46..b07e903b49f 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2073,6 +2073,7 @@ public: llvm::Instruction **callOrInvoke = 0); RValue EmitCall(QualType FnType, llvm::Value *Callee, + SourceLocation CallLoc, ReturnValueSlot ReturnValue, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd, diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index ae44396895d..0092c46151c 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -601,6 +601,14 @@ public: return X86AdjustInlineAsmType(CGF, Constraint, Ty); } + llvm::Constant *getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const { + unsigned Sig = (0xeb << 0) | // jmp rel8 + (0x06 << 8) | // .+0x08 + ('F' << 16) | + ('T' << 24); + return llvm::ConstantInt::get(CGM.Int32Ty, Sig); + } + }; } @@ -1284,6 +1292,14 @@ public: return TargetCodeGenInfo::isNoProtoCallVariadic(args, fnType); } + llvm::Constant *getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const { + unsigned Sig = (0xeb << 0) | // jmp rel8 + (0x0a << 8) | // .+0x0c + ('F' << 16) | + ('T' << 24); + return llvm::ConstantInt::get(CGM.Int32Ty, Sig); + } + }; static std::string qualifyWindowsLibrary(llvm::StringRef Lib) { diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index a7fb88649a3..f631f3102d0 100644 --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -21,6 +21,7 @@ #include "llvm/ADT/SmallString.h" namespace llvm { + class Constant; class GlobalValue; class Type; class Value; @@ -136,6 +137,13 @@ namespace clang { return ""; } + /// Return a constant used by UBSan as a signature to identify functions + /// possessing type information, or 0 if the platform is unsupported. + virtual llvm::Constant *getUBSanFunctionSignature( + CodeGen::CodeGenModule &CGM) const { + return 0; + } + /// Determine whether a call to an unprototyped functions under /// the given calling convention should use the variadic /// convention or the non-variadic convention. |