[compiler-rt] 46f3664 - -fsanitize=function: use type hashes instead of RTTI objects
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sat May 20 08:24:27 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 llvm-commits
mailing list