Skip to content

Commit 2511c26

Browse files
committed
fix -Zsanitizer=kcfi on #[naked] functions
1 parent f46ce66 commit 2511c26

File tree

2 files changed

+54
-6
lines changed

2 files changed

+54
-6
lines changed

compiler/rustc_codegen_ssa/src/mono_item.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
22
use rustc_middle::mir::mono::{Linkage, MonoItem, MonoItemData, Visibility};
3+
use rustc_middle::ty::InstanceKind;
34
use rustc_middle::ty::layout::HasTyCtxt;
45
use tracing::debug;
56

@@ -41,12 +42,12 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
4142
base::codegen_global_asm(cx, item_id);
4243
}
4344
MonoItem::Fn(instance) => {
44-
if cx
45-
.tcx()
46-
.codegen_fn_attrs(instance.def_id())
47-
.flags
48-
.contains(CodegenFnAttrFlags::NAKED)
49-
{
45+
// A shim used by `-Zsanitizer=kcfi`. Its body is a call to the real function.
46+
// The shim should be codegened like a normal function.
47+
let is_reify_shim = matches!(instance.def, InstanceKind::ReifyShim(..));
48+
49+
let flags = cx.tcx().codegen_fn_attrs(instance.def_id()).flags;
50+
if flags.contains(CodegenFnAttrFlags::NAKED) && !is_reify_shim {
5051
naked_asm::codegen_naked_asm::<Bx::CodegenCx>(cx, instance, item_data);
5152
} else {
5253
base::codegen_instance::<Bx>(cx, instance);
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//@ add-core-stubs
2+
//@ revisions: aarch64 x86_64
3+
//@ [aarch64] compile-flags: --target aarch64-unknown-none
4+
//@ [aarch64] needs-llvm-components: aarch64
5+
//@ [x86_64] compile-flags: --target x86_64-unknown-none
6+
//@ [x86_64] needs-llvm-components: x86
7+
//@ compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi -Cno-prepopulate-passes -Copt-level=0
8+
9+
#![feature(no_core, lang_items)]
10+
#![crate_type = "lib"]
11+
#![no_core]
12+
13+
extern crate minicore;
14+
use minicore::*;
15+
16+
struct Thing;
17+
trait MyTrait {
18+
#[unsafe(naked)]
19+
extern "C" fn my_naked_function() {
20+
// the real function is defined
21+
// CHECK: .globl
22+
// CHECK-SAME: my_naked_function
23+
naked_asm!("ret")
24+
}
25+
}
26+
impl MyTrait for Thing {}
27+
28+
// CHECK-LABEL: main
29+
#[unsafe(no_mangle)]
30+
pub fn main() {
31+
// Trick the compiler into generating an indirect call.
32+
const F: extern "C" fn() = Thing::my_naked_function;
33+
34+
// main calls the shim function
35+
// CHECK: call
36+
// CHECK-SAME: my_naked_function
37+
// CHECK-SAME: reify.shim.fnptr
38+
(F)();
39+
}
40+
41+
// the shim calls the real function
42+
// CHECK: define
43+
// CHECK-SAME: my_naked_function
44+
// CHECK-SAME: reify.shim.fnptr
45+
46+
// CHECK: declare !kcfi_type
47+
// CHECK-SAME: my_naked_function

0 commit comments

Comments
 (0)