Issue 071227.1: Calculate value in DWARF expression
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.