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: Mon, 31 Oct 2011 12:15:39 +0100

Hi Arun,

>> 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.
> 
> bar+offset: call <foo>
> label1:       next_instruction
> 
> if you put a gdb breakpoint on label1: and examine the registers, they
> should match the dwarf_cursor (including rip, rbp and rsp) when
> dwarf_cursor.ip == label1. No state is in flux. Everything is precise
> at the instruction boundary.

I think we agree, just used different words.

> Now the commonly understood concept of CFA at this point in the
> execution is the value of %rsp when bar returns to its caller, whereas
> dwarf_cursor.cfa is essentially %rsp at label1. This is the
> discrepancy I'm trying to address.

Can you expand on this? I would entirely agree on resolving the discrepancy,
and I agree on your first sentence, and sort of on the second.  As far as I
understand our code, our .cfa really is the result of evaluating the DWARF
CFA expression for an IP address in foo(), and does conform to the usual
definition - but it's for foo() frame, not bar().

Indeed it will appear as if it was %rsp at label1, but if bar() isn't actually
calling foo() but gets there via say signal frame or one of the other unusual
cases, then we will basically have no idea of CFA - or for that matter %rsp -
for bar() until we actually perform the step (apply_reg_state) into it. Or at
least so I understand.

>> 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.
> 
> Internal state should point to the caller. Only CFA is lagging by one
> frame. This is addressed by apply_reg_state(). The first thing it does
> is recompute CFA, so the off-by-one issue is corrected and everything
> works magically.

I think we agree, and this is what I referred to as 'straddling' as before.
That is, the CFA is still that of callee frame, but register values (and
%rip) are the values of saved registers in the caller (and instruction after
call, respectively).

>> Were you thinking of some way of returning CFA info easily, by shifting the
>> internal state somehow by one stack frame?
> 
> I was thinking of shifting this computation:
> 
> apply_reg_state:
> 
> /* Evaluate the CFA first, because it may be referred to by other
>    expressions.  */
> 
> to the end of the function, instead of being at the beginning. But
> that won't work. The problem is: the CFA evaluation expression is
> computed by run_cfi_program() on caller's IP address range, not
> callee's. So the information needed to compute the CFA is not
> available until the next call to apply_reg_state.

Right, I think we agree.

> For now, I'd suggest that callers of libunwind compute the value of
> CFA by reading the value of stack pointer in the next outer frame.

Regards,
Lassi


reply via email to

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