Joakim <dl...@joakim.fea.st> writes:

> On Monday, 4 January 2016 at 09:26:39 UTC, Dan Olson wrote:
>> Joakim <dl...@joakim.fea.st> writes:
>
>> The bug is a bad stack pointer which blows up when the last unittest
>> returns.  This unittest has all the right conditions to generate
>> stack adjustments around some of the function calls that throw
>> exceptions. The exception landing pad does not fixup the stack
>> adjustment, thus a stack leak on each caught exception.  The
>> unittest function epilog restores the stack by adding a fixed offset
>> to match the prolog, so the stack pointer stays wrong when the saved
>> registers and return address are popped.
>>
>> Really looks like LLVM is not doing the right thing with landing
>> pads. In the meantime I patched LLVM to generate epilog that always
>> uses frame pointer to restore the stack pointer.  WatchOS requires a
>> frame pointer, so this isn't too bad.  Now all unittests pass at -O3
>> for watchOS.
>
> Could be the same issue for me, not sure.  If you put your fix online,
> I can try it and see.

It is this commit based on a 2 week old LLVM 3.8 trunk:

https://github.com/smolt/llvm/commit/91a4420615c6ec83b227b63d36054f12ccffb00f

A small change but took me a long time in debugger on an Apple Watch to
figure out.  Something the x86 simulator can't show.  It is tailored to
watchOS which uses thumb2 instructions.  watchOS always has a frame,
hasFP() is always true. You will want to add Android to the hasFP() or
disable frame pointer elimination some other way.  I noticed that
-disable-fp-elim for LDC with LLVM 3.7 and above is broken so can't use
that.

The pattern to look for if you have a suspect is this:

A function that throws an exception is codegened with stack adjustment
surrounding the call:

        sub     sp, #16
        str     r1, [sp]
        mov     r1, r2
        movs    r0, #66
        movw    r2, #2424
        blx     
__D3std9exception25__T7bailOutHTC9ExceptionZ7bailOutFNaNfAyakxAaZv
        add     sp, #16    <--- This adjustment is missed on exception

Epilog without hack (llvm 3.8 git 0838b1f Add iOS TLS support for WatchOS)
        itttt   ne
        addne.w sp, sp, #9984 <-- stack adjust matches prolog, but stack
                                                      is off by 16 bytes if 
above throws
        addne   sp, #48
        popne.w {r8, r10, r11}
        popne   {r4, r5, r6, r7, pc}

Epilog with hack (commit 91a4420)
        itttt   ne
        subne.w r4, r7, #24   <-- stack set from frame pointer (r7)
        movne   sp, r4
        popne.w {r8, r10, r11}
        popne   {r4, r5, r6, r7, pc}

-- 
Dan

Reply via email to