[PATCH 3/4] gdb, typeprint: fix pointer/reference typeprint for icc/ifort

Simon Marchi simark@simark.ca
Tue Sep 27 12:48:10 GMT 2022

> The key difference here is that the DW_TAG_reference_type is a "standalone" type and there is always an object or a member (a physical location description) behind it while the DW_TAG_subrange_type is a by definition tied to a "standalone" array types. Unfortunately, it is not really meaningful to have an object of a DW_TAG_subrange_type so the type is more there to allow factorizing of the debug information.
> In the case of DW_TAG_reference_type, there is always an object that is the reference to something and if you dereference it, you get another object that the original object referenced, which is a very different case then the DW_TAG_subrange_type and the array type that references it.
> That being said, I don't believe that there is anywhere in DWARF stating that if there is an actual object of a DW_TAG_subrange_type type that the DW_OP_push_object_address operation (in any of the attributes of that type) should not use it, it just that the way how this type is defined doesn't really allow you to have a separate object of that type.

Well, you can have a standaline DW_TAG_subrange_type object, in
languages where you can define types to be subranges of other types.  I
just tried this Ada example:


And I got this, a variable with the subrange as its type:

0x00001a08:   DW_TAG_subprogram
                DW_AT_name [DW_FORM_strp]       ("greet")

0x00001a63:     DW_TAG_subrange_type
                  DW_AT_lower_bound [DW_FORM_data1]     (0x05)
                  DW_AT_upper_bound [DW_FORM_data1]     (0x06)
                  DW_AT_name [DW_FORM_strp]     ("greet__weekend_days")
                  DW_AT_type [DW_FORM_ref4]     (0x00001a2a "greet__days")

0x00001a7b:     DW_TAG_variable
                  DW_AT_name [DW_FORM_string]   ("s")
                  DW_AT_type [DW_FORM_ref4]     (0x00001a63 "greet__weekend_days")
                  DW_AT_location [DW_FORM_exprloc]      (DW_OP_fbreg -125)

> At the end of the day, the definition of DW_OP_push_object_address operation just states that the operation pushes the address of the object currently being evaluated, It even states that it could be a component of an object, but it still has to be something tangible (a real location).

I think that the confusion comes from the fact that DW_TAG_subrange_type
can serve two different and unrelated purposes.  One as a standard
standalone type, as shown above.  And two, as a direct child of a
DW_TAG_array_type, used to express the bounds.  Section 5.5 - Array Type
Entries says:

    Each array dimension is described by a debugging information entry
    with either the tag DW_TAG_subrange_type or the tag
    DW_TAG_enumeration_type. These entries are children of the array
    type entry and are ordered to reflect the appearance of the
    dimensions in the source program (that is, leftmost dimension first,
    next to leftmost second, and so on).

My interpretation of this text is that it describes that second special
use case where DW_TAG_subrange_type describes the bounds of the array,
but does not represent a concrete object itself, as it would with its
first purpose.  As Zoran said, maybe this helped "factorize" the debug
information and make the DWARF committee write less text, but I think it
also adds confusion.  I think it should be interpreted as if the
DW_TAG_array_type had the DW_AT_{lower,upper}_bound attributes directly.
I think this is what is intended by the standard, looking at the D.2.1
example.  The comments on the DW_AT_{lower,upper}_bound expressions show
that they consider DW_OP_push_object_address to have pushed the array's

That said, assuming that this is indeed "broken" DWARF, icc/ifort
produce what they produce, and I am open to make GDB handle it.  We work
around broken DWARF all the time for different compilers.  However, the
commit message would need to explain this, the code should make it clear
that this is a workaround for a specific form of DWARF emitted by
icc/ifort, and ideally gated behind a compiler check.  This way, in 20
years, when we decide we no longer want to support 20 year old hacks,
it's easy to identify and remove them.  It would also be good to have a
gdb.dwarf2 test case for this, explaining that "this is not really valid
DWARF but we want to support it anyway".


More information about the Gdb-patches mailing list