summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp2
-rw-r--r--clang/lib/CodeGen/CGCUDARuntime.cpp4
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp50
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp3
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp17
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h1
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp16
-rw-r--r--clang/lib/CodeGen/TargetInfo.h8
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.
OpenPOWER on IntegriCloud