[lldb-dev] Problem unwinding from inside of a CRT function

Zachary Turner zturner at google.com
Thu Jan 15 16:18:26 PST 2015


Yuck :(  Sounds like it's going to be a lot of work to get this working
then.  We're working with the Microsoft ABI, not the Itanium ABI, so I'm
assuming that's why ABISysV_x86_64::CreateFunctionEntryUnwindPlan isn't
doing anything for me.  Presumably I need to implement an
ABIMicrosoft_x86_x64 plugin.

Which is unfortunate, because it seems to be needed even for basic stepping
to work, like step over.  Originally I was just trying to implement
stepping, and that's how I ran into this issue.  So that brings me to a
related question.  Why is step over as complicated as it is?  It seems to
me like step over can be implemented by disassembling 1 opcode, adding the
size of the opcode to the current pc, and having the ThreadPlan::ShouldStop
always return false unless the pc is equal to old_pc + size_of_opcode.

It currently has a lot of logic for comparing frames against each other and
things like that though.

On Thu Jan 15 2015 at 4:06:23 PM Jason Molenda <jmolenda at apple.com> wrote:

> lldb is stopped on the first instruction of a function (at address
> 0x12350a1).  But there's no symbol for this function -- lldb doesn't KNOW
> it's at the first instruction of a function.  It can't profile the assembly
> instructions of the function to figure out how the unwind instructions
> should work.  So lldb falls back to the "architecture default unwind plan",
> e.g. ABISysV_x86_64::CreateDefaultUnwindPlan(), which assumes that the
> way to find the caller's eip address is to dereference ebp.
>
> Basically, you need some source of unwind info for functions.  On Linux
> systems, this would be eh_frame instructions.  On Mac OS X, there's
> "compact unwind" info that does the same thing.  I'm sure Windows has
> something -- it's needed to do exception handling.
>
> If you don't have any source of unwind information, you need to have
> accurate function start addresses so lldb can look at the instruction
> stream and make up an unwind plan from those (v. UnwindAssembly-x86.cpp).
> But this means you need to know the start address of all functions in the
> file.  On Mac OS X we have a special little section (LC_FUNCTION_STARTS)
> that encodes the length of each function in the file--so even if the
> function names are stripped before shipping, we can find the start address
> of each function easily.  lldb adds these to the symbol table and makes up
> function names for them.
>
> If you have no compiler-generated unwind information (that lldb can parse)
> and you don't have start addresses for all functions in the file, things
> are going to work poorly.
>
>
> For what it's worth, when looking at unwind issues it's usually easiest to
> turn on the unwind logging.  "log enable lldb unwind".  That'll show what
> lldb was up to.
>
> Also, another ABI method is useful - see ABISysV_x86_64::
> CreateFunctionEntryUnwindPlan().  This is the UnwindPlan that lldb will
> use when it knows it is at the start of a function before any instructions
> have been executed.
>
> J
>
>
> > On Jan 15, 2015, at 3:56 PM, Zachary Turner <zturner at google.com> wrote:
> >
> > Having some trouble unwinding when I'm broken inside of a CRT function.
> Another caveat is that I don't have symbols for this CRT function.  So the
> problem could be anything from something I've done wrong on my side, to an
> issue when symbols aren't present, to something else.  Here is the source
> code of this program:
> >
> > #include <stdio.h>
> >
> > int main (void)
> > {
> >   printf("This is line 1\n");
> >   printf("This is line 2\n");
> >   printf("This is line 3\n");
> >   return 1;
> > }
> >
> > Here is the disassembly of main:
> >
> > (lldb) disassemble -n main -F intel
> >    0x1235040 <main>: push   ebp
> >    0x1235041 <main+1>: mov    ebp, esp
> >    0x1235043 <main+3>: sub    esp, 0x14
> >    0x1235046 <main+6>: lea    eax, [0x1230040]
> >    0x123504c <main+12>: mov    dword ptr [ebp - 0x4], 0x0
> >    0x1235053 <main+19>: mov    dword ptr [esp], eax
> >    0x1235056 <main+22>: call   0x12350a1
> >    0x123505b <main+27>: lea    ecx, [0x1230050]
> >    (snipped for brevity)
> >
> > (Using the argument to "call" as the breakpoint address)
> > (lldb) break set -a 0x12350a1
> > Breakpoint 3: address = 0x012350a1
> > (lldb) run
> > Process 17044 launching
> > (lldb) Process 17044 launched: 'd:\testexe\expr_test.exe' (i386)
> > (lldb) Process 17044 stopped
> > * thread #1: tid = 0x40ec, 0x012350a1 expr_test.exe, stop reason =
> breakpoint 3.1
> >     frame #0: 0x012350a1 expr_test.exe
> > -> 0x12350a1: pushl  $0xc
> >    0x12350a3: pushl  $0x1241000
> >    0x12350a8: calll  0x1235be0
> >    0x12350ad: xorl   %edi, %edi
> > (lldb) disassemble -b -F intel
> > -> 0x12350a1: 6a 0c           push   0xc
> >    0x12350a3: 68 00 10 24 01  push   0x1241000
> >    0x12350a8: e8 33 0b 00 00  call   0x1235be0
> >    0x12350ad: 33 ff           xor    edi, edi
> >    0x12350af: 89 7d e4        mov    dword ptr [ebp - 0x1c], edi
> >    0x12350b2: 33 c0           xor    eax, eax
> >    0x12350b4: 39 45 08        cmp    dword ptr [ebp + 0x8], eax
> >    0x12350b7: 0f 95 c0        setne  al
> >    0x12350ba: 85 c0           test   eax, eax
> >    0x12350bc: 75 15           jne    0x12350d3
> >
> > Here's my register values:
> > (lldb) register read
> > General Purpose Registers:
> >        eax = 0x01230040
> >        ebx = 0x00000000
> >        ecx = 0x00000001
> >        edx = 0x00000000
> >        edi = 0x00000000
> >        esi = 0x00000000
> >        ebp = 0x00EAF920
> >        esp = 0x00EAF908
> >        eip = 0x012350A1
> >     eflags = 0b00000000000000000000001000010110
> >
> > And using the value of esp to dump the stack (sorry, I don't know how to
> use the -f argument to format this more nicely),
> >
> > (lldb) memory read 0x00EAF908
> > 0x00eaf908: 5b 50 23 01 40 00 23 01 00 00 00 00 00 00 00 00
> [P#. at .#.........
> > 0x00eaf918: 28 f9 ea 00 00 00 00 00 68 f9 ea 00 4e 52 23 01
> (.......h...NR#.
> >
> > So the return address is 0x0123505b.  Cross-referencing this with the
> original disassembly of main(), it looks like this is the correct value.
> >
> > So it seems like the Unwinder has all the information it needs, but yet
> I'm still only getting 1 frame.  Any suggestions how to dig into this?
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20150116/7fc37d13/attachment.html>


More information about the lldb-dev mailing list