a6ecd1a73f
Use the "volatile" option and the "memory" clobber on inline asm that does things like return directly, to reduce the chances of compilers rearranging the code.
73 lines
2.1 KiB
Rust
73 lines
2.1 KiB
Rust
#![allow(unused_imports)]
|
|
|
|
use core::intrinsics;
|
|
|
|
// NOTE These functions are implemented using assembly because they using a custom
|
|
// calling convention which can't be implemented using a normal Rust function
|
|
|
|
// NOTE These functions are never mangled as they are not tested against compiler-rt
|
|
// and mangling ___chkstk would break the `jmp ___chkstk` instruction in __alloca
|
|
|
|
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
|
|
#[naked]
|
|
#[no_mangle]
|
|
pub unsafe fn ___chkstk_ms() {
|
|
asm!("
|
|
push %ecx
|
|
push %eax
|
|
cmp $$0x1000,%eax
|
|
lea 12(%esp),%ecx
|
|
jb 1f
|
|
2:
|
|
sub $$0x1000,%ecx
|
|
test %ecx,(%ecx)
|
|
sub $$0x1000,%eax
|
|
cmp $$0x1000,%eax
|
|
ja 2b
|
|
1:
|
|
sub %eax,%ecx
|
|
test %ecx,(%ecx)
|
|
pop %eax
|
|
pop %ecx
|
|
ret" ::: "memory" : "volatile");
|
|
intrinsics::unreachable();
|
|
}
|
|
|
|
// FIXME: __alloca should be an alias to __chkstk
|
|
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
|
|
#[naked]
|
|
#[no_mangle]
|
|
pub unsafe fn __alloca() {
|
|
asm!("jmp ___chkstk // Jump to ___chkstk since fallthrough may be unreliable"
|
|
::: "memory" : "volatile");
|
|
intrinsics::unreachable();
|
|
}
|
|
|
|
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
|
|
#[naked]
|
|
#[no_mangle]
|
|
pub unsafe fn ___chkstk() {
|
|
asm!("
|
|
push %ecx
|
|
cmp $$0x1000,%eax
|
|
lea 8(%esp),%ecx // esp before calling this routine -> ecx
|
|
jb 1f
|
|
2:
|
|
sub $$0x1000,%ecx
|
|
test %ecx,(%ecx)
|
|
sub $$0x1000,%eax
|
|
cmp $$0x1000,%eax
|
|
ja 2b
|
|
1:
|
|
sub %eax,%ecx
|
|
test %ecx,(%ecx)
|
|
|
|
lea 4(%esp),%eax // load pointer to the return address into eax
|
|
mov %ecx,%esp // install the new top of stack pointer into esp
|
|
mov -4(%eax),%ecx // restore ecx
|
|
push (%eax) // push return address onto the stack
|
|
sub %esp,%eax // restore the original value in eax
|
|
ret" ::: "memory" : "volatile");
|
|
intrinsics::unreachable();
|
|
}
|