vsk updated this revision to Diff 116453. vsk added a comment. - Remove some noisy changes.
https://reviews.llvm.org/D38210 Files: docs/UndefinedBehaviorSanitizer.rst lib/CodeGen/CGExpr.cpp lib/CodeGen/CodeGenFunction.cpp lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CodeGen/sanitize-function-calls.c
Index: test/CodeGen/sanitize-function-calls.c =================================================================== --- /dev/null +++ test/CodeGen/sanitize-function-calls.c @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -w -triple i386-linux-gnu -fsanitize=function -emit-llvm -o - %s | FileCheck %s --check-prefixes=X32 +// RUN: %clang_cc1 -w -triple x86_64-linux-gnu -fsanitize=function -emit-llvm -o - %s | FileCheck %s --check-prefixes=X64 + +struct S {}; + +// X32: [[no_proto_ti:@.*]] = private constant i8* inttoptr (i32 4 to i8*) +// X64: [[no_proto_ti:@.*]] = private constant i8* inttoptr (i64 4 to i8*) + +// X32: prologue <{ i32, i32 }> <{ i32 846595819, i32 sub (i32 ptrtoint (i8** [[no_proto_ti]] to i32), i32 ptrtoint (void ()* @no_proto to i32)) }> +// X64: prologue <{ i32, i32 }> <{ i32 846595819, i32 trunc (i64 sub (i64 ptrtoint (i8** [[no_proto_ti]] to i64), i64 ptrtoint (void ()* @no_proto to i64)) to i32) }> +void no_proto() {} + +void proto(void) {} + +typedef struct S (*vfunc0)(void); +typedef void (*vfunc1)(void); +typedef char (*vfunc2)(void); +typedef short (*vfunc3)(void); +typedef int (*vfunc4)(void); +typedef long long (*vfunc5)(void); +typedef float (*vfunc6)(void); +typedef double (*vfunc7)(void); +typedef void (*vfunc8)(int, int, int, int, int, int, int, int, int, int, int); + +// X64-LABEL: @call_proto +void call_proto(void) { + // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, null, !nosanitize + // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize + vfunc0 f0 = &proto; + f0(); + + // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 4 to i8*), !nosanitize + // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize + vfunc1 f1 = &proto; + f1(); + + // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 16 to i8*), !nosanitize + // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize + vfunc2 f2 = &proto; + f2(); + + // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 20 to i8*), !nosanitize + // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize + vfunc3 f3 = &proto; + f3(); + + // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 24 to i8*), !nosanitize + // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize + vfunc4 f4 = &proto; + f4(); + + // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 28 to i8*), !nosanitize + // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize + vfunc5 f5 = &proto; + f5(); + + // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 8 to i8*), !nosanitize + // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize + vfunc6 f6 = &proto; + f6(); + + // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 12 to i8*), !nosanitize + // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize + vfunc7 f7 = &proto; + f7(); + + // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, inttoptr (i64 3681400516 to i8*), !nosanitize + // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize + vfunc8 f8 = &proto; + f8(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); +} + +// X64-LABEL: @call_no_proto +void call_no_proto(void) { + // X64: [[ICMP:%.*]] = icmp eq i8* {{.*}}, null, !nosanitize + // X64-NEXT: br i1 [[ICMP]], {{.*}} !nosanitize + vfunc0 f0 = &no_proto; + f0(); +} + +// X64-LABEL: @main +int main() { + call_proto(); + call_no_proto(); + return 0; +} Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -745,6 +745,9 @@ /// Get the address of the RTTI descriptor for the given type. llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH = false); + /// Get the type descriptor for a function for use with UBSan. + llvm::Constant *GetUBSanFunctionTypeDescriptor(QualType Ty); + /// Get the address of a uuid descriptor . ConstantAddress GetAddrOfUuidDescriptor(const CXXUuidofExpr* E); Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -4495,6 +4495,62 @@ return getCXXABI().getAddrOfRTTIDescriptor(Ty); } +llvm::Constant *CodeGenModule::GetUBSanFunctionTypeDescriptor(QualType Ty) { + if (getLangOpts().CPlusPlus) + return GetAddrOfRTTIDescriptor(Ty, /*ForEH=*/true); + + // Bits: + // 0 : unused + // 1 : unused + // 2-4 : encode(returnType) + // 5-6 : encode(param1) + // ... : encode(paramK) + // 30-32: encode(param9) + + auto encode = [this](QualType EncodeTy) { + // Encode one of: ?, void, f32, f64, i8, i16, i32, i64 (in 3 bits) + const auto *T = EncodeTy.getTypePtr(); + if (T->isVoidType()) + return 1; + + uint64_t Size = getContext().getTypeSize(EncodeTy); + if (T->hasFloatingRepresentation()) { + switch (Size) { + case 32: + return 2; + case 64: + return 3; + default: + return 0; + } + } + + switch (Size) { + case 8: + return 4; + case 16: + return 5; + case 32: + return 6; + case 64: + return 7; + default: + return 0; + } + }; + + const auto *FuncTy = Ty->getAs<FunctionType>(); + unsigned Encoding = encode(FuncTy->getReturnType()) << 2; + if (auto *ProtoTy = dyn_cast<FunctionProtoType>(FuncTy)) { + auto Types = ProtoTy->getParamTypes(); + for (unsigned I = 0, E = Types.size(); I < E && I < 9; ++I) + Encoding |= encode(Types[I]) << (5 + (3 * I)); + } + + return llvm::ConstantExpr::getIntToPtr( + llvm::ConstantInt::get(IntPtrTy, Encoding), Int8PtrTy); +} + void CodeGenModule::EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D) { for (auto RefExpr : D->varlists()) { auto *VD = cast<VarDecl>(cast<DeclRefExpr>(RefExpr)->getDecl()); Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -887,12 +887,12 @@ // If we are checking function types, emit a function type signature as // prologue data. - if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function)) { + if (SanOpts.has(SanitizerKind::Function)) { if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) { if (llvm::Constant *PrologueSig = CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) { llvm::Constant *FTRTTIConst = - CGM.GetAddrOfRTTIDescriptor(FD->getType(), /*ForEH=*/true); + CGM.GetUBSanFunctionTypeDescriptor(FD->getType()); llvm::Constant *FTRTTIConstEncoded = EncodeAddrForUseInPrologue(Fn, FTRTTIConst); llvm::Constant *PrologueStructElems[] = {PrologueSig, Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -4402,13 +4402,13 @@ CGCallee Callee = OrigCallee; - if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function) && + if (SanOpts.has(SanitizerKind::Function) && (!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); + CGM.GetUBSanFunctionTypeDescriptor(QualType(FnType, 0)); llvm::Type *PrefixStructTyElems[] = {PrefixSig->getType(), Int32Ty}; llvm::StructType *PrefixStructTy = llvm::StructType::get( CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true); @@ -4436,10 +4436,8 @@ DecodeAddrUsedInPrologue(CalleePtr, CalleeRTTIEncoded); llvm::Value *CalleeRTTIMatch = Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst); - llvm::Constant *StaticData[] = { - EmitCheckSourceLocation(E->getLocStart()), - EmitCheckTypeDescriptor(CalleeType) - }; + llvm::Constant *StaticData[] = {EmitCheckSourceLocation(E->getLocStart()), + EmitCheckTypeDescriptor(CalleeType)}; EmitCheck(std::make_pair(CalleeRTTIMatch, SanitizerKind::Function), SanitizerHandler::FunctionTypeMismatch, StaticData, CalleePtr); Index: docs/UndefinedBehaviorSanitizer.rst =================================================================== --- docs/UndefinedBehaviorSanitizer.rst +++ docs/UndefinedBehaviorSanitizer.rst @@ -87,7 +87,7 @@ - ``-fsanitize=float-divide-by-zero``: Floating point division by zero. - ``-fsanitize=function``: Indirect call of a function through a - function pointer of the wrong type (Darwin/Linux, C++ and x86/x86_64 + function pointer of the wrong type (Darwin/Linux and x86/x86_64 only). - ``-fsanitize=integer-divide-by-zero``: Integer division by zero. - ``-fsanitize=nonnull-attribute``: Passing null pointer as a function
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits