[Dwarf-Discuss] DWARF piece questions

Andreas Arnez arnez at linux.vnet.ibm.com
Wed Jan 25 10:11:43 PST 2017


On Tue, Jan 24 2017, Andrew Cagney wrote:

> 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:

[...]

>>>> * 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."
>
> Right.

Right, and...?  Is it intentional that DW_OP_piece(n)" is not
necessarily equivalent to "DW_OP_bit_piece(8*n, 0)?

> 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). /

Do you mean that such an ABI would take a DW_OP_piece from a register
according to the "structure parameter passing" rule *whenever* the
composite location describes an object with structure type?  But this
would be wrong, wouldn't it?  For instance, modern compilers may
optimize a 'short' structure field into a register, then usually
aligning it towards the other end of the register instead.  How should a
DWARF consumer distinguish these cases?

Also, I suggest to avoid the terms "left" and "right", since I
encountered various occasions where they caused more confusion than they
helped.  And the term "most significant" can not generally be applied to
registers either, so in this case I'd prefer something like "located in
the lowest-addressed bytes of the register when stored in memory".

> (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)

And even if GCC emitted perfect DWARF code, current GDB could not handle
it correctly.  For instance, no ABI-dependent piece placement is
implemented in GDB yet, and the DW_OP_bit_piece offset is always
ignored.  I'm currently working on fixing all the DWARF piece related
bugs in GDB.

[...]

>>>> * 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 :-)

Good, I'd like to eliminate the "adjacent register" logic from GDB's
DWARF piece handling.

> 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
> ABIs.

Not sure.  GDB's current handling is quirky, however.  The above
probably implies some kind of padding logic, which is missing from
current GDB.  The "adjacent register" logic is used instead, so the
additional 4 bytes are taken from st1.

>>> 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.

Right, and I certainly don't expect DWARF to define that relationship.
Did you get that impression somewhere?

So what about the original question, whether "DW_OP_reg*" followed by
"DW_OP_piece(size of object type)" is always equivalent to omitting the
piece operation?  Yes or no?

Note that this question was originally triggered by a question from
Adrian Prantl regarding DW_OP_reg*:

  http://lists.dwarfstd.org/private.cgi/dwarf-discuss-dwarfstd.org/2016-March/004201.html

To me it seems that DWARF's definition of the placement of the object
addressed by DW_OP_reg* may be lacking.  Currently it just says: "The
object addressed is in register n", whereas the definition of
DW_OP_piece at least states that "the placement of the piece within that
register is defined by the ABI."  IMO, the amount of detail in these two
definitions should be similar, and it would also be helpful to indicate
their relationship, such as addressed by my question above.

--
Andreas



More information about the Dwarf-Discuss mailing list