[lldb-dev] Unwinding with no symbols

Zachary Turner zturner at google.com
Fri Apr 3 17:23:18 PDT 2015


I'm wondering how it even made it to 0x1190a41. From the first bt command,
that address is higher up than main. The fact that it stops there when
stepping over something in main suggests that it actually got all the way
through the call to printf, then returned from main then stopped at the
return address of main. Does that seem like the expected behavior?
On Fri, Apr 3, 2015 at 4:04 PM Jason Molenda <jason at molenda.com> wrote:

> Yeah, this is fallout from a stack walk algorithm that uses the rule "if
> we don't know any better, assume the function saved the caller's ebp on the
> stack and keep walking via that".
>
> > On Apr 3, 2015, at 3:43 PM, Zachary Turner <zturner at google.com> wrote:
>
> > (lldb) bt
> > * thread #1: tid = 0x11fc, 0x011882be simple_step.exe`main(argc=1,
> argv=0x015e3be0) + 606 at simple_step.cpp:19, stop reason = breakpoint 1.3
> >   * frame #0: 0x011882be simple_step.exe`main(argc=1, argv=0x015e3be0) +
> 606 at simple_step.cpp:19
> >     frame #1: 0x01190a41 simple_step.exe
> >     frame #2: 0x75107c04 kernel32.dll`BaseThreadInitThunk + 36
> >     frame #3: 0x7774b54f ntdll.dll`RtlInitializeExceptionChain + 143
> >     frame #4: 0xffffffff
> > (lldb) thread step-over
> > (lldb) Process 10848 stopped
> > * thread #1: tid = 0x11fc, 0x01190a41 simple_step.exe, stop reason =
> step over
> >     frame #0: 0x01190a41 simple_step.exe
> > ->  0x1190a41: addl   $0xc, %esp
> >     0x1190a44: movl   %eax, %esi
> >     0x1190a46: movl   %esi, -0x24(%ebp)
> >     0x1190a49: testl  %ebx, %ebx
> > (lldb) bt
> > * thread #1: tid = 0x11fc, 0x01190a41 simple_step.exe, stop reason =
> step over
> >   * frame #0: 0x01190a41 simple_step.exe
> >     frame #1: 0x75107c04 kernel32.dll`BaseThreadInitThunk + 36
> >     frame #2: 0x7774b54f ntdll.dll`RtlInitializeExceptionChain + 143
> >     frame #3: 0xffffffff
>
>
>
> When we're stopped in 0x01190a41, lldb doesn't have any information about
> this function.  Are we at the first instruction?  Has the prologue
> completed?  Are we in the epilogue?  We have no way of knowing.  We have to
> make a guess, and the guess, the "Architectural Default Unwind Plan", says
> to assume we're in the middle of the function body and that the caller's
> ebp has been saved and that this function sets up & uses ebp too.
>
> I think in our previous discussions you argued that lldb should *know*
> that it just single instruction stepped into a new function.  If that
> knowledge could be transmitted down to the unwinder, we could use the ABI::CreateFunctionEntryUnwindPlan
> unwind plan instead of the ABI::CreateDefaultUnwindPlan.  The former
> describes how to unwind when we're sitting at the first instruction of a
> function.  lldb doesn't have any ability to do this today, though.
>
> Anyway, because we use the "arch default unwind plan" for a function that
> hasn't saved the caller's ebp and copied the stack pointer into ebp itself
> to indicate the start of its stack frame, ebp still has main()'s stack
> frame value.  So when the arch default unwind plan says "look at ebp to
> find the caller's pc address", we're essentially skipping over main().
>
> You can always spot an unwind algorithm that makes this assumption because
> they have the same "skip-one-frame" behavior when the 0th frame is unknown
> code and the unwinder skips the 1st frame.  It's a common behavior in
> sampling type programs.
>
> One example of where the unwinder is extra smart is when the pc value is
> 0.  When the program jumps through a null function pointer, we end up at
> address 0.  The simplistic behavior would be to use the arch default unwind
> plan which would skip the 1st frame -- the one that actually jumped through
> the null pointer.  Very unhelpful.  The unwinder has code specifically to
> spot a pc value of 0 for the 0th frame and uses the ABI::CreateFunctionEntryUnwindPlan
> unwindplan instead of the ABI::CreateDefaultUnwindPlan so we don't skip
> that critical frame #1.
>
> I know it's noisy but it is MUCH easier to inline the unwind logging in
> the console with the commands you're typing than to have it in a separate
> logfile.  The critical unwind failure is here:
>
> > th1/fr0 initialized frame current pc is 0x1190a41 cfa is 0x114fc04 using
> i386 default unwind plan UnwindPlan
> > th1/fr0 with pc value of 0x1190a41, no symbol/function name is known.
> > th1/fr0 0x0000000001190a41: CFA=ebp +8 => esp=CFA+0 ebp=[CFA-8]
> eip=[CFA-4]
> >
> > th1/fr0 CFA is 0x114fc04: Register ebp (6) contents are 0x114fbfc,
> offset is 8
> > th1/fr0 initialized frame current pc is 0x1190a41 cfa is 0x114fc04 using
> i386 default unwind plan UnwindPlan
> > th1/fr0 supplying caller's saved eip (8)'s location using i386 default
> unwind plan UnwindPlan
> > th1/fr0 supplying caller's register eip (8) from the stack, saved at CFA
> plus offset -4 [saved at 0x114fc00]
> >  th1/fr1 pc = 0x75107c04
> >  th1/fr1 with pc value of 0x75107c04, symbol name is
> 'BaseThreadInitThunk'
>
>
> We have a pc of 0x1190a41.  We fall back to using the i386 default unwind
> plan.  The unwind rule is "CFA=ebp +8 => esp=CFA+0 ebp=[CFA-8]
> eip=[CFA-4]". This says that we can find the caller's return address by
> dereferencing ebp+4 (the "Canonical Frame Address" is ebp+8 and the saved
> eip is at the CFA address - 4).  Notice how the CFA is set in terms of ebp
> but your printf() hasn't set up ebp yet.  That's because the unwinder is
> using the wrong unwind rule.
>
>
> A really helpful command with unwind questions is to do "image
> show-unwind" with -n or -a.  It shows all of the different unwind rules
> lldb knows about for that function.  I don't know if it works for a raw
> address like your printf() here; probably not.  But you can tell from the
> unwind log output that lldb used the arch default unwind plan and that's
> the same for all functions.
>
>
> J
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20150404/764c24e5/attachment.html>


More information about the lldb-dev mailing list