Hi,
I'm working on improvements for the DWARF information produced by GCC
for Ada, and I have hit the following issue:
In Ada, it is possible to define array types inside structures (that are
called records). The size of such array types can then depend on members
of such records. For instance:
type Array_Type is array (Integer range <>) of Integer;
type Record_Type (N : Integer) is record
A : Array_Type (1 .. N);
end record;
Here, A's type is a "subtype" of Array_Type. It is an array whose upper
bound is the special record member "N". I'm wondering how such bounds
should be translated into DW_AT_{lower,upper}_bound attributes. The
DWARFv4 specification (Appendix D, subsection 2.2 Ada Example) suggests
the following DIEs (I'm stripping a few attributes that are not relevant
for this issue):
1$: DW_TAG_structure_type
DW_AT_name("Record_Type")
2$: DW_TAG_member
DW_AT_name("N")
DW_AT_type(reference to Integer)
3$: DW_TAG_array_type
DW_AT_type(reference to Integer)
4$: DW_TAG_subrange_type
DW_AT_type(reference to Integer)
DW_AT_lower_bound(constant 1)
DW_AT_upper_bound(reference to member N at 2$)
5$: DW_TAG_member
DW_AT_name("A")
DW_AT_type(reference to array type at 4$)
With this debug info, the upper bound of "A" indeed completely mirrors
the value of "N". In GCC, however, computing the upper bound of "A" is
more subtle: it is internally represented as: max(0, <record>.N) so that
when "N" is negative, 0 is returned.
While it is straightforward to reference a DIE from the
DW_AT_upper_bound attribute, I struggle doing so inside a DWARF
expression, and I do need a DWARF expression to correctly describe the
computation of the upper bound. I guess I need an operation sequence
that looks like:
# Push N, then 0
??? Get the value of the "N" member;
DW_OP_lit0;
# Is N > 0?
DW_OP_over; DW_OP_over;
DW_OP_gt;
DW_OP_bra: 1;
# If not then return 0, else return N.
DW_OP_swap
DW_OP_drop
So the issue for me is to know what to put instead of the "???" part. It
looks like the DW_OP_push_object_address (defined in section 2.5.1.3
Stack Operations) was introduced specifically for this kind of
computation, but I'm not sure what it is supposed to mean in this
context. Indeed, this operation would appear as part of a DWARF
expression under a DW_TAG_subrange_type DIE, itself under a
DW_TAG_array_type DIE, itself under a DW_TAG_structure_type. So what
address would this operation push on top of the stack? The address of
the "A" member, or the address of the embedding record?
The offsets of discriminants (the special record members that can be
used to determine the size of regular record members) inside the record
are statically known, so getting the address of the embedding record
would be enough to be able to fetch the value of the discriminant. On
the other hand, getting the address of the "A" member would not be
sufficient: in more complex cases, the offset of the "A" member can
depend on discriminants!
I tried to look at the implementation of DW_OP_push_object_address in
GDB, but it looks like it's not implemented yet. What do you think about
its expected behavior? And if I cannot use this operation for such array
bound expressions, what should I use?
Thank you in advance for your answers. :-)
--
Pierre-Marie de Rodat
_______________________________________________
Dwarf-Discuss mailing list
Dwarf-Discuss@lists.dwarfstd.org
http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org