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