[clang] 46f3664 - -fsanitize=function: use type hashes instead of RTTI objects

Fangrui Song via cfe-commits cfe-commits at lists.llvm.org
Sat May 20 08:24:26 PDT 2023


Author: Fangrui Song
Date: 2023-05-20T08:24:20-07:00
New Revision: 46f366494f3ca8cc98daa6fb4f29c7c446c176b6

URL: https://github.com/llvm/llvm-project/commit/46f366494f3ca8cc98daa6fb4f29c7c446c176b6
DIFF: https://github.com/llvm/llvm-project/commit/46f366494f3ca8cc98daa6fb4f29c7c446c176b6.diff

LOG: -fsanitize=function: use type hashes instead of RTTI objects

Currently we use RTTI objects to check type compatibility. To support non-unique
RTTI objects, commit 5745eccef54ddd3caca278d1d292a88b2281528b added a
`checkTypeInfoEquality` string matching to the runtime.
The scheme is inefficient.

```
_Z1fv:
  .long   846595819                    # jmp
  .long   .L__llvm_rtti_proxy-_Z3funv
  ...

main:
  ...
  # Load the second word (pointer to the RTTI object) and dereference it.
  movslq  4(%rsi), %rax
  movq    (%rax,%rsi), %rdx
  # Is it the desired typeinfo object?
  leaq    _ZTIFvvE(%rip), %rax
  # If not, call __ubsan_handle_function_type_mismatch_v1, which may recover if checkTypeInfoEquality allows
  cmpq    %rax, %rdx
  jne     .LBB1_2
  ...

.section        .data.rel.ro,"aw", at progbits
  .p2align        3, 0x0
.L__llvm_rtti_proxy:
  .quad   _ZTIFvvE
```

Let's replace the indirect `_ZTI` pointer with a type hash similar to
`-fsanitize=kcfi`.

```
_Z1fv:
  .long   3238382334
  .long   2772461324  # type hash

main:
  ...
  # Load the second word (callee type hash) and check whether it is expected
  cmpl    $-1522505972, -4(%rax)
  # If not, fail: call __ubsan_handle_function_type_mismatch
  jne     .LBB2_2
```

The RTTI object derives its name from `clang::MangleContext::mangleCXXRTTI`,
which uses `mangleType`. `mangleTypeName` uses `mangleType` as well. So the
type compatibility change is high-fidelity.

Since we no longer need RTTI pointers in
`__ubsan::__ubsan_handle_function_type_mismatch_v1`, let's switch it back to
version 0, the original signature before
e215996a2932ed7c472f4e94dc4345b30fd0c373 (2019).
`__ubsan::__ubsan_handle_function_type_mismatch_abort` is not
recoverable, so we can revert some changes from
e215996a2932ed7c472f4e94dc4345b30fd0c373.

Reviewed By: samitolvanen

Differential Revision: https://reviews.llvm.org/D148785

Added: 
    

Modified: 
    clang/docs/UndefinedBehaviorSanitizer.rst
    clang/lib/CodeGen/CGExpr.cpp
    clang/lib/CodeGen/CodeGenFunction.cpp
    clang/lib/CodeGen/CodeGenFunction.h
    clang/lib/Driver/SanitizerArgs.cpp
    clang/test/CodeGen/ubsan-function.cpp
    clang/test/CodeGenCXX/catch-undef-behavior.cpp
    clang/test/CodeGenCXX/ubsan-function-noexcept.cpp
    clang/test/Driver/fsanitize.c
    compiler-rt/lib/ubsan/ubsan_handlers.cpp
    compiler-rt/lib/ubsan/ubsan_handlers.h
    compiler-rt/lib/ubsan/ubsan_handlers_cxx.cpp
    compiler-rt/lib/ubsan/ubsan_handlers_cxx.h
    compiler-rt/lib/ubsan/ubsan_interface.inc
    llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
    llvm/test/CodeGen/AArch64/func-sanitizer.ll
    llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll
    llvm/test/CodeGen/X86/func-sanitizer.ll
    llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll

Removed: 
    


################################################################################
diff  --git a/clang/docs/UndefinedBehaviorSanitizer.rst b/clang/docs/UndefinedBehaviorSanitizer.rst
index 189651d138a0e..ff02ce8ad892d 100644
--- a/clang/docs/UndefinedBehaviorSanitizer.rst
+++ b/clang/docs/UndefinedBehaviorSanitizer.rst
@@ -222,8 +222,8 @@ Minimal Runtime
 
 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
index 834c2fda5855b..a915849a9822d 100644
--- 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 <optional>
@@ -3222,7 +3223,7 @@ enum class CheckRecoverableKind {
 
 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 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
     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 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
       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.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 5c8b8821cd28d..e52c4831087f7 100644
--- 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 <optional>
@@ -567,18 +568,16 @@ bool CodeGenFunction::AlwaysEmitXRayTypedEvents() const {
               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<uint32_t>(llvm::xxHash64(Mangled)));
 }
 
 void CodeGenFunction::EmitKernelMetadata(const FunctionDecl *FD,
@@ -948,19 +947,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
   // 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/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index dfd8b9e6e00a7..e9ad5e7551e3e 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -117,7 +117,7 @@ enum TypeEvaluationKind {
   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 @@ class CodeGenFunction : public CodeGenTypeCache {
   /// 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/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 8fe8ef2265c99..bbd416ab751bd 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -36,8 +36,7 @@ static const SanitizerMask NeedsUbsanRt =
 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
index 694176778e7eb..fc9f60f5b2056 100644
--- 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 @@ void fun() {}
 // 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
index 9fec5ed20a3d0..9e4f0fb402c28 100644
--- a/clang/test/CodeGenCXX/catch-undef-behavior.cpp
+++ b/clang/test/CodeGenCXX/catch-undef-behavior.cpp
@@ -16,8 +16,6 @@ struct S {
 // Check that type mismatch handler is not modified by ASan.
 // CHECK-ASAN: private unnamed_addr global { { ptr, i32, i32 }, ptr, ptr, i8 } { {{.*}}, ptr [[TYPE_DESCR]], {{.*}} }
 
-// CHECK-FUNCSAN: [[PROXY:@.+]] = private unnamed_addr constant ptr @_ZTIFvPFviEE
-
 struct T : S {};
 
 // CHECK-LABEL: @_Z17reference_binding
@@ -404,16 +402,11 @@ void indirect_function_call(void (*p)(int)) {
   // CHECK-NEXT: [[SIGCMP:%.+]] = icmp eq i32 [[SIG]], -1056584962
   // CHECK-NEXT: br i1 [[SIGCMP]]
 
-  // RTTI pointer check
-  // CHECK: [[RTTIPTR:%.+]] = getelementptr <{ i32, i32 }>, ptr [[PTR]], i32 -1, i32 1
-  // CHECK-NEXT: [[RTTIEncIntTrunc:%.+]] = load i32, ptr [[RTTIPTR]]
-  // CHECK-NEXT: [[RTTIEncInt:%.+]] = sext i32 [[RTTIEncIntTrunc]] to i64
-  // CHECK-NEXT: [[FuncAddrInt:%.+]] = ptrtoint ptr {{.*}} to i64
-  // CHECK-NEXT: [[IndirectGVInt:%.+]] = add i64 [[RTTIEncInt]], [[FuncAddrInt]]
-  // CHECK-NEXT: [[IndirectGV:%.+]] = inttoptr i64 [[IndirectGVInt]] to ptr
-  // CHECK-NEXT: [[RTTI:%.+]] = load ptr, ptr [[IndirectGV]], align 8
-  // CHECK-NEXT: [[RTTICMP:%.+]] = icmp eq ptr [[RTTI]], @_ZTIFviE
-  // CHECK-NEXT: br i1 [[RTTICMP]]
+  // CalleeTypeHash check
+  // CHECK: [[CalleeTypeHashPtr:%.+]] = getelementptr <{ i32, i32 }>, ptr [[PTR]], i32 -1, i32 1
+  // CHECK-NEXT: [[CalleeTypeHash:%.+]] = load i32, ptr [[CalleeTypeHashPtr]]
+  // CHECK-NEXT: [[CalleeTypeHashMatch:%.+]] = icmp eq i32 [[CalleeTypeHash]], 27004076
+  // CHECK-NEXT: br i1 [[CalleeTypeHashMatch]]
 
   p(42);
 }
@@ -747,4 +740,4 @@ void ThisAlign::this_align_lambda_2() {
 
 // CHECK: attributes [[NR_NUW]] = { noreturn nounwind }
 
-// CHECK-FUNCSAN: ![[FUNCSAN]] = !{i32 -1056584962, ptr [[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
index 10ca603a64c1a..454e373045c0b 100644
--- 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
index 9c385c63ffd4f..a76293fd3b711 100644
--- 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.cpp b/compiler-rt/lib/ubsan/ubsan_handlers.cpp
index 410292a0d5387..0f16507d5d88f 100644
--- a/compiler-rt/lib/ubsan/ubsan_handlers.cpp
+++ b/compiler-rt/lib/ubsan/ubsan_handlers.cpp
@@ -915,4 +915,39 @@ void __ubsan::__ubsan_handle_cfi_check_fail_abort(CFICheckFailData *Data,
   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.h b/compiler-rt/lib/ubsan/ubsan_handlers.h
index 219fb15de55fe..3bd5046de3d7d 100644
--- a/compiler-rt/lib/ubsan/ubsan_handlers.h
+++ b/compiler-rt/lib/ubsan/ubsan_handlers.h
@@ -231,6 +231,17 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __ubsan_handle_cfi_bad_type(
     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_cxx.cpp b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cpp
index 0317a3d1428c8..206a0bb485a9c 100644
--- a/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cpp
+++ b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cpp
@@ -156,50 +156,6 @@ void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
     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<void *>(calleeRTTI),
-                            reinterpret_cast<void *>(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_handlers_cxx.h b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h
index fd534c2573f6d..71695cbdc090f 100644
--- a/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h
+++ b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h
@@ -33,22 +33,6 @@ void __ubsan_handle_dynamic_type_cache_miss(
 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_interface.inc b/compiler-rt/lib/ubsan/ubsan_interface.inc
index 94337d85017b4..cb27feb5d7e99 100644
--- 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)
 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
index 5b05b1a069ef3..ea6f86475c763 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -976,14 +976,9 @@ void AsmPrinter::emitFunctionHeader() {
     assert(MD->getNumOperands() == 2);
 
     auto *PrologueSig = mdconst::extract<Constant>(MD->getOperand(0));
-    auto *FTRTTIProxy = mdconst::extract<Constant>(MD->getOperand(1));
+    auto *TypeHash = mdconst::extract<Constant>(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
index fa044efafe54a..89f23e7ed80e8 100644
--- a/llvm/test/CodeGen/AArch64/func-sanitizer.ll
+++ b/llvm/test/CodeGen/AArch64/func-sanitizer.ll
@@ -2,21 +2,13 @@
 
 ; CHECK-LABEL: .type _Z3funv, at 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", at progbits
-; CHECK-LABEL: .L__llvm_rtti_proxy:
-; CHECK-NEXT:    .xword  _ZTIFvvE
-; CHECK-NEXT:    .size   .L__llvm_rtti_proxy, 8
-
- at _ZTIFvvE = linkonce_odr constant i32 1
- at __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
index b749d072104d4..0dfb5764f55b8 100644
--- 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
 
- at _ZTIFvvE = linkonce_odr constant i32 2
- at __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 @@ sw.bb4:
 ; 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 @@ define void @sanitize_function(ptr noundef %x) "patchable-function-prefix"="1" "
   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
index 859987fe47d31..b421cb53ddfec 100644
--- a/llvm/test/CodeGen/X86/func-sanitizer.ll
+++ b/llvm/test/CodeGen/X86/func-sanitizer.ll
@@ -2,17 +2,14 @@
 
 ; CHECK:      .type _Z3funv, at 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
 
- at i = linkonce_odr constant i32 1
- at __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
index eaadeef4803a1..d0a9bee7878c3 100644
--- 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
 
- at _ZTIFvvE = linkonce_odr constant i32 1
- at __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 @@ entry:
 ; 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 @@ define void @sanitize_function(ptr noundef %x) "patchable-function-prefix"="1" "
 !llvm.module.flags = !{!0}
 
 !0 = !{i32 8, !"cf-protection-branch", i32 1}
-!1 = !{i32 3238382334, ptr @__llvm_rtti_proxy}
+!1 = !{i32 3238382334, i32 42}


        


More information about the cfe-commits mailing list