[Dwarf-Discuss] DW_OP_regX vs. DW_OP_bregX 0

Ron Brender ron.brender at charter.net
Thu Feb 12 17:50:12 PST 2009


Roland McGrath wrote:
>> Furthermore, the proposed meaning of DW_OP_reg* is not precisely
>> analogous; the original meaning is in effect "push the non-memory-address
>> location of this register on the stack" 
> 
> I don't think it makes sense, so as to constitute support of any position,
> to describe the existing standard this way.  What the existing standard
> says explicitly is that DW_OP_reg* can never appear in an actual DWARF
> expression--the only place where a concept of "stack" exists.  To describe
> the specification this way makes inferences or implementation assumptions
> that are not indicated by the standard itself.
> 
> I can draw different inferences and implementation assumptions that make
> the other interpretation "natural".  Still, we are just playing semantics.
 >...

The DWARF committee does recognize that the existing text in Version 3 
of the Standard is confusing and not as clear as it should be. While you 
might make legalistic arguments about what the Version 3 text says or 
does not say, what you are hearing back from members of the committee is 
a clear statement that what you suggest is not consistent with what is 
intended.

The committee has already revised and restructured the presentation to 
distinguish what are now called DWARF expressions and DWARF location 
descriptions. In particular, the DW_OR_reg<n> operators are now clearly 
identified as DWARF location descriptions but not DWARF expressions.

Following is the current presentation as approved by the Committee for 
inclusion in the Version 4 document. This is still "in process" of 
course but hopefully you will agree that the context sensitive 
interpretation you suggest is not consistent with this revised presentation.

You can of course argue that the revised text is a mistake and should 
not be ultimately adopted. But, hopefully you will agree that is it is 
unambiguous in not admitting the interpretation you suggest.

Ron Brender

-----------------------------------------------------------------------
 From the DWARF V4 Draft of October 7, 2008:

2.5	DWARF Expressions
DWARF expressions describe how to compute a value or name a location 
during debugging of a program. They are expressed in terms of DWARF 
operations that operate on a stack of values.
All DWARF operations are encoded as a stream of opcodes that are each 
followed by zero or more literal operands. The number of operands is 
determined by the opcode.
In addition to the general operations that are defined here, additional 
operations which are specific to location descriptions are defined in 
Section2.6.
2.5.1	General Operations
Each general operation represents a postfix operation on a simple stack 
machine. Each element of the stack is the size of an address on the 
target machine. The value on the top of the stack after “executing” the 
DWARF expression is taken to be the result (the address of the object, 
the value of the array bound, the length of a dynamic string, the 
desired value itself, and so on).
2.5.1.1	Literal Encodings
The following operations all push a value onto the DWARF stack. If the 
value of a constant in one of these operations is larger than can be 
stored in a single stack element, the value is truncated to the element 
size and the low-order bits are pushed on the stack.
1.	DW_OP_lit0, DW_OP_lit1, ..., DW_OP_lit31
The DW_OP_litn operations encode the unsigned literal values from 0 
through 31, inclusive.
2.	DW_OP_addr
The DW_OP_addr operation has a single operand that encodes a machine 
address and whose size is the size of an address on the target machine.
3.	DW_OP_const1u
The single operand of the DW_OP_const1u operation provides a 1-byte 
unsigned integer constant.
4.	DW_OP_const1s
The single operand of the DW_OP_const1s operation provides a 1-byte 
signed integer constant.
5.	DW_OP_const2u
The single operand of the DW_OP_const2u operation provides a 2-byte 
unsigned integer constant.
6.	DW_OP_const2s
The single operand of the DW_OP_const2s operation provides a 2-byte 
signed integer constant.
7.	DW_OP_const4u
The single operand of the DW_OP_const4u operation provides a 4-byte 
unsigned integer constant.
8.	DW_OP_const4s
The single operand of the DW_OP_const4s operation provides a 4-byte 
signed integer constant.
9.	DW_OP_const8u
The single operand of the DW_OP_const8u operation provides an 8-byte 
unsigned integer constant.
10.	DW_OP_const8s
The single operand of the DW_OP_const8s operation provides an 8-byte 
signed integer constant.
11.	DW_OP_constu
The single operand of the DW_OP_constu operation provides an unsigned 
LEB128 integer constant.
12.	DW_OP_consts
The single operand of the DW_OP_consts operation provides a signed 
LEB128 integer constant.
2.5.1.2	Register Based Addressing
The following operations push a value onto the stack that is the result 
of adding the contents of a register with a given signed offset.
1.	DW_OP_fbreg
The DW_OP_fbreg operation provides a signed LEB128 offset from the 
address specified by the location description in the DW_AT_frame_base 
attribute of the current function. (This is typically a “stack pointer” 
register plus or minus some offset. On more sophisticated systems it 
might be a location list that adjusts the offset according to changes in 
the stack pointer as the PC changes.)
2.	DW_OP_breg0, DW_OP_breg1, ..., DW_OP_breg31
The single operand of the DW_OP_bregn operations provides a signed 
LEB128 offset from the specified register.
3.	DW_OP_bregx
The DW_OP_bregx operation has two operands: a register which is defined 
with an unsigned LEB128 number, followed by a signed LEB128 offset.
2.5.1.3	Stack Operations
The following operations manipulate the DWARF stack. Operations that 
index the stack assume that the top of the stack (most recently added 
entry) has index 0.
1.	DW_OP_dup
The DW_OP_dup operation duplicates the value at the top of the stack.
2.	DW_OP_drop
The DW_OP_drop operation pops the value at the top of the stack.
3.	DW_OP_pick
The single operand of the DW_OP_pick operation provides a 1-byte index. 
The copy of the stack entry with the specified index (0 through 255, 
inclusive) is pushed on the stack.
4.	DW_OP_over
The DW_OP_over operation duplicates the entry currently second in the 
stack at the top of the stack. This is equivalent to a DW_OP_pick 
operation, with index 1.
5.	DW_OP_swap
The DW_OP_swap operation swaps the top two stack entries. The entry at 
the top of the stack becomes the second stack entry, and the second 
entry becomes the top of the stack.
6.	DW_OP_rot
The DW_OP_rot operation rotates the first three stack entries. The entry 
at the top of the stack becomes the third stack entry, the second entry 
becomes the top of the stack, and the third entry becomes the second entry.
7.	DW_OP_deref
The DW_OP_deref operation pops the top stack entry and treats it as an 
address. The value retrieved from that address is pushed. The size of 
the data retrieved from the dereferenced address is the size of an 
address on the target machine.
8.	DW_OP_deref_size
The DW_OP_deref_size operation behaves like the DW_OP_deref operation: 
it pops the top stack entry and treats it as an address. The value 
retrieved from that address is pushed. In the DW_OP_deref_size 
operation, however, the size in bytes of the data retrieved from the 
dereferenced address is specified by the single operand. This operand is 
a 1-byte unsigned integral constant whose value may not be larger than 
the size of an address on the target machine. The data retrieved is zero 
extended to the size of an address on the target machine before being 
pushed on the expression stack.
9.	DW_OP_xderef
The DW_OP_xderef operation provides an extended dereference mechanism. 
The entry at the top of the stack is treated as an address. The second 
stack entry is treated as an “address space identifier” for those 
architectures that support multiple address spaces. The top two stack 
elements are popped, a data item is retrieved through an 
implementation-defined address calculation and pushed as the new stack 
top. The size of the data retrieved from the dereferenced address is the 
size of an address on the target machine.
10.	DW_OP_xderef_size
The DW_OP_xderef_size operation behaves like the DW_OP_xderef operation: 
the entry at the top of the stack is treated as an address. The second 
stack entry is treated as an “address space identifier” for those 
architectures that support multiple address spaces. The top two stack 
elements are popped, a data item is retrieved through an 
implementation-defined address calculation and pushed as the new stack 
top. In the DW_OP_xderef_size operation, however, the size in bytes of 
the data retrieved from the dereferenced address is specified by the 
single operand. This operand is a 1-byte unsigned integral constant 
whose value may not be larger than the size of an address on the target 
machine. The data retrieved is zero extended to the size of an address 
on the target machine before being pushed on the expression stack.
11.	DW_OP_push_object_address
The DW_OP_push_object_address operation pushes the address of the object 
currently being evaluated as part of evaluation of a user presented 
expression. This object may correspond to an independent variable 
described by its own debugging information entry or it may be a 
component of an array, structure, or class whose address has been 
dynamically determined by an earlier step during user expression evaluation.

This operator provides explicit functionality (especially for arrays 
involving descriptors) that is analogous to the implicit push of the 
base address of a structure prior to evaluation of a 
DW_AT_data_member_location to access a data member of a structure. For 
an example, see Appendix D.2.
12.	DW_OP_form_tls_address
The DW_OP_form_tls_address operation pops a value from the stack, 
translates it into an address in the current thread's thread-local 
storage block, and pushes the address. If the DWARF expression 
containing the DW_OP_form_tls_address operation belongs to the main 
executable's DWARF info, the operation uses the main executable's 
thread-local storage block; if the expression belongs to a shared 
library's DWARF info, then it uses that shared library's thread-local 
storage block.

Some implementations of C and C++ support a __thread storage class. 
Variables with this storage class have distinct values and addresses in 
distinct threads, much as automatic variables have distinct values and 
addresses in each function invocation. Typically, there is a single 
block of storage containing all __thread variables declared in the main 
executable, and a separate block for the variables declared in each 
dynamically loaded library. Computing the address of the appropriate 
block can be complex (in some cases, the compiler emits a function call 
to do it), and difficult to describe using ordinary DWARF location 
descriptions. DW_OP_form_tls_address leaves the computation to the consumer.
13.	DW_OP_call_frame_cfa
The DW_OP_call_frame_cfa operation pushes the value of the CFA, obtained 
from the Call Frame Information (see Section 6.4).

Although the value of DW_AT_frame_base can be computed using other DWARF 
expression operators, in some cases this would require an extensive 
location list because the values of the registers used in computing the 
CFA change during a subroutine. If the Call Frame Information is 
present, then it already encodes such changes, and it is space efficient 
to reference that.
2.5.1.4	Arithmetic and Logical Operations
The following provide arithmetic and logical operations. The arithmetic 
operations perform “addressing arithmetic,” that is, unsigned arithmetic 
that wraps on an address-sized boundary. The operations do not cause an 
exception on overflow.
1.	DW_OP_abs
The DW_OP_abs operation pops the top stack entry, interprets it as a 
signed value and pushes its absolute value. If the absolute value can 
not be represented, the result is undefined.
2.	DW_OP_and
The DW_OP_and operation pops the top two stack values, performs a 
bitwise and operation on the two, and pushes the result.
3.	DW_OP_div
The DW_OP_div operation pops the top two stack values, divides the 
former second entry by the former top of the stack using signed 
division, and pushes the result.
4.	DW_OP_minus
The DW_OP_minus operation pops the top two stack values, subtracts the 
former top of the stack from the former second entry, and pushes the result.
5.	DW_OP_mod
The DW_OP_mod operation pops the top two stack values and pushes the 
result of the calculation: former second stack entry modulo the former 
top of the stack.
6.	DW_OP_mul
The DW_OP_mul operation pops the top two stack entries, multiplies them 
together, and pushes the result.
7.	DW_OP_neg
The DW_OP_neg operation pops the top stack entry, and pushes its negation.
8.	DW_OP_not
The DW_OP_not operation pops the top stack entry, and pushes its bitwise 
complement.
9.	DW_OP_or
The DW_OP_or operation pops the top two stack entries, performs a 
bitwise or operation on the two, and pushes the result.
10.	DW_OP_plus
The DW_OP_plus operation pops the top two stack entries, adds them 
together, and pushes the result.
11.	DW_OP_plus_uconst
The DW_OP_plus_uconst operation pops the top stack entry, adds it to the 
unsigned LEB128 constant operand and pushes the result.

This operation is supplied specifically to be able to encode more field 
offsets in two bytes than can be done with “DW_OP_litn DW_OP_plus”.
12.	DW_OP_shl
The DW_OP_shl operation pops the top two stack entries, shifts the 
former second entry left (filling with zero bits) by the number of bits 
specified by the former top of the stack, and pushes the result.
13.	DW_OP_shr
The DW_OP_shr operation pops the top two stack entries, shifts the 
former second entry right logically (filling with zero bits) by the 
number of bits specified by the former top of the stack, and pushes the 
result.
14.	DW_OP_shra
The DW_OP_shra operation pops the top two stack entries, shifts the 
former second entry right arithmetically (divide the magnitude by 2, 
keep the same sign for the result) by the number of bits specified by 
the former top of the stack, and pushes the result.
15.	DW_OP_xor
The DW_OP_xor operation pops the top two stack entries, performs the 
bitwise exclusive-or operation on the two, and pushes the result.
2.5.1.5	Control Flow Operations
The following operations provide simple control of the flow of a DWARF 
expression.
1.	DW_OP_le, DW_OP_ge, DW_OP_eq, DW_OP_lt, DW_OP_gt, DW_OP_ne
The six relational operators each:
•	pop the top two stack values,
•	compare the operands:
      <former second entry> <relational operator> <former top entry>
•	push the constant value 1 onto the stack if the result of the 
operation is true or the constant value 0 if the result of the operation 
is false.
The comparisons are done as signed operations. The six operators are 
DW_OP_le (less than or equal to), DW_OP_ge (greater than or equal to), 
DW_OP_eq (equal to), DW_OP_lt (less than), DW_OP_gt (greater than) and 
DW_OP_ne (not equal to).
2.	DW_OP_skip
DW_OP_skip is an unconditional branch. Its single operand is a 2-byte 
signed integer constant. The 2-byte constant is the number of bytes of 
the DWARF expression to skip forward or backward from the current 
operation, beginning after the 2-byte constant.
3.	DW_OP_bra
DW_OP_bra is a conditional branch. Its single operand is a 2-byte signed 
integer constant. This operation pops the top of stack. If the value 
popped is not the constant 0, the 2-byte constant operand is the number 
of bytes of the DWARF expression to skip forward or backward from the 
current operation, beginning after the 2-byte constant.
4.	DW_OP_call2, DW_OP_call4, DW_OP_call_ref
DW_OP_call2, DW_OP_call4, and DW_OP_call_ref perform subroutine calls 
during evaluation of a DWARF expression. For DW_OP_call2 and 
DW_OP_call4, the operand is the 2- or 4-byte unsigned offset, 
respectively, of a debugging information entry in the current 
compilation unit. The DW_OP_call_ref operator has a single operand. In 
the 32-bit DWARF format, the operand is a 4-byte unsigned value; in the 
64-bit DWARF format, it is an 8-byte unsigned value (see Section 7.4). 
The operand is used as the offset of a debugging information entry in a 
.debug_info section which may be contained in a shared object for 
executable other than that containing the operator. For references from 
one shared object or executable to another, the relocation must be 
performed by the consumer.

Operand interpretation of DW_OP_call2, DW_OP_call4 and DW_OP_call_ref is 
exactly like that for DW_FORM_ref2, DW_FORM_ref4 and DW_FORM_ref_addr, 
respectively (see Section 7.5.4).

These operations transfer control of DWARF expression evaluation to the 
DW_AT_location attribute of the referenced debugging information entry. 
If there is no such attribute, then there is no effect. Execution of the 
DWARF expression of a DW_AT_location attribute may add to and/or remove 
from values on the stack. Execution returns to the point following the 
call when the end of the attribute is reached. Values on the stack at 
the time of the call may be used as parameters by the called expression 
and values left on the stack by the called expression may be used as 
return values by prior agreement between the calling and called expressions.
2.5.1.6	Special Operations
There is one special operation currently defined:
1.	DW_OP_nop
The DW_OP_nop operation is a place holder. It has no effect on the 
location stack or any of its values.
2.5.2	Example Stack Operations
The stack operations defined in Section 2.5.1.3 are fairly conventional, 
but the following examples illustrate their behavior graphically.
  Before	        Operation        After

0     17       DW_OP_dup        0     17
1     29                        1     17
2   1000                        2     29
                                 3   1000

0     17       DW_OP_drop       0     29
1     29                        1   1000
2   1000

0     17       DW_OP_pick 2     0   1000
1     29                        1     17
2   1000                        2     29
                                 3   1000

0     17       DW_OP_over       0     29
1     29                        1     17
2   1000                        2     29
                                 3   1000

0     17       DW_OP_swap       0     29
1     29                        1     17
2   1000                        2   1000

0     17       DW_OP_rot        0     29
1     29                        1   1000
2   1000                        2     17

2.6	Location Descriptions
Debugging information must provide consumers a way to find the location 
of program variables, determine the bounds of dynamic arrays and 
strings, and possibly to find the base address of a subroutine’s stack 
frame or the return address of a subroutine. Furthermore, to meet the 
needs of recent computer architectures and optimization techniques, 
debugging information must be able to describe the location of an object 
whose location changes over the object’s lifetime.
  Information about the location of program objects is provided by 
location descriptions. Location descriptions can be either of two forms:
1.	Single location descriptions, which are a language independent 
representation of addressing rules of arbitrary complexity built from 
DWARF expressions and/or other DWARF operations specific to describing 
locations. They are sufficient for describing the location of any object 
as long as its lifetime is either static or the same as the lexical 
block that owns it, and it does not move throughout its lifetime.

Single location descriptions are of two kinds:
a.	Simple location descriptions, which describe the location of one 
contiguous piece (usually all) of an object. Simple location 
descriptions may describe a location in addressable memory, in a 
register, or the lack of a location (with or without a known value).
b.	Composite location descriptions, which describe an object in terms of 
pieces each of which may be contained in part of a register or stored in 
more than one location.
2.	Location lists, which are used to describe objects that have a 
limited lifetime or change their location throughout their lifetime. 
Location lists are more completely described below.
2.6.1	The two forms are distinguished in a context sensitive manner. As 
the value of an attribute, a location description is encoded using class 
exprloc and a location list is encoded using class loclistptr (which 
serves as an offset into a separate location list table). Single 
Location Descriptions
A single location description is either:
1.	A simple location description, representing an object which exists in 
one contiguous piece at the given location, or
2.	A composite location description consisting of one or more simple 
location descriptions, each of which is followed by one composition 
operation. Each simple location description describes the location of 
one piece of the object; each composition operation describes which part 
of the object is located there. Each simple location description that is 
a DWARF expression is evaluated independently of any others (as though 
on its own separate stack, if any).
2.6.1.1	Simple Location Descriptions
A simple location description consists of one contiguous piece or all of 
an object or value.
2.6.1.1.1	Memory Location Descriptions
A memory location description consists of a non-empty DWARF expression 
(see Section 2.5), whose value is the address of a piece or all of an 
object or other entity in memory.
2.6.1.1.2	Register Location Descriptions
A register location description consists of a register name operation, 
appearing alone as a single opcode. It represents a piece or all of an 
object located in a given register.
The following DWARF operations can be used to name a register.
Note that the register number represents a DWARF specific mapping of 
numbers onto the actual registers of a given architecture. The mapping 
should be chosen to gain optimal density and should be shared by all 
users of a given architecture. It is recommended that this mapping be 
defined by the ABI authoring committee for each architecture.
1.	DW_OP_reg0, DW_OP_reg1, ..., DW_OP_reg31
The DW_OP_regn operations encode the names of up to 32 registers, 
numbered from 0 through 31, inclusive. The object addressed is in 
register n.
2.	DW_OP_regx
The DW_OP_regx operation has a single unsigned LEB128 literal operand 
that encodes the name of a register.
2.6.1.1.3	Implicit Location Descriptions
An implicit location description consists of an implicit value 
operation, appearing alone as a single opcode. It represents a piece or 
all of an object which has no actual location but whose contents is 
nonetheless known.
The flowing DWARF operations may be used to specify a value that has no 
location in the program but is a known constant or is computed from 
other location and values in the program.
1.	DW_OP_implicit_value
The DW_OP_implicit_value operation has two operands: an unsigned LEB128 
length, followed by a block representing the value in the memory 
representation of the target machine. The length operand gives the 
length in bytes of the block that follows.

This operation should be used only in location lists for ranges where 
the value of an object does not exist in memory or a register, but whose 
value is a known constant.
2.	DW_OP_stack_value
The DW_OP_stack_value operation specifies that the object does not exist 
in memory but its value is nonetheless known and is at the top of the 
DWARF expression stack.

This operation may only be followed by DW_OP_piece or DW_OP_bit_piece.
2.6.1.1.4	Empty Location Descriptions
An empty location description consists of a DWARF expression containing 
no operations. It represents a piece or all of an object that is present 
in the source but not in the object code (perhaps due to optimization).
2.6.2	Composite Location Descriptions
A composite location description describes an object or value which may 
be contained in part of a register or stored in more than one location. 
Each piece is described by a composition operation, which does not 
compute a value nor store any result on the DWARF stack. There may be 
one or more composition  operations in a single composite location 
description. A series of such operations describes the parts of a value 
in memory address order.
Each composition operation is immediately preceeded by a simple location 
description which describes the location where part of the resultant 
value is contained.
1.	DW_OP_piece
The DW_OP_piece operation takes a single operand, which is an unsigned 
LEB128 number. The number describes the size in bytes of the piece of 
the object referenced by the preceding simple location description. If 
the piece is located in a register, but does not occupy the entire 
register, the placement of the piece within that register is defined by 
the ABI.
Many compilers store a single variable in sets of registers, or store a 
variable partially in memory and partially in registers. DW_OP_piece 
provides a way of describing how large a part of a variable a particular 
DWARF location description refers to.
2.	DW_OP_bit_piece
The DW_OP_bit_piece operation takes two operands. The first is an 
unsigned LEB128 number that gives the size in bits of the piece. The 
second is an unsigned LEB128 number that gives the offset in bits from 
the location defined by the preceding DWARF location description.

Interpretation of the offset depends on the kind of location 
description. If the location description is empty, the offset doesn’t 
matter and the DW_OP_bit_piece operation describes a piece consisting of 
the given number of bits whose values are undefined. If the location is 
a register, the offset is from the least significant bit end of the 
register. If the location is a memory address, the DW_OP_bit_piece 
operation describes a sequence of bits relative to the location whose 
address is on the top of the DWARF stack using the bit numbering and 
direction conventions that are appropriate to the current language on 
the target system.
DW_OP_bit_piece is used instead of DW_OP_piece when the piece to be 
assembled into a value or assigned to is not byte-sized or is not at the 
start of a register or addressable unit of memory.

2.6.3	Example Location Descriptions
The addressing expression represented by a location description, if 
evaluated, generates the runtime location of the value of a symbol.
Here are some examples of how DWARF operations are used to form location 
descriptions:
DW_OP_reg3
The value is in register 3.

DW_OP_regx 54
The value is in register 54.

DW_OP_addr 0x80d0045c
The value of a static variable is at machine address 0x80d0045c.

DW_OP_breg11 44
Add 44 to the value in register 11 to get the address of an automatic 
variable instance.

DW_OP_fbreg -50
Given an DW_AT_frame_base value of “DW_OP_breg31 64,” this example 
computes the address of a local variable that is -50 bytes from a 
logical frame pointer that is computed by adding 64 to the current stack 
pointer (register 31).

DW_OP_bregx 54 32 DW_OP_deref
A call-by-reference parameter whose address is in the word 32 bytes from 
where register 54 points.

DW_OP_plus_uconst 4
A structure member is four bytes from the start of the structure 
instance. The base address is assumed to be already on the stack.

DW_OP_reg3 DW_OP_piece 4 DW_OP_reg10 DW_OP_piece 2
A variable whose first four bytes reside in register 3 and whose next 
two bytes reside in register 10.

DW_OP_reg0 DW_OP_piece 4 DW_OP_piece 4 DW_OP_fbreg -12 DW_OP_piece 4
A twelve byte value whose first four bytes reside in register zero, 
whose middle four bytes are unavailable (perhaps due to optimization), 
and whose last four bytes are in memory, 12 bytes before the frame base.

DW_OP_breg1 0 DW_OP_breg2 0 DW_OP_add DW_OP_stack_value
Add the contents of r1 and r2 to compute a value. This value is the 
“contents” of an otherwise anonymous location.

DW_OP_lit1 DW_OP_stack_value DW_OP_piece 4
DW_OP_breg3 0 DW_OP_breg4 0 DW_OP_add DW_OP_stack_value DW_OP_piece 4
The object value is found in an anonymous (virtual) location whose value 
consists of two parts, given in memory address order: the 4 byte value 1 
followed by the four byte value computed from the sum of the contents of 
r3 and r4.




More information about the Dwarf-Discuss mailing list