[lldb-dev] Stack unwinding fails on x86/x86_64

Mario Zechner badlogicgames at gmail.com
Tue Jan 13 10:42:40 PST 2015


Sounds great! We are currently in a hot phase regarding our product. May
take a bit until i get some time to test with the changes in trunk.

Thanks!
Mario
On Jan 13, 2015 8:55 AM, "Jason Molenda" <jmolenda at apple.com> wrote:

> NB I do know about one remaining small problem with this on your example
> program.  The eh_frame augmentation is doing the correct thing, e.g. image
> show-unwind says that the original eh_frame instructions were
>
> row[0]:    0: CFA=rsp +8 => rip=[rsp]
> row[1]:    1: CFA=rsp+16 => rbp=[rsp] rip=[rsp+8]
> row[2]:    4: CFA=rbp+16 => rbp=[rbp] rip=[rbp+8]
>
>
> & the augmented instructions identify the mid-function epilogue at offset
> 41, re-instate the unwind rules on offset 42, and then get the unwind rules
> correct for the final epilogue instruction at offset 68:
>
> row[0]:    0: CFA=rsp +8 => rip=[rsp]
> row[1]:    1: CFA=rsp+16 => rbp=[rsp] rip=[rsp+8]
> row[2]:    4: CFA=rbp+16 => rbp=[rbp] rip=[rbp+8]
> row[3]:   41: CFA=rsp +8 => rbp=[rsp-8] rip=[rsp]
> row[4]:   42: CFA=rbp+16 => rbp=[rbp] rip=[rbp+8]
> row[5]:   68: CFA=rsp +8 => rbp=[rsp-8] rip=[rsp]
>
>
> But the assembly language unwinder, which you wouldn't use here, is
> missing the final epilogue.  It gets
>
> row[0]:    0: CFA=rsp +8 => rsp=rsp+8 rip=[rsp]
> row[1]:    1: CFA=rsp+16 => rbp=[rsp] rsp=rsp+16 rip=[rsp+8]
> row[2]:    4: CFA=rbp+16 => rbp=[rbp] rsp=rbp+16 rip=[rbp+8]
> row[3]:   41: CFA=rsp +8 => rsp=rsp+8 rip=[rsp]
> row[4]:   42: CFA=rbp+16 => rbp=[rbp] rsp=rbp+16 rip=[rbp+8]
>
>
> I need to track that down still but it's time to go home.  For simple test
> programs I tried, it's doing the correct thing. But there's an off-by-one
> error with this particular function that I need to track down before this
> is complete.
>
>
> J
>
>
> > On Jan 12, 2015, at 11:41 PM, Jason Molenda <jmolenda at apple.com> wrote:
> >
> > Give top of tree a try if you're still doing codegen like this.  Let me
> know if it doesn't look correct.
> >
> >
> > Sending        source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
> > Transmitting file data .
> > Committed revision 225773.
> >
> >
> >
> >> On Jan 8, 2015, at 8:10 AM, Mario Zechner <badlogicgames at gmail.com>
> wrote:
> >>
> >> Hi,
> >>
> >> sorry for taking so long. You can find a binary at
> >> http://libgdx.badlogicgames.com/downloads/InvalidFrameTest.zip
> >>
> >> This is a debug build for Mac OS X 64-bit. You should be able to run
> >> it, the README.md file has a few notes about that in it. Let me know
> >> if i can help any other way.
> >>
> >> Thanks,
> >> Mario
> >>
> >> On Jan 7, 2015 2:55 AM, "Jason Molenda" <jmolenda at apple.com> wrote:
> >>>
> >>> Can you send me a binary with one of these mid-function epilogues in
> the middle?  I'm not going to run it.  (I mean, if you want to make a self
> contained binary that I *could* run, that'd be awesome but I can test it by
> static inspection by using 'image show-unwind' after loading the binary
> into an x86-64 debug session)  it'll be easier to add support for
> mid-function epilogues if I have an example of one without having to write
> it myself.
> >>>
> >>> J
> >>>
> >>>> On Jan 5, 2015, at 4:34 PM, Jason Molenda <jmolenda at apple.com> wrote:
> >>>>
> >>>> I should fix the x86 assembly unwinder, it's something I knew would
> fail eventually when lldb was used on a significantly different code
> generation style.  It's not terribly difficult - assembly profiler code
> needs to save the unwind state once the prologue has finished.  When it
> detects the start of the epilogue instruction sequence, it preserves the
> unwind state until the epilogue has finished and then re-installs it.
> >>>>
> >>>> If you can change your codegen to have a single return for
> i386/x86_64, that would definitely work.  But this is a limitation in the
> x86 unwinder right now - that's where the real fix should be done.
> >>>>
> >>>> J
> >>>>
> >>>>> On Jan 5, 2015, at 4:10 PM, Mario Zechner <badlogicgames at gmail.com>
> wrote:
> >>>>>
> >>>>> Hi Jason,
> >>>>>
> >>>>> thanks for the response. We temporarily 'fixed' it by disabling the
> eh_frame unwinder [1] in our LLDB fork. We did this after figuring out that
> the LLDB version shipped with XCode didn't exhibit the issue. We compared
> the diagnostic unwind info and found XCode's LLDB not using that unwinder
> plan. It's a nasty hack we'd like to get rid of.
> >>>>>
> >>>>> We also found that the latest trunk of LLDB has the same issue with
> 32-bit x86. Here's the 32-bit version of the failing method [2]. It also
> contains a mid-function epilogue, bumping esp instead of rsp.
> >>>>>
> >>>>> The mid-functiom epilogues are a result of translating JVM bytecode
> [3] straight to LLVM IR. The bytecode contains mid-function returns. I
> guess we could coalesce those into a single basic block just like Clang
> does, using a temporary to store the return value.
> >>>>>
> >>>>> Thanks!
> >>>>> Mario
> >>>>>
> >>>>> [1] https://gist.github.com/badlogic/f7d65aca25270ee3b93d
> >>>>> [2] https://gist.github.com/badlogic/da0c7a3de6ffa3446bba
> >>>>> [3] https://gist.github.com/badlogic/571fdcced98968e08499
> >>>>>
> >>>>> On Jan 6, 2015 12:41 AM, "Jason Molenda" <jmolenda at apple.com> wrote:
> >>>>> Hi Mario, sorry I missed this one over the holidays.
> >>>>>
> >>>>> The problem here is the
> '[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V' function.
> It has a mid-function epilogue which lldb can't handle today on x86_64.
> This is a common idiom on armv7/arm64 - I have experience with how to solve
> the problem there but I had never seen a compiler generate code like this
> on x86_64 so it wasn't handled there.
> >>>>>
> >>>>> In your example session, when you're stopped at 0x000000010014bb5f,
> lldb is no longer able to backtrace.  Looking at the disassembly, we see
> that 0x10014bb5f is just past a mid-function epilogue.  We'll need to
> update the x86_64 assembly unwinder to recognize the epilogue sequence and
> re-install the previous unwind state before the epilogue unwound it.
> >>>>>
> >>>>> 0x10014bb38
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V>: pushq
> %rbp
> >>>>> 0x10014bb39
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+1>: movq
>  %rsp, %rbp
> >>>>> 0x10014bb3c
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+4>: subq
>  $0x20, %rsp
> >>>>> 0x10014bb40
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+8>: movq
>  %rdi, -0x8(%rbp)
> >>>>> 0x10014bb44
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+12>: movq
>  -0x10000(%rsp), %rax
> >>>>> 0x10014bb4c
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+20>: movl
>  %esi, -0xc(%rbp)
> >>>>> 0x10014bb4f
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+23>: cmpl
>  $0x64, -0xc(%rbp)
> >>>>> 0x10014bb53
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+27>: movq
>  %rdi, -0x18(%rbp)
> >>>>> 0x10014bb57
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+31>: jle
> 0x10014bb5f               ;
> [J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V + 39 at
> InvalidFrame.java:13
> >>>>> 0x10014bb59
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+33>: addq
>  $0x20, %rsp
> >>>>> 0x10014bb5d
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+37>: popq
>  %rbp
> >>>>> 0x10014bb5e
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+38>: retq
> >>>>> 0x10014bb5f
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+39>: movl
>  -0xc(%rbp), %eax
> >>>>> 0x10014bb62
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+42>: addl
>  $0x1, %eax
> >>>>> 0x10014bb65
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+45>: movl
>  %eax, -0x10(%rbp)
> >>>>> 0x10014bb68
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+48>: movl
>  -0x10(%rbp), %esi
> >>>>> 0x10014bb6b
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+51>: movq
>  -0x18(%rbp), %rdi
> >>>>> 0x10014bb6f
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+55>: callq
> 0x10014bb38               ;
> [J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V at
> InvalidFrame.java:10
> >>>>> 0x10014bb74
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+60>: addq
>  $0x20, %rsp
> >>>>> 0x10014bb78
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+64>: popq
>  %rbp
> >>>>> 0x10014bb79
> <[J]com.robovm.debug.server.apps.InvalidFrame.testRecursion(I)V+65>: retq
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>> On Dec 23, 2014, at 6:59 AM, Mario Zechner <badlogicgames at gmail.com>
> wrote:
> >>>>>>
> >>>>>> Hi,
> >>>>>>
> >>>>>> i'm running into stack unwinding issues when trying to get a
> backtrace for a currently selected thread. You can see the output of
> diagnose-unwind here:
> https://gist.github.com/badlogic/99736e5c37f54ea08481
> >>>>>>
> >>>>>> The simple stack walking algorithm in diagnose-unwind succeeds in
> reconstructing the correct frames.
> >>>>>>
> >>>>>> Any idea what I could be doing wrong or how i could fix this issue?
> >>>>>>
> >>>>>> Thanks,
> >>>>>> Mario
> >>>>>> _______________________________________________
> >>>>>> lldb-dev mailing list
> >>>>>> lldb-dev at cs.uiuc.edu
> >>>>>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
> >>>>>
> >>>>
> >>>
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20150113/759c003b/attachment.html>


More information about the lldb-dev mailing list