Skip to content

Commit 2498a9d

Browse files
committed
CFI: Restore typeid_for_instance default behavior
Restore typeid_for_instance default behavior of performing self type erasure, since it's the most common case and what it does most of the time. Using concrete self (or not performing self type erasure) is for assigning a secondary type id, and secondary type ids are only assigned when they're unique and to methods, and also are only tested for when methods are used as function pointers.
1 parent 9cbaa01 commit 2498a9d

File tree

4 files changed

+29
-13
lines changed

4 files changed

+29
-13
lines changed

compiler/rustc_codegen_llvm/src/declare.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
147147
for options in [
148148
TypeIdOptions::GENERALIZE_POINTERS,
149149
TypeIdOptions::NORMALIZE_INTEGERS,
150-
TypeIdOptions::ERASE_SELF_TYPE,
150+
TypeIdOptions::USE_CONCRETE_SELF,
151151
]
152152
.into_iter()
153153
.powerset()
@@ -173,9 +173,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
173173

174174
if self.tcx.sess.is_sanitizer_kcfi_enabled() {
175175
// LLVM KCFI does not support multiple !kcfi_type attachments
176-
// Default to erasing the self type. If we need the concrete type, there will be a
177-
// hint in the instance.
178-
let mut options = TypeIdOptions::ERASE_SELF_TYPE;
176+
let mut options = TypeIdOptions::empty();
179177
if self.tcx.sess.is_sanitizer_cfi_generalize_pointers_enabled() {
180178
options.insert(TypeIdOptions::GENERALIZE_POINTERS);
181179
}

compiler/rustc_symbol_mangling/src/typeid.rs

+24-6
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,14 @@ bitflags! {
2424
/// `-fsanitize-cfi-icall-experimental-normalize-integers` option for cross-language LLVM
2525
/// CFI and KCFI support.
2626
const NORMALIZE_INTEGERS = 4;
27-
/// Generalize the instance by erasing the concrete `Self` type where possible.
28-
/// Only has an effect on `{kcfi_,}typeid_for_instance`.
29-
const ERASE_SELF_TYPE = 8;
27+
/// Do not perform self type erasure for attaching a secondary type id to methods with their
28+
/// concrete self so they can be used as function pointers.
29+
///
30+
/// (This applies to typeid_for_instance only and should be used to attach a secondary type
31+
/// id to methods during their declaration/definition so they match the type ids returned by
32+
/// either typeid_for_instance or typeid_for_fnabi at call sites during code generation for
33+
/// type membership tests when methods are used as function pointers.)
34+
const USE_CONCRETE_SELF = 8;
3035
}
3136
}
3237

@@ -69,10 +74,23 @@ pub fn kcfi_typeid_for_instance<'tcx>(
6974
instance: Instance<'tcx>,
7075
mut options: TypeIdOptions,
7176
) -> u32 {
72-
// If we receive a `ReifyShim` intended to produce a function pointer, we need to remain
73-
// concrete - abstraction is for vtables.
77+
// KCFI support for Rust shares most of its implementation with the CFI support, with some key
78+
// differences:
79+
//
80+
// 1. KCFI performs type tests differently and are implemented as different LLVM passes than CFI
81+
// to not require LTO.
82+
// 2. KCFI has the limitation that a function or method may have one type id assigned only.
83+
//
84+
// Because of the limitation listed above (2), the current KCFI implementation (not CFI) does
85+
// reifying of types (i.e., adds shims/trampolines for indirect calls in these cases) for:
86+
//
87+
// * Supporting casting between function items, closures, and Fn trait objects.
88+
// * Supporting methods being cast as function pointers.
89+
//
90+
// This was implemented for KCFI support in #123106 and #123052 (which introduced the
91+
// ReifyReason). The tracking issue for KCFI support for Rust is #123479.
7492
if matches!(instance.def, InstanceDef::ReifyShim(_, Some(ReifyReason::FnPtr))) {
75-
options.remove(TypeIdOptions::ERASE_SELF_TYPE);
93+
options.insert(TypeIdOptions::USE_CONCRETE_SELF);
7694
}
7795
// A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the
7896
// xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)

compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,7 @@ pub fn typeid_for_instance<'tcx>(
10981098
instance.args = tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1));
10991099
}
11001100

1101-
if options.contains(EncodeTyOptions::ERASE_SELF_TYPE) {
1101+
if !options.contains(EncodeTyOptions::USE_CONCRETE_SELF) {
11021102
if let Some(impl_id) = tcx.impl_of_method(instance.def_id())
11031103
&& let Some(trait_ref) = tcx.impl_trait_ref(impl_id)
11041104
{

tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-method-secondary-typeid.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ impl Trait1 for Type1 {
1818
}
1919

2020

21-
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}5Type1EE"}
22-
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}6Trait1u6regionEEE"}
21+
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}6Trait1u6regionEEE"}
22+
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}5Type1EE"}

0 commit comments

Comments
 (0)