[Dwarf-Discuss] About self-referencial sized types

Pierre-Marie de Rodat derodat@adacore.com
Thu May 15 16:30:20 GMT 2014


On 05/15/2014 04:22 PM, Agovic, Sanimir wrote:
> For this particular case you might do something like:
> DW_TAG_subrange_type:
> 	DW_AT_upper_bound: DW_OP_push_object_address; DW_OP_lit4;
>                          DW_OP_minus; DW_OP_deref_size 4;
> Of course it is very limiting, please see this as FYI only. It illustrates
> how to use DW_OP_push_object_address.

Absolutely. I that was my first try in GCC, before I thought about the 
nasty example with two array fields.

> An alternative is
> DW_TAG_subrange_type:
> 	DW_AT_upper_bound: DW_OP_call_ref "R"; DW_OP_deref_size 4;
> The first operation evaluates the DW_AT_location attribute of the referenced
> DIE. We end up of having the value of n, thus the upper bound. But I`m not
> sure if I misuse the op here, as it requires a type to be bound/instantiated
> for a particular variable.

Oh, smart: I missed this operation. I just had a look at the DWARFv4 
standard, however:

     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

In our case, the "Record_type" DW_TAG_structure type does not have a 
DW_AT_location attribute, so regardless how DW_AT_push_object_address 
migth be evaluated in such cases, the DW_OP_call_ref operation would 
have no effect.

> The way you implement the record above is quite interesting. It requires
> member offsets to be computed rather than being constant.

Indeed. I only had a look at how it was implemented by GNAT, though: 
it's working this way for ages. ;-)

By the way, variable record field offsets are not an issue in DWARF, 
even for our example: the evaluation of the DWARF expression in 
DW_AT_data_member_location starts with a stack that contains the address 
of the record, so it's easy to compute a field offset (for instance a2) 
using the discriminants values (here: n).

> struct record_type {
>    int n;
>    int a1[1]; // array_type with constant member offset
>    int a2[1]; // ...
> };
> In this scenario you have constant offsets, upper_bound for a1,a2 could look
> like:
>    DW_OP_push_object_address; DW_OP_deref_size 4
> The actual location of a1, a2 could be described via DW_AT_data_location. The
> attribute allows indirection to the actual payload.
> I hope the examples above make sense to you.

I'm not sure what you meant: how could a1 and a2 still be arrays with 
dynamic bounds? (assuming they have constant member offsets)

I don't know if this is what you had in mind, but I thought you were 
suggesting to use the whole record as a descriptor for each array. That 
would be, in the DWARF info:

  1. setting the DW_AT_member_data_location attribute of the a1 and a2 
structure members to an "identity" expression (i.e. DW_OP_plus_uconst: 0);

  2. setting the array type DIEs' DW_AT_data_location attribute to add 
the field offset (which sometimes depend on discriminants, but that 
isn't an issue anymore since we have the address of the record);

  3. likewise for the subrange type DIEs' DW_AT_{lower,upper}_bound 

... It would work pretty well, actually! I'm not sure if this would 
really be the way to go:

   - it looks like DWARF hacking: I'm not sure that the record can be 
properly considered as an array descriptor

   - it may require to change a bunch of things in the compiler, but I 
guess this is not an issue if know we will generate quality DWARF info. :-)

> Btw, gcc accepts vla as members of structures as an extension see ['1] and
> Tom pointed out ['2] in a source comment:
> | [...] GCC does have an extension that allows a VLA in the middle of a
> | structure, but the DWARF it emits is relatively useless
> | to us, so we can't represent such a type properly --
> This might be related to your current work.
> ['1] https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html
> ['2] https://sourceware.org/ml/gdb-patches/2014-05/msg00097.html

Interesting. This is still about arrays whose size depends on local 
variables (or function arguments, which is the same to me), though. So 
crafting DWARF expressions for the DW_AT_{lower,uppper}_bound attributes 
looks reasonably easy to me: a sequence of regular register/stack 
operations and computations on them should be sufficient.

Pierre-Marie de Rodat

More information about the Dwarf-discuss mailing list