libunwind-devel
[Top][All Lists]
Advanced

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

Re: [Libunwind-devel] local vars


From: Lassi Tuura
Subject: Re: [Libunwind-devel] local vars
Date: Sat, 29 Oct 2011 23:06:10 +0200

Hi,

>>> I can't think of anything obvious that'd break if we returned a
>>> different answer for UNW_X86_64_CFA. Let me think about this a bit
>>> more before attempting to implement something.
>> 
>> Hm, are you certain about this?
> 
> After this patch: [...] I get:
> 
> ip=400c59 sp=7fffffffd900 cfa=7fffffffd900
> ip=40195b sp=7fffffffda40 cfa=7fffffffda40 <-- bar()'s frame
> ip=40199b sp=7fffffffde30 cfa=7fffffffde30
> ip=332d01d8b4 sp=7fffffffdf00 cfa=7fffffffdf00
> ip=400b69 sp=7fffffffdfc0 cfa=7fffffffdfc0
> 
> note how (cfa == sp) is always true. Whereas DWARF defines cfa to be
> the sp *before* the call.

For cfa == sp, yes because we have this for x86_64 tdep_access_reg:

  case UNW_X86_64_CFA:
  case UNW_X86_64_RSP:
    if (write)
      return -UNW_EREADONLYREG;
    *valp = c->dwarf.cfa;
    return 0;

> gdb shows:
> 
> Breakpoint 1, bar (v=1) at Gtest-bt.c:139
> 139     {
> (gdb) info frame
> Stack level 0, frame at 0x7fffffffde30:
> rip = 0x400f50 in bar (Gtest-bt.c:139); saved rip 0x40199b
> called by frame at 0x7fffffffdf00
> source language c.
> Arglist at 0x7fffffffde20, args: v=1
> Locals at 0x7fffffffde20, Previous frame's sp is 0x7fffffffde30
> Saved registers:
> rip at 0x7fffffffde28

What I meant before about straddling is that, at least to my understanding,
the way unw_step / dwarf_step / apply_reg_state works is that we return info
for a frame *as seen from* the callee frame, at the point of call. We have
not actually stepped into the caller frame yet at that point.

So unw_getcontext() returns info on register state, including %rip, at the
point of call from do_backtrace() into unw_getcontext -- but internally in
the cursor object, the *frame* is that of getcontext. After one unw_step(),
the libunwind cursor is actually pointing to the frame of do_backtrace(),
while returning info about the point of call from bar().

It turns out this works for almost everything because you actually do see
%rip and register state as if it was for the frame caller frame. But it does
not work for returning the CFA. In fact we have no idea what the CFA is for
the caller frame, since we haven't yet looked up its DWARF info or executed
the CFI program.

So in a sense, the information for UNW_X86_64_CFA trails the other info by
one frame, because the internal state really still points to the callee.
Were you thinking of some way of returning CFA info easily, by shifting the
internal state somehow by one stack frame?

> I'm essentially thinking of changing the return value of unw_get_reg
> (&cursor, UNW_X86_64_CFA, &cfa), without touching any other
> implementation details. Does that affect the fast trace
> implementation?

I suppose it depends on how you're thinking of changing it. We do appear to
return DWARF idea of CFA as UNW_X86_64_CFA, with the caveat described above.

The fast trace mostly tracks just RSP/RBP movements, but that code is based
on tracking CFA deltas, and it needs to set things back right in the cursor
when it calls to unw_step() for slow steps.

Regards,
Lassi



reply via email to

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