Skip to content

Commit 7bc34f6

Browse files
committed
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.
1 parent b73caec commit 7bc34f6

File tree

2 files changed

+35
-11
lines changed

2 files changed

+35
-11
lines changed

src/rt/arch/i386/morestack.S

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,6 @@
4949
MORESTACK:
5050
#ifdef __linux__
5151
.cfi_startproc
52-
53-
// Some magic that explains to the unwinder the unusal nature
54-
// of this stack frame. Copied verbatim from libgcc, which
55-
// has comments explaining it.
56-
.cfi_offset 8, 8
57-
.cfi_escape 0x15, 4, 0x7d
5852
#endif
5953

6054
pushl %ebp
@@ -66,14 +60,29 @@ MORESTACK:
6660
#ifdef __linux__
6761
.cfi_def_cfa_register %ebp
6862
#endif
69-
63+
7064
// FIXME (1226): main is compiled with the split-stack prologue,
7165
// causing it to call __morestack, so we have to jump back out
7266
subl $28,%esp
7367
calll RUST_GET_TASK
7468
testl %eax,%eax
7569
jz .L$bail
7670

71+
// During unwinding we want to skip our caller.
72+
#ifdef __linux__
73+
// Don't understand this line. I think it means that
74+
// the next frame's pc is the return address of our caller.
75+
.cfi_offset 8, 8
76+
// The next frame's esp is stored at our CFA - 12
77+
// (by the code below)
78+
.cfi_offset %esp, -12
79+
#endif
80+
81+
// Save the the correct %esp value for our grandparent frame,
82+
// for the unwinder
83+
leal 20(%ebp), %eax
84+
movl %eax, -4(%ebp)
85+
7786
// The arguments to rust_new_stack2
7887
movl 40(%esp),%eax // Size of stack arguments
7988
movl %eax,20(%esp)

src/rt/arch/x86_64/morestack.S

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,20 @@ MORESTACK:
6565
.cfi_def_cfa_register %rbp
6666
#endif
6767

68+
// During unwinding we want to skip our caller since it's not
69+
// a complete frame and will make the unwinder sad
70+
#if defined(__linux__)
71+
// Don't understand this line
72+
.cfi_offset 16, 0
73+
// Tell the unwinding where to get the stack pointer for
74+
// our grandparent frame
75+
.cfi_offset %rsp, -24
76+
#endif
77+
78+
// Save the grandparent stack pointer for the unwinder
79+
leaq 16(%rbp), %rax
80+
pushq %rax
81+
6882
// FIXME: libgcc also saves rax. not sure if we need to
6983

7084
// Save argument registers
@@ -81,8 +95,6 @@ MORESTACK:
8195
movq %rbp, %rcx
8296
addq $24, %rcx // Base pointer, return address x2
8397

84-
pushq $0 // Alignment
85-
8698
pushq %r11 // Size of stack arguments
8799
pushq %rcx // Address of stack arguments
88100
pushq %r10 // The amount of stack needed
@@ -99,7 +111,7 @@ MORESTACK:
99111

100112
// Pop the new_stack_args struct
101113
popq %rax
102-
addq $32, %rsp
114+
addq $24, %rsp
103115

104116
// Pop the saved arguments
105117
popq %r9
@@ -108,7 +120,10 @@ MORESTACK:
108120
popq %rdx
109121
popq %rsi
110122
popq %rdi
111-
123+
124+
// Pop the unwinding %rsp
125+
addq $8, %rsp
126+
112127
movq 8(%rbp),%r10 // Grab the return pointer.
113128
incq %r10 // Skip past the `ret` in our parent frame
114129
movq %rax,%rsp // Switch to the new stack.

0 commit comments

Comments
 (0)