Issue 071227.1: Calculate value in DWARF expression

Author: John Bishop
Champion: Bishop/Blandy
Date submitted: 2007-12-27
Date revised:
Date closed:
Type: Extension
Status: Accepted with changes
DWARF Version: 4
Original proposal by Alexandre Oliva can be found at
http://dwarfstd.org/issues/071227.1..htmlold&type=closed

Revised 04/29/2008:
- Removed DW_OP_fetch as DW_OP_deref already exists
- Split DW_OP_deref into DW_OP_deref and DW_OP_deref_size (_multiple)
- Split DW_OP_value into DW_OP_value and DW_OP_value_size (_multiple)
- Specify that DW_OP_value* is "terminal" -- it does not push on the stack
- Reference conflict with DW_OP_implicit_value
- Do as changes to std.

Revised 19-Jun-2008:
- Removed _size operators.

Modifications to section 2.4, "DWARF Expressions"

Background:

The DWARF expression stack is an expression stack which runs a "program" 
given by a stack expression.  The stack elements are the size of an 
address in the debuggee, and so are either 32 or 64 bits long (in most 
cases).  The stack elements are untyped but are mostly treated as signed 
or unsigned integers.

The typical use of the stack is to compute the "location" (address) 
of a variable so that the debugger may fetch the value of the variable 
by reading the memory at that address in the debuggee.  The register 
name operators (DW_OP_reg0, etc.) are treated as though they were 
"addresses" of the registers.

Note that the stack can already compute numbers, e.g.

  DW_OP_lit1          Push 1, now top of stack

 - or -

  DW_OP_const4u 99
  DW_OP_const4u 1
  DW_OP_plus          push 99, push 1, add top two, get 100 on top of stack

Problem:

Some variables have predictable values but are not materialized in 
the address space of the program.  We are proposing a mechanism by 
which the compiler can tell the debugger what that predictable value 
is using the existing "location list" mechanism.

We therefore want a stack expression which means "the value at the 
top of the stack is the value we wanted, not the address of the 
value we wanted".  This new operator is DW_OP_value, the "voila`" operator.

To do more detailed accesses on the item or to construct an item larger than
a stack lement, you would use multiple DW_OP_value operations, applying a
DW_OP_piece or DW_OP_bit_piece to the result of the DW_OP_value as though
it were part of the target's memory.

Examples:

1.  DW_OP_lit1 
    DW_OP_value

       The result of this is the value 1.

2.  DW_OP_lit2
    DW_OP_value
    DW_OP_piece 4
    DW_OP_lit1
    DW_OP_value
    DW_OP_piece 4

       The result of this expression is an eight-byte block formed from
       the top of the stack and the item below it.  That value is
       the signed value 0x00020001 (or is it 0x00010002?).

3.  DW_OP_breg3 0
    DW_OP_value

       Register 3 holds the same value as is computed here,
       but the register is _not_ this value, e.g., modifying 
       the register should not change the value.  If we were 
       calculating the value of a variable in r3, we'd have
       used "DW_OP_reg3".

    NOTE: "reg" is a pseudo-address which is the 'address' of a register.
          "breg" is the value given by adding the contents of a register
          to a literal offset.

    NOTE: because "DW_OP_breg" exists, we don't need to ever use "DW_OP_reg"
          followed by "DW_OP_deref".

4.  DW_OP_breg4 0
    DW_OP_breg3 0
    DW_OP_plus
    DW_OP_value

       Add the contents of r4 and r3 to get the value.

5.  DW_OP_breg3 0
    DW_OP_value
    DW_OP_piece 4
    DW_OP_breg4 0
    DW_OP_value
    DW_OP_piece 4

        The value is 8 bytes long; the upper 4 are in r3 and the 
        lower 4 are in r4.

6.  DW_OP_breg10 5
    DW_OP_lit4
    DW_OP_mul
    DW_OP_value
    DW_OP_piece 2

        Two bytes of the value are computed by taking the contents
        of R10, adding 5 and then multiplying by 4, i.e.:

              4 * (5 + .r10)

7.  DW_OP_fbreg -16
    DW_OP_deref
    DW_OP_lit1
    DW_OP_plus
    DW_OP_value

        The value is always one more than the value of another
        variable which is at address '.fp - 16'.

8.  DW_OP_breg4 0
    DW_OP_breg3 0
    DW_OP_plus
    DW_OP_value
    DW_OP_piece 4
    DW_OP_breg5 0
    DW_OP_breg6 0
    DW_OP_plus
    DW_OP_value
    DW_OP_piece 4

       Add the contents of r4 and r3 to get the value of the
       lower 32 bits of the full value; add the contents of r5 
       and r6 to get the value of the upper 32 bits.

Parts to modify:

Section 2.4, these details

Section 2.5: 
  (add bracketed portion to text)

  ...of a dynamic string, [the desired value itself,] and so on.

Section 2.6.3

  (Add one operator)

  3. DW_OP_value

  The DW_OP_value operation specifies that the value of the DWARF expression is
  the value on the top of the stack.  It does not pop a value off the stack or
  push a value on the stack.

  Example:

    DW_OP_breg4 0
    DW_OP_breg3 0
    DW_OP_add
    DW_OP_value

       Add the contents of r4 and r3 to get the value.  

  This operator may be followed by DW_OP_piece and DW_OP_bit_piece, but it is 
  expected to be at the end or close to the end of an expression as it
  would otherwise be a no-op when used in the middle of an expression.  

  (This operator is similar to DW_OP_implicit_value, issue "070426.1".  The
  latter only permits the description of values known to be literals at
  compile-time; this proposal permits the description of values which
  have known expressions at compile-time.  It is more general; since 
  a sequence of DW_OP_constxx, DW_OP_value can replace every instance
  of DW_OP_implicit_value, this proposal also includes the removal of
  DW_OP_implicit value from the standard.)


  Example
    DW_OP_breg1 0
    DW_OP_breg2 0
    DW_OP_add
    DW_OP_value
    DW_OP_piece 4
    DW_OP_breg3 0
    DW_OP_breg4 0
    DW_OP_add
    DW_OP_value
    DW_OP_piece 4

       Add the contents of r1 and r2 to get the high-order four bytes 
       of the value.  Add together r3 and r4 to get the low-order four
       bytes of the value.

======

Accepted with two editorial changes:
  -- correct description of example 2 -- current text shows 32 bit values
     which should be 64 bit values.
  -- Note that DW_OP_value can only be followed by DW_OP_piece or 
     DW_OP_bit_piece.