[Dwarf-Discuss] About self-referencial sized types

Agovic, Sanimir sanimir.agovic at intel.com
Fri May 16 06:00:00 PDT 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
types.

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

 -Sanimir  


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