arch/x86_64: hack to work around ld64 shortcomings on OS X.

fix #35, close #36
This commit is contained in:
whitequark 2016-09-01 02:04:35 +04:00 committed by edef
parent 49d1a24e8f
commit a1ea208652
4 changed files with 32 additions and 4 deletions

View File

@ -1,5 +1,8 @@
language: rust
rust: nightly
os:
- linux
- osx
sudo: false
install:
- .travis/docs/install

View File

@ -49,6 +49,7 @@ use stack::Stack;
pub struct StackPointer(*mut usize);
pub unsafe fn init(stack: &Stack, f: unsafe extern "C" fn(usize) -> !) -> StackPointer {
#[cfg(not(target_vendor = "apple"))]
#[naked]
unsafe extern "C" fn trampoline_1() {
asm!(
@ -77,6 +78,21 @@ pub unsafe fn init(stack: &Stack, f: unsafe extern "C" fn(usize) -> !) -> StackP
: : "s" (trampoline_2 as usize) : "memory" : "volatile")
}
#[cfg(target_vendor = "apple")]
#[naked]
unsafe extern "C" fn trampoline_1() {
asm!(
r#"
# Same as above; however, .local and .size are not supported in Mach-O.
__morestack:
.private_extern __morestack
.cfi_def_cfa %rbx, 0
.cfi_offset %rbp, -16
call ${0:c}
"#
: : "s" (trampoline_2 as usize) : "memory" : "volatile")
}
#[naked]
unsafe extern "C" fn trampoline_2() {
asm!(
@ -84,7 +100,16 @@ pub unsafe fn init(stack: &Stack, f: unsafe extern "C" fn(usize) -> !) -> StackP
# Set up the second part of our DWARF CFI.
# When unwinding the frame corresponding to this function, a DWARF unwinder
# will restore %rbx (and thus CFA of the first trampoline) from the stack slot.
.cfi_offset %rbx, 16
#
# The following is functionally equivalent to:
# .cfi_offset %rbx, 16
# however positive offsets in .cfi_offset translate to DW_CFA_offset_extended_sf,
# and ld64's CFI parser only supports regular DW_CFA_offset (which only supports
# negative offsets, with the sign being implicit), so to avoid crashing the linker
# on OS X, fold offset into DW_CFA_def_offset.
.cfi_def_cfa_offset 24
.cfi_offset %rip, -24
.cfi_offset %rbx, 0
# Call the provided function.
call *8(%rsp)
"#

View File

@ -4,7 +4,7 @@
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#![feature(asm, naked_functions)]
#![feature(asm, naked_functions, cfg_target_vendor)]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(test, feature(test, thread_local, const_fn))]
#![no_std]

View File

@ -17,13 +17,13 @@ use self::libc::MAP_FAILED;
const GUARD_PROT: c_int = libc::PROT_NONE;
const STACK_PROT: c_int = libc::PROT_READ
| libc::PROT_WRITE;
#[cfg(not(any(target_os = "freebsd", target_os = "dragonfly")))]
#[cfg(not(any(target_os = "freebsd", target_os = "dragonfly", target_vendor = "apple")))]
const STACK_FLAGS: c_int = libc::MAP_STACK
| libc::MAP_PRIVATE
| libc::MAP_ANON;
// workaround for http://lists.freebsd.org/pipermail/freebsd-bugs/2011-July/044840.html
// according to libgreen, DragonFlyBSD suffers from this too
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
#[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_vendor = "apple"))]
const STACK_FLAGS: c_int = libc::MAP_PRIVATE
| libc::MAP_ANON;