Issue 030812.2: CFA Calculation

Author: David Anderson
Champion: Todd Allen
Date submitted: 2003-08-12
Date revised:
Date closed:
Type: Extension
Status: Accepted with modifications
DWARF Version: 3
By David Anderson. Any mistaken attributions or omissions
are mine, not the original contributors).

Starting on Aug 12, 2003 Andrew Cagney, Todd Allen, Ron Brender,
Chris Quenelle, Daniel Jacobowitz
and others pointed out issues in the CFI and solutions/workarounds
they have employed.

One of those issues is, as rephrased by David Anderson:
   If CFA is SP+offset and there is no 'frame pointer'
   stored on the stack, 
   then how do we recover the SP when unwinding?

   Daniel Jacobowitz suggested new 'register rules' of 
   val_expression(E) or val_cfa_offset(N) which would
   describe an actual value, not the address of a location
   where the value was stored. No specific means to create
   and recognize such rules was proposed.
   
   One possibility: a new call-frame-instruction changing
   the interpretation to a value (effectively a flag).
   Or new flag byte in the FDE flagging that offset
   and expression compute a value, not address-of-value. 
   Or a new call-frame-instruction changing interpretation
   of a given table-column to value (not
   reg+offset-as-address-of-value). 



Chris Quenelle:
>val_expression(E) or val_cfa_offset(N) which would
This seems like the right approach

>    One possibility: a new call-frame-instruction changing
>    the interpretation to a value (effectively a flag).

This approach seems more obfuscated.


PROPOSAL:

Sec 6.4.1.
Add a paragraphs giving new register rules, immediately
following the expression(E) rule description.

val_expression(E2) The previous value of this register is
                  the value produced by executing the DWARF
        expression E2.

val_offset(N)   The previous value of this register is the
        value CFA+N where CFA is the current CFA
        value and N is a signed offset.

------------------------------------------------------

Revised proposal:

But we need to expand the proposal into subsequent sections, so here are my
proposed additions and modification for that:

6.4.2 Call Frame Instructions

   ...

   20. DW_CFA_expression

      The DW_CFA_val_expression instruction takes two operands: an unsigned
      LEB128 value representing a register number, and a DW_FORM_block value
      representing a DWARF expression. The required action is to
      <changed text>
      change the rule for the register indicated by the register
      number to be an expression(E) rule where E is the DWARF
      expression.  That is, the DWARF expression computes the address
      in which the given register contents are found.
      </changed text>
      The value of the CFA is pushed on the DWARF evaluation stack
      prior to execution of the DWARF expression.

      ...

   ...

   24. DW_CFA_val_offset

      The DW_CFA_val_offset instruction takes two unsigned LEB128 operands
      representing a register number and a factored offset.  The required
      action is to change the rule for the register indicated by the register
      number to be a val_offset(N) rule with a value of (N = factored offset
      * data_alignment_factor).

   25. DW_CFA_val_offset_sf

      The DW_CFA_val_offset_sf instruction takes two operands: an unsigned
      LEB128 value representing a register number and a signed LEB128
      factored offset.  This instruction is identical to DW_CFA_val_offset
      except that the second operand is signed.

   26. DW_CFA_val_expression

      The DW_CFA_val_expression instruction takes two operands: an unsigned
      LEB128 value representing a register number, and a DW_FORM_block value
      representing a DWARF expression.  The required action is to change the
      rule for the register indicated by the register number to be a
      val_expression(E) rule where E is the DWARF expression.  That is, the
      DWARF expression computes the value of the given register.

      The value of the CFA is pushed on the DWARF evaluation stack prior to
      execution of the DWARF expression.

      The DW_OP_call2, DW_OP_call4, DW_OP_call_ref and
      DW_OP_push_object_address DWARF operators (see Section 2.4.1) cannot be
      used in such a DWARF expression.

[I'm proposing that the following text, which current is between points 20
and 21, be pushed to the end of section 6.4.2, since the instructions to
which it applies no longer are defined contiguously.]

   *DW_OP_call2, DW_OP_call4 and DW_OP_call_ref operators are not meaningful
   in a DW_CFA_def_cfa_expression, DW_CFA_expression, or
   DW_CFA_val_expression operand because there is no mapping from call frame
   information to any corresponding debugging compilation unit information,
   thus there is no way to interpret the call offset.

   DW_OP_push_object_address is also not meaningful in a
   DW_CFA_def_cfa_expression, DW_CFA_expression, or DW_CFA_val_expression
   operand because there is no object context to provide a value to push.*

7.23 Call Frame Information, Figure 36. Call frame instruction encodings

                            High 2  Low 6
   Instruction              Bits    Bits    Operand 1  Operand 2
   -----------------------  ------  ------  ---------  ---------
   DW_CFA_val_offset +      0       0x14    ULEB128    ULEB128
   DW_CFA_val_offset_sf +   0       0x15    ULEB128    SLEB128
   DW_CFA_val_expression +  0       0x16    ULEB128    BLOCK

   (+ means the double dagger that means New in DWARF V3)

Points of interest:

   1) Is there really any value to DW_CFA_val_offset_sf?  I couldn't think of
      any practical use, but I included it for completeness.
   2) The val_offset instructions all take factored offsets.  So, if the
      factor was -4, for instance, you would be unable to say that a register
      value was anything other than a multiple of 4 offset from the current
      CFA.  Does everyone think that's reasonable?  If not, the instructions
      can be redefined to use non-factored offsets (like DW_CFA_def_cfa
      already does).
   3) I proposed changing the text for DW_CFA_expression to clarify which
      rule it was using, because now there will be two rules that involve
      expressions, and to make its text similar to the text for other
      instructions which talk about specific rules from the list in 6.4.1.
   4) Do we wish to revisit issue 020902.1, since these new instructions
      would provide a general way of describe the stack pointer instead of
      relying on an architectural rule?  D.5 could be made to use these
      instructions, or it could be left as is, or we could simply briefly
      mention these instructions there.

-----------------------------------------------------

Modifications:
Paragraphs 21i & 25:  Should indicate "signed and factored".