From 7bc34f63d85ee7d351b90320239fc48860f01da2 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 11 Dec 2011 16:32:36 -0800 Subject: [PATCH] rt: Write CFI instructions that (might) work on mac in __morestack The DW_CFA_val_offset_sf instruction doesn't seem to work on mac, even after implementing it in the llvm-mc assembler, so now I'm looking for a different way to communicate the stack pointer adjustment to the unwinder. --- src/rt/arch/i386/morestack.S | 23 ++++++++++++++++------- src/rt/arch/x86_64/morestack.S | 23 +++++++++++++++++++---- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/rt/arch/i386/morestack.S b/src/rt/arch/i386/morestack.S index 7d1883833da2..23aa36353a19 100644 --- a/src/rt/arch/i386/morestack.S +++ b/src/rt/arch/i386/morestack.S @@ -49,12 +49,6 @@ MORESTACK: #ifdef __linux__ .cfi_startproc - - // Some magic that explains to the unwinder the unusal nature - // of this stack frame. Copied verbatim from libgcc, which - // has comments explaining it. - .cfi_offset 8, 8 - .cfi_escape 0x15, 4, 0x7d #endif pushl %ebp @@ -66,7 +60,7 @@ MORESTACK: #ifdef __linux__ .cfi_def_cfa_register %ebp #endif - + // FIXME (1226): main is compiled with the split-stack prologue, // causing it to call __morestack, so we have to jump back out subl $28,%esp @@ -74,6 +68,21 @@ MORESTACK: testl %eax,%eax jz .L$bail + // During unwinding we want to skip our caller. +#ifdef __linux__ + // Don't understand this line. I think it means that + // the next frame's pc is the return address of our caller. + .cfi_offset 8, 8 + // The next frame's esp is stored at our CFA - 12 + // (by the code below) + .cfi_offset %esp, -12 +#endif + + // Save the the correct %esp value for our grandparent frame, + // for the unwinder + leal 20(%ebp), %eax + movl %eax, -4(%ebp) + // The arguments to rust_new_stack2 movl 40(%esp),%eax // Size of stack arguments movl %eax,20(%esp) diff --git a/src/rt/arch/x86_64/morestack.S b/src/rt/arch/x86_64/morestack.S index d5212004f100..fafedb54418d 100644 --- a/src/rt/arch/x86_64/morestack.S +++ b/src/rt/arch/x86_64/morestack.S @@ -65,6 +65,20 @@ MORESTACK: .cfi_def_cfa_register %rbp #endif + // During unwinding we want to skip our caller since it's not + // a complete frame and will make the unwinder sad +#if defined(__linux__) + // Don't understand this line + .cfi_offset 16, 0 + // Tell the unwinding where to get the stack pointer for + // our grandparent frame + .cfi_offset %rsp, -24 +#endif + + // Save the grandparent stack pointer for the unwinder + leaq 16(%rbp), %rax + pushq %rax + // FIXME: libgcc also saves rax. not sure if we need to // Save argument registers @@ -81,8 +95,6 @@ MORESTACK: movq %rbp, %rcx addq $24, %rcx // Base pointer, return address x2 - pushq $0 // Alignment - pushq %r11 // Size of stack arguments pushq %rcx // Address of stack arguments pushq %r10 // The amount of stack needed @@ -99,7 +111,7 @@ MORESTACK: // Pop the new_stack_args struct popq %rax - addq $32, %rsp + addq $24, %rsp // Pop the saved arguments popq %r9 @@ -108,7 +120,10 @@ MORESTACK: popq %rdx popq %rsi popq %rdi - + + // Pop the unwinding %rsp + addq $8, %rsp + movq 8(%rbp),%r10 // Grab the return pointer. incq %r10 // Skip past the `ret` in our parent frame movq %rax,%rsp // Switch to the new stack.