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