Skip to content

Commit d6dd269

Browse files
committed
use #[naked] for __rust_probestack
1 parent 59aa1e8 commit d6dd269

File tree

2 files changed

+41
-97
lines changed

2 files changed

+41
-97
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/probestack.rs

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

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

190123
// This function is the same as above, except that some instructions are
191124
// [manually patched for LVI].
@@ -195,8 +128,10 @@ core::arch::global_asm!(
195128
target_arch = "x86_64",
196129
all(target_env = "sgx", target_vendor = "fortanix")
197130
))]
198-
core::arch::global_asm!(
199-
define_rust_probestack!(
131+
#[unsafe(naked)]
132+
#[no_mangle]
133+
pub unsafe extern "C" fn __rust_probestack() {
134+
core::arch::naked_asm!(
200135
"
201136
.cfi_startproc
202137
pushq %rbp
@@ -248,19 +183,23 @@ core::arch::global_asm!(
248183
lfence
249184
jmp *%r11
250185
.cfi_endproc
251-
"
252-
),
253-
options(att_syntax)
254-
);
186+
",
187+
options(att_syntax)
188+
)
189+
}
255190

256191
#[cfg(all(target_arch = "x86", not(target_os = "uefi")))]
257192
// This is the same as x86_64 above, only translated for 32-bit sizes. Note
258193
// that on Unix we're expected to restore everything as it was, this
259194
// function basically can't tamper with anything.
260195
//
196+
// This function is unsafe because it uses a custom ABI, it does not actually match `extern "C"`.
197+
//
261198
// The ABI here is the same as x86_64, except everything is 32-bits large.
262-
core::arch::global_asm!(
263-
define_rust_probestack!(
199+
#[unsafe(naked)]
200+
#[rustc_std_internal_symbol]
201+
pub unsafe extern "C" fn __rust_probestack() {
202+
core::arch::naked_asm!(
264203
"
265204
.cfi_startproc
266205
push %ebp
@@ -291,24 +230,28 @@ core::arch::global_asm!(
291230
.cfi_adjust_cfa_offset -4
292231
ret
293232
.cfi_endproc
294-
"
295-
),
296-
options(att_syntax)
297-
);
233+
",
234+
options(att_syntax)
235+
)
236+
}
298237

299238
#[cfg(all(target_arch = "x86", target_os = "uefi"))]
300239
// UEFI target is windows like target. LLVM will do _chkstk things like windows.
301240
// probestack function will also do things like _chkstk in MSVC.
302241
// So we need to sub %ax %sp in probestack when arch is x86.
303242
//
243+
// This function is unsafe because it uses a custom ABI, it does not actually match `extern "C"`.
244+
//
304245
// REF: Rust commit(74e80468347)
305246
// rust\src\llvm-project\llvm\lib\Target\X86\X86FrameLowering.cpp: 805
306247
// Comments in LLVM:
307248
// MSVC x32's _chkstk and cygwin/mingw's _alloca adjust %esp themselves.
308249
// MSVC x64's __chkstk and cygwin/mingw's ___chkstk_ms do not adjust %rsp
309250
// themselves.
310-
core::arch::global_asm!(
311-
define_rust_probestack!(
251+
#[unsafe(naked)]
252+
#[rustc_std_internal_symbol]
253+
pub unsafe extern "C" fn __rust_probestack() {
254+
core::arch::naked_asm!(
312255
"
313256
.cfi_startproc
314257
push %ebp
@@ -344,7 +287,7 @@ core::arch::global_asm!(
344287
.cfi_adjust_cfa_offset -4
345288
ret
346289
.cfi_endproc
347-
"
348-
),
349-
options(att_syntax)
350-
);
290+
",
291+
options(att_syntax)
292+
)
293+
}

0 commit comments

Comments
 (0)