[Dwarf-Discuss] DWARF piece questions

Andrew Cagney andrew.cagney at gmail.com
Tue Jan 24 11:37:16 PST 2017

On 12 December 2016 at 09:28, Andreas Arnez <arnez at linux.vnet.ibm.com> wrote:
> On Fri, Dec 09 2016, Adrian Prantl wrote:
>> Here's my take on this.
> Thanks!
>>> On Dec 9, 2016, at 11:11 AM, Andreas Arnez <arnez at linux.vnet.ibm.com> wrote:
>>> Although I've already created public comments for (most of) this,
>>> Michael Eager suggested that I post my questions regarding DWARF pieces
>>> on this list (again).
>>> All of these questions are related to the definition of DW_OP_piece and
>>> DW_OP_bit_piece:
>>> * Is "DW_OP_piece(n)" equivalent to "DW_OP_bit_piece(8*n, 0)"?
>> I would think the answer to this is yes, and if it isn't I would
>> really like to see the counterexample added to the Appendix.
> Right, I think clarification would be appropriate either way.
> Does anybody vote for "no"?

>>> * What is the correct placement rule for register pieces?  ABI-defined
>>>  or lsb0-ordered?  If lsb0-ordered, how exactly is that order defined
>>>  for non-integer registers?
>> "If the location is a register, the offset is from the least
>> significant bit end of the register."
>> Does this text from the latest draft answer the question?
>> If not, can you give an example where it isn't?
> The definition of DW_OP_piece differs, though: "[...] the placement of
> the piece within that register is defined by the ABI."


For instance, a big-endian ABI (MIPS O32, N32, N64 all come to mind)
may specify that small structures are passed "left aligned" in one or
more registers (i.e., in the high bytes of the register).  This is so
that a word-sized load/store of the register puts the struct at the
correct address.

I'm suggesting non-normative text along the lines of:

/ For instance, so that structure variables passed by register can be
loaded and stored
using register-sized transfers, a big-endian ABI may specify that the
pieces of a structure are "left aligned" within a register (located in
the most significant bytes of the register). /

(for the record, the GCC MIPS compilers I looked at - up to 6.x - all
generated wrong debug info for this case - the never written to memory
structure was described as being in memory)

>>> * Shall DW_OP_bit_piece ignore the offset for stack- and implicit
>>>  values?
>> "If the location is any implicit value or stack value, the
>> DW_OP_bit_piece operation describes a sequence of bits using the least
>> significant bits of that value."
>> No.
> Really?  IMHO the wording implies that the least significant bit always
> belongs to the piece.
>>> * What is the "least significant bit" of an implicit value?  And is it
>>>  intentional that the placement rule differs between implicit- and
>>>  memory values?
>> I don't know.
>>> * Some DWARF producers describe a register pair just with a single
>>>  DW_OP_reg<n>.  Can a register piece reach into the next register like
>>>  that as well?
>> You mean for a pair of r1,r2 they would emit only DW_OP_reg1? I don't
>> think this use is supported by the DWARF specification.
> OK.  Are there other opinions?

STABS, and early DWARF emitters liked to do this.  For instance, a
64-bit value passed in two adjacent 32-bit registers would only have
the first (even) register specified and then rely on "magic".

DWARF introduced DW_OP_piece et.al. as a way to get away from this so
a modern ABI trying to recommend the old behaviour will likely get
laughed at :-)

BTW a variation of this is still standard.  For instance, something like:

     float f;  // DW_OP_reg st0

While st0 is 80-bit, f is 32-bit, and it is assumed that the consumer
performs an implicit conversion.

>>> * Is "DW_OP_reg*" followed by "DW_OP_piece(size of object type)" always
>>>  equivalent to omitting the piece operation?
>> If sizeof(obj) == sizeof(reg) it is obviously.
>> If sizeof(obj) > sizeof(reg) the expression is malformed because there
>> are undefined bits in the object that should have been represented
>> with an empty DW_OP_piece.
> GCC may describe a long double struct member on x86 as
>   DW_OP_regx: 33 (st0); DW_OP_piece: 16
> where st0 is only 10 bytes wide.  Is that invalid then?

While something like:
  DW_OP_reg st0; DW_OP_piece 12; DW_OP_piece 4;
might be less ambiguous and safer on a big-endian architecture, the
above does have a reasonable little-endian interpretation.

Since these existing operations are long standing these edge cases
will have already been defined (perhaps implicitly) by the existing

>> If sizeof(obj) < sizeof(reg) the expression is overspecified, but
>> still sound, so I would say yes.
> So you'd say the placement rules for DW_OP_reg* and DW_OP_piece shall be
> compatible, both defined by the ABI -- not necessarily lsb0-ordered?
> And the bytes referred to by a "DW_OP_reg*"-location may depend on the
> object's size, but not its type, right?
> Note that this wouldn't work well with cases like the "SPU preferred
> slots"; see https://sourceware.org/ml/gdb/2016-01/msg00013.html, section
> 2.2.

It is probably worth pointing out that DWARF is tied to an ABI and the
ABI is, in turn, tied to an underlying hardware architecture (UAE in
PowerPC speak).

For instance, 32-bit ELF x86 binary would be described using 32-bit
ELF x86 DWARF.  If that binary were to be run on a 64-bit machine say,
then the 64-bit hardware designer, ABI designer, 64-bit operating
system and DWARF consumer all get to figure out exactly what that
means and how it works.  For instance, it is the DWARF consumer et.al.
that get to figure out how to map the 32-bit DWARF specified "eax"
onto onto "rax"; not DWARF.


More information about the Dwarf-Discuss mailing list