libunwind-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Libunwind-devel] [PATCH 1/2] Restore the interpretation of the NULL


From: Lassi Tuura
Subject: Re: [Libunwind-devel] [PATCH 1/2] Restore the interpretation of the NULL %rbp location as end of frame chain.
Date: Tue, 18 Sep 2012 20:55:23 +0200

Hey,

>> src/dwarf/Gparser.c comment "DWARF spec says undefined return address
>> location means end of stack."
>>
> In fact, I was unable to find a justification for exactly the statement
> from the comment in the documentaion.

See http://www.dwarfstd.org/doc/DWARF4.pdf section 6.4.4 Call Frame
Calling Address:

"If a Return Address register is defined in the virtual unwind table,
and its rule is undefined (for
example, by DW_CFA_undefined), then there is no return address and no
call address, and the
virtual unwind of stack activations is complete"

And yes, null value vs. undefined location are not the same thing. I
changed the "null rbp location" check to "null rip location" in the
PLT fix 
(http://git.savannah.gnu.org/gitweb/?p=libunwind.git;a=commitdiff;h=f252f5ff4e51af90fd6629f122f72556db94ccb7)
though certainly won't claim to recall all the details :-)

> Which is not the same as setting the %rbp location to NULL. FreeBSD
> startup sequence ATM is to enter usermmode with zero %rbp, which is
> not compliant, but historically established.

I confirm Linux does/has done the same; and as you noted, it's
specified - see also line 83 in src/x86_64/Gstep.c.

It's not unusual the first non-thread frame in Linuxen also terminates
in the frame-based unwinder, with the null rbp check. I made the fast
trace unwinder handle frame-pointer-walked frames because a few very
prominent frames lack dwarf info - the first (non-thread) entry point
frame, PLT, etc.

> Looking at the unpatched Gstep.c, I see the following sequence
> of the events:
>
> 1. %rbp is zero, as read by DWARF_GET_LOC().
> 2. The rip_loc is set to DWARF_NULL_LOC, and then reassigned to cursor
>    dwarf.loc[RIP].
> 3. The check !DWARF_IS_NULL_LOC (c->dwarf.loc[RIP] returns false, which
>    causes assignment the c->dwarf.ip = 0.
> 4. The last non-return statement in unw_step() is executed, which verifies
>    that stepper has made a progress. It would not on the next step,
>    returning UNW_EBADFRAME.
>
> My patch explicitely handles the case of zero %ebp if dwarf unwinder
> already declained,

Thanks for this! Are we talking about this code in src/x86_64/Gstep.c?

 217       if (c->dwarf.ip == prev_ip && c->dwarf.cfa == prev_cfa)
 218         return -UNW_EBADFRAME;

In that case, any idea why the previous unw_step() didn't flag it as
the last frame and return zero? It seems it's stuck looping on the
same frame if that condition trips? The previous frame should have
triggered either code around line 83 (dwarf-based; or the end-of-stack
code from Gparser.c) or line 152 (frame-pointer based), and unw_step()
should have returned zero? Or did I misunderstand?

Regards,
Lassi



reply via email to

[Prev in Thread] Current Thread [Next in Thread]