49
49
// We only define stack probing for these architectures today.
50
50
#![ cfg( any( target_arch = "x86_64" , target_arch = "x86" ) ) ]
51
51
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
-
123
52
// Our goal here is to touch each page between %rsp+8 and %rsp+8-%rax,
124
53
// ensuring that if any pages are unmapped we'll make a page fault.
125
54
//
55
+ // This function is unsafe because it uses a custom ABI, it does not actually match `extern "C"`.
56
+ //
126
57
// The ABI here is that the stack frame size is located in `%rax`. Upon
127
58
// return we're not supposed to modify `%rsp` or `%rax`.
128
59
//
@@ -131,8 +62,10 @@ macro_rules! define_rust_probestack {
131
62
target_arch = "x86_64" ,
132
63
not( all( target_env = "sgx" , target_vendor = "fortanix" ) )
133
64
) ) ]
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!(
136
69
"
137
70
.cfi_startproc
138
71
pushq %rbp
@@ -182,10 +115,10 @@ core::arch::global_asm!(
182
115
.cfi_adjust_cfa_offset -8
183
116
ret
184
117
.cfi_endproc
185
- "
186
- ) ,
187
- options ( att_syntax )
188
- ) ;
118
+ " ,
119
+ options ( att_syntax )
120
+ )
121
+ }
189
122
190
123
// This function is the same as above, except that some instructions are
191
124
// [manually patched for LVI].
@@ -195,8 +128,10 @@ core::arch::global_asm!(
195
128
target_arch = "x86_64" ,
196
129
all( target_env = "sgx" , target_vendor = "fortanix" )
197
130
) ) ]
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!(
200
135
"
201
136
.cfi_startproc
202
137
pushq %rbp
@@ -248,19 +183,23 @@ core::arch::global_asm!(
248
183
lfence
249
184
jmp *%r11
250
185
.cfi_endproc
251
- "
252
- ) ,
253
- options ( att_syntax )
254
- ) ;
186
+ " ,
187
+ options ( att_syntax )
188
+ )
189
+ }
255
190
256
191
#[ cfg( all( target_arch = "x86" , not( target_os = "uefi" ) ) ) ]
257
192
// This is the same as x86_64 above, only translated for 32-bit sizes. Note
258
193
// that on Unix we're expected to restore everything as it was, this
259
194
// function basically can't tamper with anything.
260
195
//
196
+ // This function is unsafe because it uses a custom ABI, it does not actually match `extern "C"`.
197
+ //
261
198
// 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!(
264
203
"
265
204
.cfi_startproc
266
205
push %ebp
@@ -291,24 +230,28 @@ core::arch::global_asm!(
291
230
.cfi_adjust_cfa_offset -4
292
231
ret
293
232
.cfi_endproc
294
- "
295
- ) ,
296
- options ( att_syntax )
297
- ) ;
233
+ " ,
234
+ options ( att_syntax )
235
+ )
236
+ }
298
237
299
238
#[ cfg( all( target_arch = "x86" , target_os = "uefi" ) ) ]
300
239
// UEFI target is windows like target. LLVM will do _chkstk things like windows.
301
240
// probestack function will also do things like _chkstk in MSVC.
302
241
// So we need to sub %ax %sp in probestack when arch is x86.
303
242
//
243
+ // This function is unsafe because it uses a custom ABI, it does not actually match `extern "C"`.
244
+ //
304
245
// REF: Rust commit(74e80468347)
305
246
// rust\src\llvm-project\llvm\lib\Target\X86\X86FrameLowering.cpp: 805
306
247
// Comments in LLVM:
307
248
// MSVC x32's _chkstk and cygwin/mingw's _alloca adjust %esp themselves.
308
249
// MSVC x64's __chkstk and cygwin/mingw's ___chkstk_ms do not adjust %rsp
309
250
// 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!(
312
255
"
313
256
.cfi_startproc
314
257
push %ebp
@@ -344,7 +287,7 @@ core::arch::global_asm!(
344
287
.cfi_adjust_cfa_offset -4
345
288
ret
346
289
.cfi_endproc
347
- "
348
- ) ,
349
- options ( att_syntax )
350
- ) ;
290
+ " ,
291
+ options ( att_syntax )
292
+ )
293
+ }
0 commit comments