diff --git a/src/probestack.rs b/src/probestack.rs index 8b9d5082..a2e9c875 100644 --- a/src/probestack.rs +++ b/src/probestack.rs @@ -43,13 +43,14 @@ #![cfg(not(windows))] // Windows already has builtins to do this +#[cfg(all(any(target_arch = "x86_64", target_arch = "x86"), not(target_vendor = "apple")))] extern "C" { pub fn __rust_probestack(); } #[naked] #[no_mangle] -#[cfg(all(target_arch = "x86_64", not(feature = "mangled-names")))] +#[cfg(all(target_arch = "x86_64", not(target_vendor = "apple"), not(feature = "mangled-names")))] pub unsafe extern "C" fn __rust_probestack_wrapper() { // Our goal here is to touch each page between %rsp+8 and %rsp+8-%rax, // ensuring that if any pages are unmapped we'll make a page fault. @@ -128,7 +129,7 @@ pub unsafe extern "C" fn __rust_probestack_wrapper() { #[naked] #[no_mangle] -#[cfg(all(target_arch = "x86", not(feature = "mangled-names")))] +#[cfg(all(target_arch = "x86", not(target_vendor = "apple"), not(feature = "mangled-names")))] pub unsafe extern "C" fn __rust_probestack_wrapper() { // This is the same as x86_64 above, only translated for 32-bit sizes. Note // that on Unix we're expected to restore everything as it was, this @@ -179,3 +180,73 @@ pub unsafe extern "C" fn __rust_probestack_wrapper() { " ::: "memory" : "volatile"); ::core::intrinsics::unreachable(); } + +#[naked] +#[no_mangle] +#[cfg(all(target_arch = "x86_64", target_vendor = "apple", not(feature = "mangled-names")))] +pub unsafe extern "C" fn __rust_probestack() { + // Same as above, but without the CFI tricks. The assembler for Apple + // devices doesn't support the directives we were using to define + // __rust_probestack. + asm!(" + pushq %rbp + movq %rsp, %rbp + + mov %rax,%r11 + + cmp $$0x1000,%r11 + jna 3f + 2: + sub $$0x1000,%rsp + test %rsp,8(%rsp) + sub $$0x1000,%r11 + cmp $$0x1000,%r11 + ja 2b + + 3: + sub %r11,%rsp + test %rsp,8(%rsp) + + add %rax,%rsp + + leave + ret + " ::: "memory" : "volatile"); + ::core::intrinsics::unreachable(); +} + +#[naked] +#[no_mangle] +#[cfg(all(target_arch = "x86", target_vendor = "apple", not(feature = "mangled-names")))] +pub unsafe extern "C" fn __rust_probestack() { + // This is the same as x86_64 above, only translated for 32-bit sizes. Note + // that on Unix we're expected to restore everything as it was, this + // function basically can't tamper with anything. + // + // The ABI here is the same as x86_64, except everything is 32-bits large. + asm!(" + push %ebp + mov %esp, %ebp + push %ecx + mov %eax,%ecx + + cmp $$0x1000,%ecx + jna 3f + 2: + sub $$0x1000,%esp + test %esp,8(%esp) + sub $$0x1000,%ecx + cmp $$0x1000,%ecx + ja 2b + + 3: + sub %ecx,%esp + test %esp,8(%esp) + + add %eax,%esp + pop %ecx + leave + ret + " ::: "memory" : "volatile"); + ::core::intrinsics::unreachable(); +}