[lldb-dev] Unwinding with no symbols

Jason Molenda jason at molenda.com
Fri Apr 3 16:04:55 PDT 2015


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



More information about the lldb-dev mailing list