Rollup merge of #143293 - folkertdev:naked-function-kcfi, r=compiler-errors
fix `-Zsanitizer=kcfi` on `#[naked]` functions fixes https://github.com/rust-lang/rust/issues/143266 With `-Zsanitizer=kcfi`, indirect calls happen via generated intermediate shim that forwards the call. The generated shim preserves the attributes of the original, including `#[unsafe(naked)]`. The shim is not a naked function though, and violates its invariants (like having a body that consists of a single `naked_asm!` call). My fix here is to match on the `InstanceKind`, and only use `codegen_naked_asm` when the instance is not a `ReifyShim`. That does beg the question whether there are other `InstanceKind`s that could come up. As far as I can tell the answer is no: calling via `dyn` seems to work find, and `#[track_caller]` is disallowed in combination with `#[naked]`. r? codegen ````@rustbot```` label +A-naked cc ````@maurer```` ````@rcvalle````
This commit is contained in:
@@ -356,7 +356,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
LocalRef::Operand(operand) => {
|
||||
// Don't spill operands onto the stack in naked functions.
|
||||
// See: https://github.com/rust-lang/rust/issues/42779
|
||||
let attrs = bx.tcx().codegen_fn_attrs(self.instance.def_id());
|
||||
let attrs = bx.tcx().codegen_instance_attrs(self.instance.def);
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -390,9 +390,8 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
|
||||
let mut num_untupled = None;
|
||||
|
||||
let codegen_fn_attrs = bx.tcx().codegen_fn_attrs(fx.instance.def_id());
|
||||
let naked = codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED);
|
||||
if naked {
|
||||
let codegen_fn_attrs = bx.tcx().codegen_instance_attrs(fx.instance.def);
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ fn prefix_and_suffix<'tcx>(
|
||||
let is_arm = tcx.sess.target.arch == "arm";
|
||||
let is_thumb = tcx.sess.unstable_target_features.contains(&sym::thumb_mode);
|
||||
|
||||
let attrs = tcx.codegen_fn_attrs(instance.def_id());
|
||||
let attrs = tcx.codegen_instance_attrs(instance.def);
|
||||
let link_section = attrs.link_section.map(|symbol| symbol.as_str().to_string());
|
||||
|
||||
// If no alignment is specified, an alignment of 4 bytes is used.
|
||||
|
||||
@@ -611,11 +611,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
|
||||
let fn_ty = bx.fn_decl_backend_type(fn_abi);
|
||||
let fn_attrs = if bx.tcx().def_kind(instance.def_id()).has_codegen_attrs() {
|
||||
Some(bx.tcx().codegen_fn_attrs(instance.def_id()))
|
||||
Some(bx.tcx().codegen_instance_attrs(instance.def))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
bx.call(fn_ty, fn_attrs, Some(fn_abi), fn_ptr, &[], None, Some(instance))
|
||||
bx.call(
|
||||
fn_ty,
|
||||
fn_attrs.as_deref(),
|
||||
Some(fn_abi),
|
||||
fn_ptr,
|
||||
&[],
|
||||
None,
|
||||
Some(instance),
|
||||
)
|
||||
} else {
|
||||
bx.get_static(def_id)
|
||||
};
|
||||
|
||||
@@ -41,12 +41,8 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
|
||||
base::codegen_global_asm(cx, item_id);
|
||||
}
|
||||
MonoItem::Fn(instance) => {
|
||||
if cx
|
||||
.tcx()
|
||||
.codegen_fn_attrs(instance.def_id())
|
||||
.flags
|
||||
.contains(CodegenFnAttrFlags::NAKED)
|
||||
{
|
||||
let flags = cx.tcx().codegen_instance_attrs(instance.def).flags;
|
||||
if flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
naked_asm::codegen_naked_asm::<Bx::CodegenCx>(cx, instance, item_data);
|
||||
} else {
|
||||
base::codegen_instance::<Bx>(cx, instance);
|
||||
@@ -75,7 +71,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
|
||||
cx.predefine_static(def_id, linkage, visibility, symbol_name);
|
||||
}
|
||||
MonoItem::Fn(instance) => {
|
||||
let attrs = cx.tcx().codegen_fn_attrs(instance.def_id());
|
||||
let attrs = cx.tcx().codegen_instance_attrs(instance.def);
|
||||
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
// do not define this function; it will become a global assembly block
|
||||
|
||||
Reference in New Issue
Block a user