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

Jason Molenda jmolenda at apple.com
Mon Jan 12 23:41:29 PST 2015


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
>>>> 
>>> 
>> 





More information about the lldb-dev mailing list