Skip to content

Commit 23d752e

Browse files
committed
use #[naked] for __rust_probestack
1 parent d13a431 commit 23d752e

File tree

3 files changed

+42
-99
lines changed

3 files changed

+42
-99
lines changed

compiler/rustc_codegen_llvm/src/attributes.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_hir::def_id::DefId;
55
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry};
66
use rustc_middle::ty::{self, TyCtxt};
77
use rustc_session::config::{BranchProtection, FunctionReturn, OptLevel, PAuthKey, PacRet};
8+
use rustc_symbol_mangling::mangle_internal_symbol;
89
use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector};
910
use smallvec::SmallVec;
1011

@@ -256,11 +257,11 @@ fn probestack_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
256257
StackProbeType::Inline => "inline-asm",
257258
// Flag our internal `__rust_probestack` function as the stack probe symbol.
258259
// This is defined in the `compiler-builtins` crate for each architecture.
259-
StackProbeType::Call => "__rust_probestack",
260+
StackProbeType::Call => &mangle_internal_symbol(cx.tcx, "__rust_probestack"),
260261
// Pick from the two above based on the LLVM version.
261262
StackProbeType::InlineOrCall { min_llvm_version_for_inline } => {
262263
if llvm_util::get_version() < min_llvm_version_for_inline {
263-
"__rust_probestack"
264+
&mangle_internal_symbol(cx.tcx, "__rust_probestack")
264265
} else {
265266
"inline-asm"
266267
}

library/compiler-builtins/compiler-builtins/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#![feature(linkage)]
99
#![feature(naked_functions)]
1010
#![feature(repr_simd)]
11+
#![feature(rustc_attrs)]
1112
#![cfg_attr(f16_enabled, feature(f16))]
1213
#![cfg_attr(f128_enabled, feature(f128))]
1314
#![no_builtins]

library/compiler-builtins/compiler-builtins/src/probestack.rs

Lines changed: 38 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -49,82 +49,11 @@
4949
// We only define stack probing for these architectures today.
5050
#![cfg(any(target_arch = "x86_64", target_arch = "x86"))]
5151

52-
// SAFETY: defined in this module.
53-
// FIXME(extern_custom): the ABI is not correct.
54-
unsafe extern "C" {
55-
pub fn __rust_probestack();
56-
}
57-
58-
// A wrapper for our implementation of __rust_probestack, which allows us to
59-
// keep the assembly inline while controlling all CFI directives in the assembly
60-
// emitted for the function.
61-
//
62-
// This is the ELF version.
63-
#[cfg(not(any(target_vendor = "apple", target_os = "uefi")))]
64-
macro_rules! define_rust_probestack {
65-
($body: expr) => {
66-
concat!(
67-
"
68-
.pushsection .text.__rust_probestack
69-
.globl __rust_probestack
70-
.type __rust_probestack, @function
71-
.hidden __rust_probestack
72-
__rust_probestack:
73-
",
74-
$body,
75-
"
76-
.size __rust_probestack, . - __rust_probestack
77-
.popsection
78-
"
79-
)
80-
};
81-
}
82-
83-
#[cfg(all(target_os = "uefi", target_arch = "x86_64"))]
84-
macro_rules! define_rust_probestack {
85-
($body: expr) => {
86-
concat!(
87-
"
88-
.globl __rust_probestack
89-
__rust_probestack:
90-
",
91-
$body
92-
)
93-
};
94-
}
95-
96-
// Same as above, but for Mach-O. Note that the triple underscore
97-
// is deliberate
98-
#[cfg(target_vendor = "apple")]
99-
macro_rules! define_rust_probestack {
100-
($body: expr) => {
101-
concat!(
102-
"
103-
.globl ___rust_probestack
104-
___rust_probestack:
105-
",
106-
$body
107-
)
108-
};
109-
}
110-
111-
// In UEFI x86 arch, triple underscore is deliberate.
112-
#[cfg(all(target_os = "uefi", target_arch = "x86"))]
113-
macro_rules! define_rust_probestack {
114-
($body: expr) => {
115-
concat!(
116-
"
117-
.globl ___rust_probestack
118-
___rust_probestack:
119-
",
120-
$body
121-
)
122-
};
123-
}
124-
12552
// Our goal here is to touch each page between %rsp+8 and %rsp+8-%rax,
12653
// ensuring that if any pages are unmapped we'll make a page fault.
12754
//
55+
// This function is unsafe because it uses a custom ABI, it does not actually match `extern "C"`.
56+
//
12857
// The ABI here is that the stack frame size is located in `%rax`. Upon
12958
// return we're not supposed to modify `%rsp` or `%rax`.
13059
//
@@ -133,8 +62,10 @@ macro_rules! define_rust_probestack {
13362
target_arch = "x86_64",
13463
not(all(target_env = "sgx", target_vendor = "fortanix"))
13564
))]
136-
core::arch::global_asm!(
137-
define_rust_probestack!(
65+
#[unsafe(naked)]
66+
#[rustc_std_internal_symbol]
67+
pub unsafe extern "C" fn __rust_probestack() {
68+
core::arch::naked_asm!(
13869
"
13970
.cfi_startproc
14071
pushq %rbp
@@ -184,10 +115,10 @@ core::arch::global_asm!(
184115
.cfi_adjust_cfa_offset -8
185116
ret
186117
.cfi_endproc
187-
"
188-
),
189-
options(att_syntax)
190-
);
118+
",
119+
options(att_syntax)
120+
)
121+
}
191122

192123
// This function is the same as above, except that some instructions are
193124
// [manually patched for LVI].
@@ -197,8 +128,10 @@ core::arch::global_asm!(
197128
target_arch = "x86_64",
198129
all(target_env = "sgx", target_vendor = "fortanix")
199130
))]
200-
core::arch::global_asm!(
201-
define_rust_probestack!(
131+
#[unsafe(naked)]
132+
#[no_mangle]
133+
pub unsafe extern "C" fn __rust_probestack() {
134+
core::arch::naked_asm!(
202135
"
203136
.cfi_startproc
204137
pushq %rbp
@@ -250,19 +183,23 @@ core::arch::global_asm!(
250183
lfence
251184
jmp *%r11
252185
.cfi_endproc
253-
"
254-
),
255-
options(att_syntax)
256-
);
186+
",
187+
options(att_syntax)
188+
)
189+
}
257190

258191
#[cfg(all(target_arch = "x86", not(target_os = "uefi")))]
259192
// This is the same as x86_64 above, only translated for 32-bit sizes. Note
260193
// that on Unix we're expected to restore everything as it was, this
261194
// function basically can't tamper with anything.
262195
//
196+
// This function is unsafe because it uses a custom ABI, it does not actually match `extern "C"`.
197+
//
263198
// The ABI here is the same as x86_64, except everything is 32-bits large.
264-
core::arch::global_asm!(
265-
define_rust_probestack!(
199+
#[unsafe(naked)]
200+
#[rustc_std_internal_symbol]
201+
pub unsafe extern "C" fn __rust_probestack() {
202+
core::arch::naked_asm!(
266203
"
267204
.cfi_startproc
268205
push %ebp
@@ -293,24 +230,28 @@ core::arch::global_asm!(
293230
.cfi_adjust_cfa_offset -4
294231
ret
295232
.cfi_endproc
296-
"
297-
),
298-
options(att_syntax)
299-
);
233+
",
234+
options(att_syntax)
235+
)
236+
}
300237

301238
#[cfg(all(target_arch = "x86", target_os = "uefi"))]
302239
// UEFI target is windows like target. LLVM will do _chkstk things like windows.
303240
// probestack function will also do things like _chkstk in MSVC.
304241
// So we need to sub %ax %sp in probestack when arch is x86.
305242
//
243+
// This function is unsafe because it uses a custom ABI, it does not actually match `extern "C"`.
244+
//
306245
// REF: Rust commit(74e80468347)
307246
// rust\src\llvm-project\llvm\lib\Target\X86\X86FrameLowering.cpp: 805
308247
// Comments in LLVM:
309248
// MSVC x32's _chkstk and cygwin/mingw's _alloca adjust %esp themselves.
310249
// MSVC x64's __chkstk and cygwin/mingw's ___chkstk_ms do not adjust %rsp
311250
// themselves.
312-
core::arch::global_asm!(
313-
define_rust_probestack!(
251+
#[unsafe(naked)]
252+
#[rustc_std_internal_symbol]
253+
pub unsafe extern "C" fn __rust_probestack() {
254+
core::arch::naked_asm!(
314255
"
315256
.cfi_startproc
316257
push %ebp
@@ -346,7 +287,7 @@ core::arch::global_asm!(
346287
.cfi_adjust_cfa_offset -4
347288
ret
348289
.cfi_endproc
349-
"
350-
),
351-
options(att_syntax)
352-
);
290+
",
291+
options(att_syntax)
292+
)
293+
}

0 commit comments

Comments
 (0)