[Dwarf-Discuss] About self-referencial sized types

Agovic, Sanimir sanimir.agovic@intel.com
Fri May 16 13:00:00 GMT 2014

> > 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
>      effect.
> 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.
Indeed, therefore you have to reference a DW_TAG_variable. But
this introduces a type/variable dependency. So a record type maps
to a single variable, you end up with a 1:1 relation for this kind of

> > 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).
Unfortunately gdb only allows constant offsets or constant dwarf expressions.

> > 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)
It essentially works around the limitation of not having dynamic member
offset support.

 a) Assign constant offsets to your record members.
 b) Use data_location for array types to refer to the actual array offset
 c) use upper/lower to specify the bounds

See a1/a2/aN as proxy array types which use data_location to point
to the right location at runtime.

> 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
> attributes.
> ... It would work pretty well, actually! I'm not sure if this would
> really be the way to go:
It is indeed quite hackish and we should rather add the necessary bits
to gdb.

>    - it looks like DWARF hacking: I'm not sure that the record can be
> properly considered as an array descriptor
If you emit the corresponding dwarf tags for your initial example and
add the data_location as well as the upper/lower attributes it should
work, of course only in theory ATM.

> > 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.
The problem is that the member offset depend on runtime information similar
to sizeof which needs to be evaluated at runtime if the operand is a vla.

Given the following snippet:

	struct foo {int a[n], int b[i];};

	&((struct foo *)0)->b;

What value do you expect here? And should the value be different if it is 
evaluated at runtime e.g. &f.b - &f.a?


Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052

More information about the Dwarf-discuss mailing list