summary refs log tree commit diff
path: root/src/rt
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-12-11 16:32:36 -0800
committerBrian Anderson <banderson@mozilla.com>2011-12-11 16:32:36 -0800
commit7bc34f63d85ee7d351b90320239fc48860f01da2 (patch)
tree2dee0f9e23dba10fd64822868d517e6e66c570c4 /src/rt
parentb73caec3ced9e6588856f77f6a03319d3515f5ac (diff)
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.
Diffstat (limited to 'src/rt')
-rw-r--r--src/rt/arch/i386/morestack.S23
-rw-r--r--src/rt/arch/x86_64/morestack.S23
2 files changed, 35 insertions, 11 deletions
diff --git a/src/rt/arch/i386/morestack.S b/src/rt/arch/i386/morestack.S
index 7d1883833da..23aa36353a1 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 d5212004f10..fafedb54418 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.