Skip to content

Commit a2cb4bd

Browse files
committed
Revert "CFI: Fix SIGILL reached via trait objects"
We no longer need the special instance resolution this added, and it can be broken in edge cases (specifically with a FnPtr shim, which will cause the calculation of fn_abi to fail). * We keep the Clone impls it added, because they have since become used by other portions of the compiler. * Add a test for the address-taken calls that this previously broke. This reverts commit 7c7b22e.
1 parent 671e47b commit a2cb4bd

File tree

8 files changed

+54
-132
lines changed

8 files changed

+54
-132
lines changed

compiler/rustc_codegen_llvm/src/callee.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,13 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
6767
true,
6868
),
6969
fn_abi,
70-
Some(instance),
7170
);
7271
unsafe {
7372
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
7473
}
7574
llfn
7675
} else {
77-
cx.declare_fn(sym, fn_abi, Some(instance))
76+
cx.declare_fn(sym, fn_abi)
7877
};
7978
debug!("get_fn: not casting pointer!");
8079

compiler/rustc_codegen_llvm/src/declare.rs

Lines changed: 17 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,8 @@ use crate::llvm::AttributePlace::Function;
1919
use crate::type_::Type;
2020
use crate::value::Value;
2121
use rustc_codegen_ssa::traits::TypeMembershipMethods;
22-
use rustc_middle::ty::{Instance, Ty};
23-
use rustc_symbol_mangling::typeid::{
24-
kcfi_typeid_for_fnabi, kcfi_typeid_for_instance, typeid_for_fnabi, typeid_for_instance,
25-
TypeIdOptions,
26-
};
22+
use rustc_middle::ty::Ty;
23+
use rustc_symbol_mangling::typeid::{kcfi_typeid_for_fnabi, typeid_for_fnabi, TypeIdOptions};
2724
use smallvec::SmallVec;
2825

2926
/// Declare a function.
@@ -119,12 +116,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
119116
///
120117
/// If there’s a value with the same name already declared, the function will
121118
/// update the declaration and return existing Value instead.
122-
pub fn declare_fn(
123-
&self,
124-
name: &str,
125-
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
126-
instance: Option<Instance<'tcx>>,
127-
) -> &'ll Value {
119+
pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Value {
128120
debug!("declare_rust_fn(name={:?}, fn_abi={:?})", name, fn_abi);
129121

130122
// Function addresses in Rust are never significant, allowing functions to
@@ -140,35 +132,18 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
140132
fn_abi.apply_attrs_llfn(self, llfn);
141133

142134
if self.tcx.sess.is_sanitizer_cfi_enabled() {
143-
if let Some(instance) = instance {
144-
let typeid = typeid_for_instance(self.tcx, &instance, TypeIdOptions::empty());
145-
self.set_type_metadata(llfn, typeid);
146-
let typeid =
147-
typeid_for_instance(self.tcx, &instance, TypeIdOptions::GENERALIZE_POINTERS);
148-
self.add_type_metadata(llfn, typeid);
149-
let typeid =
150-
typeid_for_instance(self.tcx, &instance, TypeIdOptions::NORMALIZE_INTEGERS);
151-
self.add_type_metadata(llfn, typeid);
152-
let typeid = typeid_for_instance(
153-
self.tcx,
154-
&instance,
155-
TypeIdOptions::GENERALIZE_POINTERS | TypeIdOptions::NORMALIZE_INTEGERS,
156-
);
157-
self.add_type_metadata(llfn, typeid);
158-
} else {
159-
let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::empty());
160-
self.set_type_metadata(llfn, typeid);
161-
let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::GENERALIZE_POINTERS);
162-
self.add_type_metadata(llfn, typeid);
163-
let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::NORMALIZE_INTEGERS);
164-
self.add_type_metadata(llfn, typeid);
165-
let typeid = typeid_for_fnabi(
166-
self.tcx,
167-
fn_abi,
168-
TypeIdOptions::GENERALIZE_POINTERS | TypeIdOptions::NORMALIZE_INTEGERS,
169-
);
170-
self.add_type_metadata(llfn, typeid);
171-
}
135+
let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::empty());
136+
self.set_type_metadata(llfn, typeid);
137+
let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::GENERALIZE_POINTERS);
138+
self.add_type_metadata(llfn, typeid);
139+
let typeid = typeid_for_fnabi(self.tcx, fn_abi, TypeIdOptions::NORMALIZE_INTEGERS);
140+
self.add_type_metadata(llfn, typeid);
141+
let typeid = typeid_for_fnabi(
142+
self.tcx,
143+
fn_abi,
144+
TypeIdOptions::GENERALIZE_POINTERS | TypeIdOptions::NORMALIZE_INTEGERS,
145+
);
146+
self.add_type_metadata(llfn, typeid);
172147
}
173148

174149
if self.tcx.sess.is_sanitizer_kcfi_enabled() {
@@ -181,13 +156,8 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
181156
options.insert(TypeIdOptions::NORMALIZE_INTEGERS);
182157
}
183158

184-
if let Some(instance) = instance {
185-
let kcfi_typeid = kcfi_typeid_for_instance(self.tcx, &instance, options);
186-
self.set_kcfi_type_metadata(llfn, kcfi_typeid);
187-
} else {
188-
let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi, options);
189-
self.set_kcfi_type_metadata(llfn, kcfi_typeid);
190-
}
159+
let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi, options);
160+
self.set_kcfi_type_metadata(llfn, kcfi_typeid);
191161
}
192162

193163
llfn

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,7 @@ fn gen_fn<'ll, 'tcx>(
939939
) -> (&'ll Type, &'ll Value) {
940940
let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
941941
let llty = fn_abi.llvm_type(cx);
942-
let llfn = cx.declare_fn(name, fn_abi, None);
942+
let llfn = cx.declare_fn(name, fn_abi);
943943
cx.set_frame_pointer_type(llfn);
944944
cx.apply_target_cpu_attr(llfn);
945945
// FIXME(eddyb) find a nicer way to do this.

compiler/rustc_codegen_llvm/src/mono_item.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
5151
assert!(!instance.args.has_infer());
5252

5353
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
54-
let lldecl = self.declare_fn(symbol_name, fn_abi, Some(instance));
54+
let lldecl = self.declare_fn(symbol_name, fn_abi);
5555
unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) };
5656
let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
5757
base::set_link_section(lldecl, attrs);

compiler/rustc_symbol_mangling/src/typeid.rs

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/// For more information about LLVM CFI and cross-language LLVM CFI support for the Rust compiler,
55
/// see design document in the tracking issue #89653.
66
use bitflags::bitflags;
7-
use rustc_middle::ty::{Instance, Ty, TyCtxt};
7+
use rustc_middle::ty::{Ty, TyCtxt};
88
use rustc_target::abi::call::FnAbi;
99
use std::hash::Hasher;
1010
use twox_hash::XxHash64;
@@ -30,15 +30,6 @@ pub fn typeid_for_fnabi<'tcx>(
3030
typeid_itanium_cxx_abi::typeid_for_fnabi(tcx, fn_abi, options)
3131
}
3232

33-
/// Returns a type metadata identifier for the specified Instance.
34-
pub fn typeid_for_instance<'tcx>(
35-
tcx: TyCtxt<'tcx>,
36-
instance: &Instance<'tcx>,
37-
options: TypeIdOptions,
38-
) -> String {
39-
typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options)
40-
}
41-
4233
/// Returns a KCFI type metadata identifier for the specified FnAbi.
4334
pub fn kcfi_typeid_for_fnabi<'tcx>(
4435
tcx: TyCtxt<'tcx>,
@@ -51,16 +42,3 @@ pub fn kcfi_typeid_for_fnabi<'tcx>(
5142
hash.write(typeid_itanium_cxx_abi::typeid_for_fnabi(tcx, fn_abi, options).as_bytes());
5243
hash.finish() as u32
5344
}
54-
55-
/// Returns a KCFI type metadata identifier for the specified Instance.
56-
pub fn kcfi_typeid_for_instance<'tcx>(
57-
tcx: TyCtxt<'tcx>,
58-
instance: &Instance<'tcx>,
59-
options: TypeIdOptions,
60-
) -> u32 {
61-
// A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the
62-
// xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)
63-
let mut hash: XxHash64 = Default::default();
64-
hash.write(typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options).as_bytes());
65-
hash.finish() as u32
66-
}

compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs

Lines changed: 2 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use rustc_data_structures::fx::FxHashMap;
1212
use rustc_hir as hir;
1313
use rustc_middle::ty::layout::IntegerExt;
1414
use rustc_middle::ty::{
15-
self, Const, ExistentialPredicate, FloatTy, FnSig, Instance, IntTy, List, Region, RegionKind,
16-
TermKind, Ty, TyCtxt, UintTy,
15+
self, Const, ExistentialPredicate, FloatTy, FnSig, IntTy, List, Region, RegionKind, TermKind,
16+
Ty, TyCtxt, UintTy,
1717
};
1818
use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef};
1919
use rustc_span::def_id::DefId;
@@ -1074,58 +1074,3 @@ pub fn typeid_for_fnabi<'tcx>(
10741074

10751075
typeid
10761076
}
1077-
1078-
/// Returns a type metadata identifier for the specified Instance using the Itanium C++ ABI with
1079-
/// vendor extended type qualifiers and types for Rust types that are not used at the FFI boundary.
1080-
pub fn typeid_for_instance<'tcx>(
1081-
tcx: TyCtxt<'tcx>,
1082-
instance: &Instance<'tcx>,
1083-
options: TypeIdOptions,
1084-
) -> String {
1085-
let fn_abi = tcx
1086-
.fn_abi_of_instance(tcx.param_env(instance.def_id()).and((*instance, ty::List::empty())))
1087-
.unwrap_or_else(|instance| {
1088-
bug!("typeid_for_instance: couldn't get fn_abi of instance {:?}", instance)
1089-
});
1090-
1091-
// If this instance is a method and self is a reference, get the impl it belongs to
1092-
let impl_def_id = tcx.impl_of_method(instance.def_id());
1093-
if impl_def_id.is_some() && !fn_abi.args.is_empty() && fn_abi.args[0].layout.ty.is_ref() {
1094-
// If this impl is not an inherent impl, get the trait it implements
1095-
if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id.unwrap()) {
1096-
// Transform the concrete self into a reference to a trait object
1097-
let existential_predicate = trait_ref.map_bound(|trait_ref| {
1098-
ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty(
1099-
tcx, trait_ref,
1100-
))
1101-
});
1102-
let existential_predicates = tcx.mk_poly_existential_predicates(&[ty::Binder::dummy(
1103-
existential_predicate.skip_binder(),
1104-
)]);
1105-
// Is the concrete self mutable?
1106-
let self_ty = if fn_abi.args[0].layout.ty.is_mutable_ptr() {
1107-
Ty::new_mut_ref(
1108-
tcx,
1109-
tcx.lifetimes.re_erased,
1110-
Ty::new_dynamic(tcx, existential_predicates, tcx.lifetimes.re_erased, ty::Dyn),
1111-
)
1112-
} else {
1113-
Ty::new_imm_ref(
1114-
tcx,
1115-
tcx.lifetimes.re_erased,
1116-
Ty::new_dynamic(tcx, existential_predicates, tcx.lifetimes.re_erased, ty::Dyn),
1117-
)
1118-
};
1119-
1120-
// Replace the concrete self in an fn_abi clone by the reference to a trait object
1121-
let mut fn_abi = fn_abi.clone();
1122-
// HACK(rcvalle): It is okay to not replace or update the entire ArgAbi here because the
1123-
// other fields are never used.
1124-
fn_abi.args[0].layout.ty = self_ty;
1125-
1126-
return typeid_for_fnabi(tcx, &fn_abi, options);
1127-
}
1128-
}
1129-
1130-
typeid_for_fnabi(tcx, fn_abi, options)
1131-
}

compiler/rustc_target/src/abi/call/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ impl Uniform {
268268
/// `rest.unit` register type gets repeated often enough to cover `rest.size`. This describes the
269269
/// actual type used for the call; the Rust type of the argument is then transmuted to this ABI type
270270
/// (and all data in the padding between the registers is dropped).
271-
#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
271+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
272272
pub struct CastTarget {
273273
pub prefix: [Option<Reg>; 8],
274274
pub rest: Uniform,
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Check that the type of trait methods on a concrete type are not abstracted
2+
3+
//@ needs-sanitizer-cfi
4+
//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
5+
//@ compile-flags: -C codegen-units=1 -C opt-level=0
6+
//@ run-pass
7+
8+
trait Foo {
9+
fn foo(&self);
10+
}
11+
12+
struct S;
13+
14+
impl Foo for S {
15+
fn foo(&self) {}
16+
}
17+
18+
struct S2 {
19+
f: fn(&S)
20+
}
21+
22+
impl S2 {
23+
fn foo(&self, s: &S) {
24+
(self.f)(s)
25+
}
26+
}
27+
28+
fn main() {
29+
S2 { f: <S as Foo>::foo }.foo(&S)
30+
}

0 commit comments

Comments
 (0)