diff --git a/clang/docs/UndefinedBehaviorSanitizer.rst b/clang/docs/UndefinedBehaviorSanitizer.rst --- a/clang/docs/UndefinedBehaviorSanitizer.rst +++ b/clang/docs/UndefinedBehaviorSanitizer.rst @@ -222,8 +222,8 @@ There is a minimal UBSan runtime available suitable for use in production environments. This runtime has a small attack surface. It only provides very -basic issue logging and deduplication, and does not support -``-fsanitize=function`` and ``-fsanitize=vptr`` checking. +basic issue logging and deduplication, and does not support ``-fsanitize=vptr`` +checking. To use the minimal runtime, add ``-fsanitize-minimal-runtime`` to the clang command line options. For example, if you're used to compiling with diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -40,6 +40,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" +#include "llvm/Support/xxhash.h" #include "llvm/Transforms/Utils/SanitizerStats.h" #include @@ -3222,7 +3223,7 @@ static CheckRecoverableKind getRecoverableKind(SanitizerMask Kind) { assert(Kind.countPopulation() == 1); - if (Kind == SanitizerKind::Function || Kind == SanitizerKind::Vptr) + if (Kind == SanitizerKind::Vptr) return CheckRecoverableKind::AlwaysRecoverable; else if (Kind == SanitizerKind::Return || Kind == SanitizerKind::Unreachable) return CheckRecoverableKind::Unrecoverable; @@ -5353,12 +5354,8 @@ if (llvm::Constant *PrefixSig = CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) { SanitizerScope SanScope(this); - // Remove any (C++17) exception specifications, to allow calling e.g. a - // noexcept function through a non-noexcept pointer. - auto ProtoTy = - getContext().getFunctionTypeWithExceptionSpec(PointeeType, EST_None); - llvm::Constant *FTRTTIConst = - CGM.GetAddrOfRTTIDescriptor(ProtoTy, /*ForEH=*/true); + auto *TypeHash = getUBSanFunctionTypeHash(PointeeType); + llvm::Type *PrefixSigType = PrefixSig->getType(); llvm::StructType *PrefixStructTy = llvm::StructType::get( CGM.getLLVMContext(), {PrefixSigType, Int32Ty}, /*isPacked=*/true); @@ -5378,19 +5375,17 @@ Builder.CreateCondBr(CalleeSigMatch, TypeCheck, Cont); EmitBlock(TypeCheck); - llvm::Value *CalleeRTTIPtr = - Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, -1, 1); - llvm::Value *CalleeRTTIEncoded = - Builder.CreateAlignedLoad(Int32Ty, CalleeRTTIPtr, getPointerAlign()); - llvm::Value *CalleeRTTI = - DecodeAddrUsedInPrologue(CalleePtr, CalleeRTTIEncoded); - llvm::Value *CalleeRTTIMatch = - Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst); + llvm::Value *CalleeTypeHash = Builder.CreateAlignedLoad( + Int32Ty, + Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, -1, 1), + getPointerAlign()); + llvm::Value *CalleeTypeHashMatch = + Builder.CreateICmpEQ(CalleeTypeHash, TypeHash); llvm::Constant *StaticData[] = {EmitCheckSourceLocation(E->getBeginLoc()), EmitCheckTypeDescriptor(CalleeType)}; - EmitCheck(std::make_pair(CalleeRTTIMatch, SanitizerKind::Function), + EmitCheck(std::make_pair(CalleeTypeHashMatch, SanitizerKind::Function), SanitizerHandler::FunctionTypeMismatch, StaticData, - {CalleePtr, CalleeRTTI, FTRTTIConst}); + {CalleePtr}); Builder.CreateBr(Cont); EmitBlock(Cont); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -117,7 +117,7 @@ SANITIZER_CHECK(DivremOverflow, divrem_overflow, 0) \ SANITIZER_CHECK(DynamicTypeCacheMiss, dynamic_type_cache_miss, 0) \ SANITIZER_CHECK(FloatCastOverflow, float_cast_overflow, 0) \ - SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 1) \ + SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 0) \ SANITIZER_CHECK(ImplicitConversion, implicit_conversion, 0) \ SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0) \ SANITIZER_CHECK(InvalidObjCCast, invalid_objc_cast, 0) \ @@ -2368,10 +2368,9 @@ /// XRay typed event handling calls. bool AlwaysEmitXRayTypedEvents() const; - /// Decode an address used in a function prologue, encoded by \c - /// EncodeAddrForUseInPrologue. - llvm::Value *DecodeAddrUsedInPrologue(llvm::Value *F, - llvm::Value *EncodedAddr); + /// Return a type hash constant for a function instrumented by + /// -fsanitize=function. + llvm::ConstantInt *getUBSanFunctionTypeHash(QualType T) const; /// EmitFunctionProlog - Emit the target specific LLVM code to load the /// arguments for the given function. This is also responsible for naming the diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -44,6 +44,7 @@ #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Operator.h" #include "llvm/Support/CRC.h" +#include "llvm/Support/xxhash.h" #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" #include "llvm/Transforms/Utils/PromoteMemToReg.h" #include @@ -567,18 +568,16 @@ XRayInstrKind::Typed); } -llvm::Value * -CodeGenFunction::DecodeAddrUsedInPrologue(llvm::Value *F, - llvm::Value *EncodedAddr) { - // Reconstruct the address of the global. - auto *PCRelAsInt = Builder.CreateSExt(EncodedAddr, IntPtrTy); - auto *FuncAsInt = Builder.CreatePtrToInt(F, IntPtrTy, "func_addr.int"); - auto *GOTAsInt = Builder.CreateAdd(PCRelAsInt, FuncAsInt, "global_addr.int"); - auto *GOTAddr = Builder.CreateIntToPtr(GOTAsInt, Int8PtrPtrTy, "global_addr"); - - // Load the original pointer through the global. - return Builder.CreateLoad(Address(GOTAddr, Int8PtrTy, getPointerAlign()), - "decoded_addr"); +llvm::ConstantInt * +CodeGenFunction::getUBSanFunctionTypeHash(QualType Ty) const { + // Remove any (C++17) exception specifications, to allow calling e.g. a + // noexcept function through a non-noexcept pointer. + auto ProtoTy = getContext().getFunctionTypeWithExceptionSpec(Ty, EST_None); + std::string Mangled; + llvm::raw_string_ostream Out(Mangled); + CGM.getCXXABI().getMangleContext().mangleTypeName(ProtoTy, Out, false); + return llvm::ConstantInt::get(CGM.Int32Ty, + static_cast(llvm::xxHash64(Mangled))); } void CodeGenFunction::EmitKernelMetadata(const FunctionDecl *FD, @@ -948,19 +947,12 @@ // prologue data. if (FD && getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function)) { if (llvm::Constant *PrologueSig = getPrologueSignature(CGM, FD)) { - // Remove any (C++17) exception specifications, to allow calling e.g. a - // noexcept function through a non-noexcept pointer. - auto ProtoTy = getContext().getFunctionTypeWithExceptionSpec( - FD->getType(), EST_None); - llvm::Constant *FTRTTIConst = - CGM.GetAddrOfRTTIDescriptor(ProtoTy, /*ForEH=*/true); - llvm::GlobalVariable *FTRTTIProxy = - CGM.GetOrCreateRTTIProxyGlobalVariable(FTRTTIConst); llvm::LLVMContext &Ctx = Fn->getContext(); llvm::MDBuilder MDB(Ctx); - Fn->setMetadata(llvm::LLVMContext::MD_func_sanitize, - MDB.createRTTIPointerPrologue(PrologueSig, FTRTTIProxy)); - CGM.addCompilerUsedGlobal(FTRTTIProxy); + Fn->setMetadata( + llvm::LLVMContext::MD_func_sanitize, + MDB.createRTTIPointerPrologue( + PrologueSig, getUBSanFunctionTypeHash(FD->getType()))); } } diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -36,8 +36,7 @@ static const SanitizerMask NeedsUbsanCxxRt = SanitizerKind::Vptr | SanitizerKind::CFI; static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr; -static const SanitizerMask NotAllowedWithMinimalRuntime = - SanitizerKind::Function | SanitizerKind::Vptr; +static const SanitizerMask NotAllowedWithMinimalRuntime = SanitizerKind::Vptr; static const SanitizerMask RequiresPIE = SanitizerKind::DataFlow | SanitizerKind::Scudo; static const SanitizerMask NeedsUnwindTables = diff --git a/clang/test/CodeGen/ubsan-function.cpp b/clang/test/CodeGen/ubsan-function.cpp --- a/clang/test/CodeGen/ubsan-function.cpp +++ b/clang/test/CodeGen/ubsan-function.cpp @@ -2,7 +2,6 @@ // RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - %s -fsanitize=function -fno-sanitize-recover=all | FileCheck %s // RUN: %clang_cc1 -triple aarch64_be-linux-gnu -emit-llvm -o - %s -fsanitize=function -fno-sanitize-recover=all | FileCheck %s -// CHECK: @[[PROXY:.*]] = private unnamed_addr constant ptr @_ZTIFvvE // CHECK: define{{.*}} void @_Z3funv() #0 !func_sanitize ![[FUNCSAN:.*]] { void fun() {} @@ -14,14 +13,18 @@ // CHECK: [[LABEL1]]: // CHECK: getelementptr <{ i32, i32 }>, ptr {{.*}}, i32 -1, i32 1, !nosanitize // CHECK: load i32, ptr {{.*}}, align {{.*}}, !nosanitize -// CHECK: icmp eq ptr {{.*}}, @_ZTIFvvE, !nosanitize +// CHECK: icmp eq i32 {{.*}}, -1522505972, !nosanitize // CHECK: br i1 {{.*}}, label %[[LABEL3:.*]], label %[[LABEL2:[^,]*]], {{.*}}!nosanitize // CHECK: [[LABEL2]]: -// CHECK: call void @__ubsan_handle_function_type_mismatch_v1_abort(ptr {{.*}}, i64 {{.*}}, i64 {{.*}}, i64 {{.*}}) #{{.*}}, !nosanitize -// CHECK-NOT: unreachable -// CHECK: br label %[[LABEL3]], !nosanitize -// CHECK: [[LABEL3]]: +// CHECK: call void @__ubsan_handle_function_type_mismatch_abort(ptr @[[#]], i64 %[[#]]) #[[#]], !nosanitize +// CHECK-NEXT: unreachable, !nosanitize +// CHECK-EMPTY: +// CHECK-NEXT: [[LABEL3]]: // CHECK: br label %[[LABEL4]], !nosanitize +// CHECK-EMPTY: +// CHECK-NEXT: [[LABEL4]]: +// CHECK-NEXT: call void +// CHECK-NEXT: ret void void caller(void (*f)()) { f(); } -// CHECK: ![[FUNCSAN]] = !{i32 -1056584962, ptr @[[PROXY]]} +// CHECK: ![[FUNCSAN]] = !{i32 -1056584962, i32 -1522505972} diff --git a/clang/test/CodeGenCXX/catch-undef-behavior.cpp b/clang/test/CodeGenCXX/catch-undef-behavior.cpp --- a/clang/test/CodeGenCXX/catch-undef-behavior.cpp +++ b/clang/test/CodeGenCXX/catch-undef-behavior.cpp @@ -16,8 +16,6 @@ // Check that type mismatch handler is not modified by ASan. // CHECK-ASAN: private unnamed_addr global { { [{{.*}} x i8]*, i32, i32 }, { i16, i16, [4 x i8] }*, i8*, i8 } { {{.*}}, { i16, i16, [4 x i8] }* [[TYPE_DESCR]], {{.*}} } -// CHECK-FUNCSAN: [[PROXY:@.+]] = private unnamed_addr constant i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) - struct T : S {}; // CHECK-LABEL: @_Z17reference_binding @@ -408,15 +406,10 @@ // CHECK-NEXT: br i1 [[SIGCMP]] // RTTI pointer check - // CHECK: [[RTTIPTR:%.+]] = getelementptr <{ i32, i32 }>, <{ i32, i32 }>* [[PTR]], i32 -1, i32 1 - // CHECK-NEXT: [[RTTIEncIntTrunc:%.+]] = load i32, i32* [[RTTIPTR]] - // CHECK-NEXT: [[RTTIEncInt:%.+]] = sext i32 [[RTTIEncIntTrunc]] to i64 - // CHECK-NEXT: [[FuncAddrInt:%.+]] = ptrtoint void (i32)* {{.*}} to i64 - // CHECK-NEXT: [[IndirectGVInt:%.+]] = add i64 [[RTTIEncInt]], [[FuncAddrInt]] - // CHECK-NEXT: [[IndirectGV:%.+]] = inttoptr i64 [[IndirectGVInt]] to i8** - // CHECK-NEXT: [[RTTI:%.+]] = load i8*, i8** [[IndirectGV]], align 8 - // CHECK-NEXT: [[RTTICMP:%.+]] = icmp eq i8* [[RTTI]], bitcast ({ i8*, i8* }* @_ZTIFviE to i8*) - // CHECK-NEXT: br i1 [[RTTICMP]] + // CHECK: [[CalleeTypeHashPtr:%.+]] = getelementptr <{ i32, i32 }>, <{ i32, i32 }>* [[PTR]], i32 -1, i32 1 + // CHECK-NEXT: [[CalleeTypeHash:%.+]] = load i32, i32* [[CalleeTypeHashPtr]] + // CHECK-NEXT: [[HashCmp:%.+]] = icmp eq i32 [[CalleeTypeHash]], 27004076 + // CHECK-NEXT: br i1 [[HashCmp]] p(42); } @@ -750,4 +743,4 @@ // CHECK: attributes [[NR_NUW]] = { noreturn nounwind } -// CHECK-FUNCSAN: ![[FUNCSAN]] = !{i32 -1056584962, i8** [[PROXY]]} +// CHECK-FUNCSAN: ![[FUNCSAN]] = !{i32 -1056584962, i32 -1302768377} diff --git a/clang/test/CodeGenCXX/ubsan-function-noexcept.cpp b/clang/test/CodeGenCXX/ubsan-function-noexcept.cpp --- a/clang/test/CodeGenCXX/ubsan-function-noexcept.cpp +++ b/clang/test/CodeGenCXX/ubsan-function-noexcept.cpp @@ -1,17 +1,18 @@ // RUN: %clang_cc1 -std=c++17 -fsanitize=function -emit-llvm -triple x86_64-linux-gnu %s -o - | FileCheck %s -// Check that typeinfo recorded in function prolog doesn't have "Do" noexcept -// qualifier in its mangled name. -// CHECK: [[PROXY:@.*]] = private unnamed_addr constant ptr @_ZTIFvvE -// CHECK: define{{.*}} void @_Z1fv() #{{.*}} !func_sanitize ![[FUNCSAN:.*]] { -void f() noexcept {} +/// Check the following two functions have the same func_sanitize metadata, i.e. +/// they have the same type hash despite the exception specifier. +// CHECK: define{{.*}} void @_Z1fv() #[[#]] !func_sanitize ![[FUNCSAN:.*]] { +// CHECK: define{{.*}} void @_Z10f_noexceptv() #[[#]] !func_sanitize +// CHECK-SAME: ![[FUNCSAN]] { +void f() {} +void f_noexcept() noexcept {} // CHECK: define{{.*}} void @_Z1gPDoFvvE void g(void (*p)() noexcept) { - // Check that reference typeinfo at call site doesn't have "Do" noexcept - // qualifier in its mangled name, either. - // CHECK: icmp eq ptr %{{.*}}, @_ZTIFvvE, !nosanitize + // CHECK: icmp eq i32 %{{.*}}, -1056584962, !nosanitize + // CHECK: icmp eq i32 %{{.*}}, [[Hash:[-0-9]+]], !nosanitize p(); } -// CHECK: ![[FUNCSAN]] = !{i32 -1056584962, ptr [[PROXY]]} +// CHECK: ![[FUNCSAN]] = !{i32 -1056584962, i32 [[Hash]]} diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -841,7 +841,7 @@ // CHECK-TSAN-MINIMAL: error: invalid argument '-fsanitize-minimal-runtime' not allowed with '-fsanitize=thread' // RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-MINIMAL -// CHECK-UBSAN-MINIMAL: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){17}"}} +// CHECK-UBSAN-MINIMAL: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute|function),?){18}"}} // CHECK-UBSAN-MINIMAL: "-fsanitize-minimal-runtime" // RUN: %clang --target=x86_64-linux-gnu -fsanitize=integer -fsanitize-trap=integer %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-INTSAN-TRAP @@ -855,8 +855,7 @@ // CHECK-MEMTAG-MINIMAL: "-fsanitize=memtag-stack,memtag-heap,memtag-globals" // CHECK-MEMTAG-MINIMAL: "-fsanitize-minimal-runtime" -// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize=function -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-FUNCTION-MINIMAL -// CHECK-UBSAN-FUNCTION-MINIMAL: error: invalid argument '-fsanitize=function' not allowed with '-fsanitize-minimal-runtime' +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize=function -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck /dev/null --implicit-check-not=error: // RUN: %clang --target=x86_64-linux-gnu -fsanitize=undefined -fsanitize=vptr -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-VPTR-MINIMAL // CHECK-UBSAN-VPTR-MINIMAL: error: invalid argument '-fsanitize=vptr' not allowed with '-fsanitize-minimal-runtime' diff --git a/compiler-rt/lib/ubsan/ubsan_handlers.h b/compiler-rt/lib/ubsan/ubsan_handlers.h --- a/compiler-rt/lib/ubsan/ubsan_handlers.h +++ b/compiler-rt/lib/ubsan/ubsan_handlers.h @@ -231,6 +231,17 @@ CFICheckFailData *Data, ValueHandle Vtable, bool ValidVtable, ReportOptions Opts); +struct FunctionTypeMismatchData { + SourceLocation Loc; + const TypeDescriptor &Type; +}; + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void +__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data, + ValueHandle Val); +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void +__ubsan_handle_function_type_mismatch_abort(FunctionTypeMismatchData *Data, + ValueHandle Val); } #endif // UBSAN_HANDLERS_H diff --git a/compiler-rt/lib/ubsan/ubsan_handlers.cpp b/compiler-rt/lib/ubsan/ubsan_handlers.cpp --- a/compiler-rt/lib/ubsan/ubsan_handlers.cpp +++ b/compiler-rt/lib/ubsan/ubsan_handlers.cpp @@ -915,4 +915,39 @@ Die(); } +static bool handleFunctionTypeMismatch(FunctionTypeMismatchData *Data, + ValueHandle Function, + ReportOptions Opts) { + SourceLocation CallLoc = Data->Loc.acquire(); + ErrorType ET = ErrorType::FunctionTypeMismatch; + if (ignoreReport(CallLoc, Opts, ET)) + return true; + + ScopedReport R(Opts, CallLoc, ET); + + SymbolizedStackHolder FLoc(getSymbolizedLocation(Function)); + const char *FName = FLoc.get()->info.function; + if (!FName) + FName = "(unknown)"; + + Diag(CallLoc, DL_Error, ET, + "call to function %0 through pointer to incorrect function type %1") + << FName << Data->Type; + Diag(FLoc, DL_Note, ET, "%0 defined here") << FName; + return true; +} + +void __ubsan::__ubsan_handle_function_type_mismatch( + FunctionTypeMismatchData *Data, ValueHandle Function) { + GET_REPORT_OPTIONS(false); + handleFunctionTypeMismatch(Data, Function, Opts); +} + +void __ubsan::__ubsan_handle_function_type_mismatch_abort( + FunctionTypeMismatchData *Data, ValueHandle Function) { + GET_REPORT_OPTIONS(true); + if (handleFunctionTypeMismatch(Data, Function, Opts)) + Die(); +} + #endif // CAN_SANITIZE_UB diff --git a/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h --- a/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h +++ b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h @@ -33,22 +33,6 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __ubsan_handle_dynamic_type_cache_miss_abort( DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash); - -struct FunctionTypeMismatchData { - SourceLocation Loc; - const TypeDescriptor &Type; -}; - -extern "C" SANITIZER_INTERFACE_ATTRIBUTE void -__ubsan_handle_function_type_mismatch_v1(FunctionTypeMismatchData *Data, - ValueHandle Val, - ValueHandle calleeRTTI, - ValueHandle fnRTTI); -extern "C" SANITIZER_INTERFACE_ATTRIBUTE void -__ubsan_handle_function_type_mismatch_v1_abort(FunctionTypeMismatchData *Data, - ValueHandle Val, - ValueHandle calleeRTTI, - ValueHandle fnRTTI); } #endif // UBSAN_HANDLERS_CXX_H diff --git a/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cpp b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cpp --- a/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cpp +++ b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cpp @@ -156,50 +156,6 @@ Diag(Loc, DL_Note, ET, "check failed in %0, vtable located in %1") << SrcModule << DstModule; } - -static bool handleFunctionTypeMismatch(FunctionTypeMismatchData *Data, - ValueHandle Function, - ValueHandle calleeRTTI, - ValueHandle fnRTTI, ReportOptions Opts) { - if (checkTypeInfoEquality(reinterpret_cast(calleeRTTI), - reinterpret_cast(fnRTTI))) - return false; - - SourceLocation CallLoc = Data->Loc.acquire(); - ErrorType ET = ErrorType::FunctionTypeMismatch; - - if (ignoreReport(CallLoc, Opts, ET)) - return true; - - ScopedReport R(Opts, CallLoc, ET); - - SymbolizedStackHolder FLoc(getSymbolizedLocation(Function)); - const char *FName = FLoc.get()->info.function; - if (!FName) - FName = "(unknown)"; - - Diag(CallLoc, DL_Error, ET, - "call to function %0 through pointer to incorrect function type %1") - << FName << Data->Type; - Diag(FLoc, DL_Note, ET, "%0 defined here") << FName; - return true; -} - -void __ubsan_handle_function_type_mismatch_v1(FunctionTypeMismatchData *Data, - ValueHandle Function, - ValueHandle calleeRTTI, - ValueHandle fnRTTI) { - GET_REPORT_OPTIONS(false); - handleFunctionTypeMismatch(Data, Function, calleeRTTI, fnRTTI, Opts); -} - -void __ubsan_handle_function_type_mismatch_v1_abort( - FunctionTypeMismatchData *Data, ValueHandle Function, - ValueHandle calleeRTTI, ValueHandle fnRTTI) { - GET_REPORT_OPTIONS(true); - if (handleFunctionTypeMismatch(Data, Function, calleeRTTI, fnRTTI, Opts)) - Die(); -} } // namespace __ubsan #endif // CAN_SANITIZE_UB diff --git a/compiler-rt/lib/ubsan/ubsan_interface.inc b/compiler-rt/lib/ubsan/ubsan_interface.inc --- a/compiler-rt/lib/ubsan/ubsan_interface.inc +++ b/compiler-rt/lib/ubsan/ubsan_interface.inc @@ -21,8 +21,8 @@ INTERFACE_FUNCTION(__ubsan_handle_dynamic_type_cache_miss_abort) INTERFACE_FUNCTION(__ubsan_handle_float_cast_overflow) INTERFACE_FUNCTION(__ubsan_handle_float_cast_overflow_abort) -INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_v1) -INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_v1_abort) +INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch) +INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_abort) INTERFACE_FUNCTION(__ubsan_handle_implicit_conversion) INTERFACE_FUNCTION(__ubsan_handle_implicit_conversion_abort) INTERFACE_FUNCTION(__ubsan_handle_invalid_builtin) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -976,14 +976,9 @@ assert(MD->getNumOperands() == 2); auto *PrologueSig = mdconst::extract(MD->getOperand(0)); - auto *FTRTTIProxy = mdconst::extract(MD->getOperand(1)); + auto *TypeHash = mdconst::extract(MD->getOperand(1)); emitGlobalConstant(F.getParent()->getDataLayout(), PrologueSig); - - const MCExpr *Proxy = lowerConstant(FTRTTIProxy); - const MCExpr *FnExp = MCSymbolRefExpr::create(CurrentFnSym, OutContext); - const MCExpr *PCRel = MCBinaryExpr::createSub(Proxy, FnExp, OutContext); - // Use 32 bit since only small code model is supported. - OutStreamer->emitValue(PCRel, 4u); + emitGlobalConstant(F.getParent()->getDataLayout(), TypeHash); } if (isVerbose()) { diff --git a/llvm/test/CodeGen/AArch64/func-sanitizer.ll b/llvm/test/CodeGen/AArch64/func-sanitizer.ll --- a/llvm/test/CodeGen/AArch64/func-sanitizer.ll +++ b/llvm/test/CodeGen/AArch64/func-sanitizer.ll @@ -2,21 +2,13 @@ ; CHECK-LABEL: .type _Z3funv,@function ; CHECK-NEXT: .word 3238382334 // 0xc105cafe -; CHECK-NEXT: .word .L__llvm_rtti_proxy-_Z3funv +; CHECK-NEXT: .word 42 ; CHECK-NEXT: _Z3funv: ; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: ret -; CHECK: .section .rodata,"a",@progbits -; CHECK-LABEL: .L__llvm_rtti_proxy: -; CHECK-NEXT: .xword _ZTIFvvE -; CHECK-NEXT: .size .L__llvm_rtti_proxy, 8 - -@_ZTIFvvE = linkonce_odr constant i32 1 -@__llvm_rtti_proxy = private unnamed_addr constant ptr @_ZTIFvvE - define dso_local void @_Z3funv() nounwind !func_sanitize !0 { ret void } -!0 = !{i32 3238382334, ptr @__llvm_rtti_proxy} +!0 = !{i32 3238382334, i32 42} diff --git a/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll b/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll --- a/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll +++ b/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll @@ -1,8 +1,5 @@ ; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s -@_ZTIFvvE = linkonce_odr constant i32 2 -@__llvm_rtti_proxy = private unnamed_addr constant ptr @_ZTIFvvE - define void @f0() "patchable-function-entry"="0" "branch-target-enforcement"="true" { ; CHECK-LABEL: f0: ; CHECK-NEXT: .Lfunc_begin0: @@ -94,7 +91,7 @@ ; CHECK-NEXT: .Ltmp{{.*}}: ; CHECK-NEXT: nop ; CHECK-NEXT: .word 3238382334 // 0xc105cafe -; CHECK-NEXT: .word .L__llvm_rtti_proxy-sanitize_function +; CHECK-NEXT: .word 42 ; CHECK-NEXT: sanitize_function: ; CHECK-NEXT: .Lfunc_begin{{.*}}: ; CHECK-NEXT: .cfi_startproc @@ -106,4 +103,4 @@ ret void } -!0 = !{i32 3238382334, ptr @__llvm_rtti_proxy} +!0 = !{i32 3238382334, i32 42} diff --git a/llvm/test/CodeGen/X86/func-sanitizer.ll b/llvm/test/CodeGen/X86/func-sanitizer.ll --- a/llvm/test/CodeGen/X86/func-sanitizer.ll +++ b/llvm/test/CodeGen/X86/func-sanitizer.ll @@ -2,17 +2,14 @@ ; CHECK: .type _Z3funv,@function ; CHECK-NEXT: .long 3238382334 # 0xc105cafe -; CHECK-NEXT: .long .L__llvm_rtti_proxy-_Z3funv +; CHECK-NEXT: .long 42 ; CHECK-NEXT: _Z3funv: ; CHECK-NEXT: .cfi_startproc ; CHECK-NEXT: # %bb.0: ; CHECK-NEXT: retq -@i = linkonce_odr constant i32 1 -@__llvm_rtti_proxy = private unnamed_addr constant ptr @i - define dso_local void @_Z3funv() !func_sanitize !0 { ret void } -!0 = !{i32 3238382334, ptr @__llvm_rtti_proxy} +!0 = !{i32 3238382334, i32 42} diff --git a/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll b/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll --- a/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll +++ b/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll @@ -1,9 +1,6 @@ ; RUN: llc -mtriple=i686 %s -o - | FileCheck --check-prefixes=CHECK,32 %s ; RUN: llc -mtriple=x86_64 %s -o - | FileCheck --check-prefixes=CHECK,64 %s -@_ZTIFvvE = linkonce_odr constant i32 1 -@__llvm_rtti_proxy = private unnamed_addr constant ptr @_ZTIFvvE - ;; -fpatchable-function-entry=0 -fcf-protection=branch define void @f0() "patchable-function-entry"="0" { ; CHECK-LABEL: f0: @@ -91,7 +88,7 @@ ; CHECK-NEXT: .Ltmp{{.*}}: ; CHECK-NEXT: nop ; CHECK-NEXT: .long 3238382334 -; CHECK-NEXT: .long .L__llvm_rtti_proxy-sanitize_function +; CHECK-NEXT: .long 42 ; CHECK-NEXT: sanitize_function: ; CHECK-NEXT: .Lfunc_begin{{.*}}: ; CHECK-NEXT: .cfi_startproc @@ -107,4 +104,4 @@ !llvm.module.flags = !{!0} !0 = !{i32 8, !"cf-protection-branch", i32 1} -!1 = !{i32 3238382334, ptr @__llvm_rtti_proxy} +!1 = !{i32 3238382334, i32 42}