[lldb-dev] Stack trace from within syscall on x86 Linux

Chaoren Lin chaorenl at google.com
Wed Mar 11 11:09:15 PDT 2015


The problem is not the __read function, but a subroutine that the __read
function calls. GDB shows it as __kernel_vsyscall, but LLDB doesn't have a
name for it, I don't think LLDB even considers it a function.

"image show-unwind -a $pc" in the subroutine shows no unwind data.

================================================================================
->  0xf7fdb420: pushl  %ecx
    0xf7fdb421: pushl  %edx
    0xf7fdb422: pushl  %ebp
    0xf7fdb423: movl   %esp, %ebp
(lldb) image show-unwind -a $pc
error: no unwind data found that matches '$pc'.
============================================================
====================
libc.so.6`__read:
->  0xf7d9cbec <+28>: calll  *%gs:0x10
    0xf7d9cbf3 <+35>: popl   %ebx
    0xf7d9cbf4 <+36>: cmpl   $0xfffff001, %eax
    0xf7d9cbf9 <+41>: jae    0xf7d9cc2d                ; <+93>
(lldb) si
th1/fr0 supplying caller's saved eip (8)'s location using assembly insn
profiling UnwindPlan
th1/fr0 supplying caller's register eip (8) from the stack, saved at CFA
plus offset -4 [saved at 0xffffda8c]
 th1/fr1 pc = 0xf7d31c73
th1/fr0 supplying caller's register ebp (6) from the live RegisterContext
at frame 0
 th1/fr1 fp = 0xf7cc1940
th1/fr0 supplying caller's saved esp (7)'s location using assembly insn
profiling UnwindPlan
th1/fr0 supplying caller's register esp (7), value is CFA plus offset 0
[value is 0xffffda90]
 th1/fr1 sp = 0xffffda90
 th1/fr1 with pc value of 0xf7d31c73, symbol name is '_IO_file_underflow'
 th1/fr1 active row: 0x00000000f7d31b67: CFA=esp+48 => ebx=[CFA-20]
ebp=[CFA-8] esi=[CFA-16] edi=[CFA-12] eip=[CFA-4]

th1/fr0 supplying caller's saved esp (7)'s location, cached
 th1/fr1 CFA is 0xffffdac0: Register esp (7) contents are 0xffffda90,
offset is 48
 th1/fr1 m_cfa = 0xffffdac0
 th1/fr1 initialized frame current pc is 0xf7d31c73 cfa is 0xffffdac0
th1/fr0 supplying caller's saved eip (8)'s location, cached
th1/fr0 using architectural default unwind method
th1/fr0 with pc value of 0xf7fdb420, no symbol/function name is known.
th1/fr0 0x00000000f7fdb420: CFA=ebp +8 => esp=CFA+0 ebp=[CFA-8] eip=[CFA-4]

th1/fr0 CFA is 0xf7cc1948: Register ebp (6) contents are 0xf7cc1940, offset
is 8
th1/fr0 initialized frame current pc is 0xf7fdb420 cfa is 0xf7cc1948 using
i386 default unwind plan UnwindPlan
Process 22545 stopped
* thread #1: tid = 22545, 0xf7fdb420, name = 'getline32', stop reason =
instruction step into
    frame #0: 0xf7fdb420
->  0xf7fdb420: pushl  %ecx
    0xf7fdb421: pushl  %edx
    0xf7fdb422: pushl  %ebp
    0xf7fdb423: movl   %esp, %ebp
(lldb) bt
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 0xf7cc1944]
 th1/fr1 pc = 0xf7cc1e08
th1/fr0 supplying caller's saved ebp (6)'s location using i386 default
unwind plan UnwindPlan
th1/fr0 supplying caller's register ebp (6) from the stack, saved at CFA
plus offset -8 [saved at 0xf7cc1940]
 th1/fr1 fp = 0xf7cc1940
th1/fr0 supplying caller's saved esp (7)'s location using i386 default
unwind plan UnwindPlan
th1/fr0 supplying caller's register esp (7), value is CFA plus offset 0
[value is 0xf7cc1948]
 th1/fr1 sp = 0xf7cc1948
 th1/fr1 using architectural default unwind method
 th1/fr1 had a pc of 0xf7cc1e08 which is not in executable memory but on
frame 1 -- allowing it once.
th1/fr0 supplying caller's saved ebp (6)'s location, cached
 th1/fr1 CFA is 0xf7cc1948: Register ebp (6) contents are 0xf7cc1940,
offset is 8
 th1/fr1 same CFA address as next frame, assuming the unwind is looping -
stopping
 Frame 1 invalid RegisterContext for this frame, stopping stack walk
th1 Unwind of this thread is complete.
* thread #1: tid = 22545, 0xf7fdb420, name = 'getline32', stop reason =
instruction step into
  * frame #0: 0xf7fdb420


On Tue, Mar 10, 2015 at 5:59 PM, Jason Molenda <jmolenda at apple.com> wrote:

> Hi guys, sorry for not seeing this thread yesterday.
>
> lldb should be able to handle this function, if and only if it knows the
> start address for the function/symbol.  The assembly instruction profiler
> can do the right thing with an instruction sequence like this.
>
> The first thing to do is
>
> (lldb) image show-unwind -a $pc
>
> when you're stopped in the function, or
>
> (lldb) image show-unwind -n __read
>
> This will dump the various UnwindPlans that lldb can use for this function.
>
> To see how the unwinder is actually walking the stack, before you step
> into __read, do
>
> (lldb) log enable lldb unwind
>
> then go into __read and try to backtrace a couple of frames.
>
> The output may not be easy to read - but send it along and I can interpret.
>
> J
>
> > On Mar 10, 2015, at 5:29 PM, Chaoren Lin <chaorenl at google.com> wrote:
> >
> > After some more debugging, I no longer think it's related to the
> syscall. The subroutine that invokes the syscall has a strange prologue
> (see below) which results in a return address stored at ebp+12 instead of
> ebp+4, which seems to be what LLDB uses to determine if a frame is valid.
> Is there some way we could not rely on the return address being at ebp+4?
> Maybe cache esp after every call instruction? Or keep looking up the stack
> for a valid return address? Or should we call this an intended behavior and
> use something other than fgets while waiting to be attached in
> TestHelloWorld.
> >
> > libc.so.6`__read:
> >
> > ->  0xf7d9cbec <+28>: calll  *%gs:0x10
> >
> > ->  0xf7fdb420: pushl  %ecx
> >     0xf7fdb421: pushl  %edx
> >     0xf7fdb422: pushl  %ebp
> >     0xf7fdb423: movl   %esp, %ebp
> >     0xf7fdb425: sysenter
> >
> > On Tue, Mar 10, 2015 at 10:26 AM, Pavel Labath <labath at google.com>
> wrote:
> >
> > On 10 March 2015 at 17:13, Chaoren Lin <chaorenl at google.com> wrote:
> > According to the Apple dudes in that conversation, UnwindLLDB and
> RegisterContextLLDB are what I should be looking at, correct?
> >
> > Yes, those are the two main classes. I would go about by going through
> RegisterContextLLDB::InitializeZerothFrame and try to figure out what
> UnwindPlan it ends up using. Then compare the unwind plan with the
> information obtained from gdb, for instance.
> >
> > I don't know where it gets its default unwind plan on i386 (maybe from
> nowhere?), but the reason the unwinding works (mostly) could be that lldb
> can read unwind plans from dwarf info which is generally embedded in the
> files.
> >
> > I suspect unwinding on i386 could be a bit tricky (especially in the
> proximity of assembly code like syscall internals) since the architecture
> has less registers, so people tend to reuse ebp for storing other stuff,
> which makes locating stuff on the stack harder.
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20150311/79b344ea/attachment.html>


More information about the lldb-dev mailing list