Re: [PATCHv2 4/5] gdb: Carry default property type around with dynamic properties

Tom Tromey
2019-05-22T19:05:53Z

Andrew> <1><af>: Abbrev Number: 12 (DW_TAG_array_type)
Andrew> <b0> DW_AT_data_location: 2 byte block: 97 6 (DW_OP_push_object_address; DW_OP_deref)
Andrew> <b3> DW_AT_allocated : 4 byte block: 97 6 30 2e (DW_OP_push_object_address; DW_OP_deref; DW_OP_lit0; DW_OP_ne)
Andrew> <b8> DW_AT_type : <0x2a>
Andrew> <2><bc>: Abbrev Number: 13 (DW_TAG_subrange_type)
Andrew> <bd> DW_AT_lower_bound : 4 byte block: 97 23 10 6 (DW_OP_push_object_address; DW_OP_plus_uconst: 16; DW_OP_deref)
Andrew> <c2> DW_AT_upper_bound : 4 byte block: 97 23 14 6 (DW_OP_push_object_address; DW_OP_plus_uconst: 20; DW_OP_deref)
Andrew> <c7> DW_AT_byte_stride : 6 byte block: 97 23 c 6 34 1e (DW_OP_push_object_address; DW_OP_plus_uconst: 12; DW_OP_deref; DW_OP_lit4; DW_OP_mul)

This is a funny coincidence, because we were discussing a similar case
with Ada just this week. Gnat can generate very similar expressions in
some cases:

<1><11b5>: Abbrev Number: 8 (DW_TAG_array_type)
<11b6> DW_AT_name : (indirect string, offset: 0x1ba2): string
<11ba> DW_AT_data_location: 2 byte block: 97 6 (DW_OP_push_object_address; DW_OP_deref)
<11bd> DW_AT_type : <0x113c>
<11c1> DW_AT_sibling : <0x11db>
<2><11c5>: Abbrev Number: 9 (DW_TAG_subrange_type)
<11c6> DW_AT_type : <0x11e0>
<11ca> DW_AT_lower_bound : 6 byte block: 97 23 8 6 94 4 (DW_OP_push_object_address; DW_OP_plus_uconst: 8; DW_OP_deref; DW_OP_deref_size: 4)
<11d1> DW_AT_upper_bound : 8 byte block: 97 23 8 6 23 4 94 4 (DW_OP_push_object_address; DW_OP_plus_uconst: 8; DW_OP_deref; DW_OP_plus_uconst: 4; DW_OP_deref_size: 4)

Essentially what's going on here is that the compiler represents a
pointer-to-array as a structure that holds a pointer and the array
bounds; and then chooses to represent this in DWARF as the above.

This in turn causes problems in gdb. In the above case, it's not
possible to make a call like `do_something("string")', because gdb
doesn't know that constructing one of these arrays at runtime actually
requires two allocations and some special messing around.

So, this week we've been talking about changing the representation of
these things to be more explicit, that is, make the hidden struct type
explicit (and marked DW_AT_artificial).

I wonder how Fortran will handle this, or whether it even needs to. Is
it possible for gdb to construct one of these arrays at runtime?

Another option, besides changing the representation, would be to teach
gdb how to create one of the above by recognizing the expressions as a
kind of special case. This seemed uglier and more fragile, though.

For Ada at least, this sort of DWARF isn't the default yet. The default
is this Ada-specific name encodings scheme; you have to opt-in to DWARF
using a compiler command-line flag; but one of the things I'm looking
into is getting gdb to the point where we can flip the default.

Andrew> I wonder if the best solution for dealing with signed properties will
Andrew> be to move away from an over reliance on fetch_address, and instead
Andrew> come up with a new solution that considers the current type of the
Andrew> value on the stack, and the type that the value needs to become;
Andrew> basically a solution built around casting rather than assuming we
Andrew> always want an address.

DWARF now has typed expressions as well, so gcc could just emit this
explicitly, I think. I didn't look at gcc's dwarf2out.c for this but
maybe you need -gdwarf-5 to make this happen.

Andrew> It is my belief that we can find a suitable default type for every
Andrew> dynamic property, either specified explicitly in the DWARF spec, or we
Andrew> can infer an obvious choice if the spec doesn't help us.

Seems reasonable.

Andrew> +static struct type *
Andrew> +dwarf2_per_cu_addr_sized_int_type (struct dwarf2_per_cu_data *per_cu)
Andrew> +{
Andrew> + struct objfile *objfile = per_cu->dwarf2_per_objfile->objfile;
Andrew> + int addr_size = dwarf2_per_cu_addr_size (per_cu);
Andrew> + struct type *int_type;
Andrew> +
Andrew> + int_type = objfile_type (objfile)->builtin_short;
Andrew> + if (int_type != NULL && TYPE_LENGTH (int_type) == addr_size)
Andrew> + return int_type;

dwarf2_per_cu_addr_type handles unsigned char here, but this one does not.
I doubt it matters but I wonder why the difference.

Andrew> +/* Return a type that is a generic pointer type, the size of which matches
Andrew> + the address size given in the compilation unit header for PER_CU. */
Andrew> +static struct type *
Andrew> +dwarf2_per_cu_addr_type (struct dwarf2_per_cu_data *per_cu)
Andrew> +{
Andrew> + struct objfile *objfile = per_cu->dwarf2_per_objfile->objfile;
Andrew> + struct type *void_type = objfile_type (objfile)->builtin_void;
Andrew> + struct type *addr_type = lookup_pointer_type (void_type);
Andrew> + int addr_size = dwarf2_per_cu_addr_size (per_cu);
Andrew> +
Andrew> + if (TYPE_LENGTH (addr_type) == addr_size)
Andrew> + return addr_type;
Andrew> +
Andrew> + /* Yuck! We currently only support one address size per architecture in
Andrew> + GDB, which should usually match the address size encoded into the
Andrew> + compilation unit header. However... we have a few tests where this is
Andrew> + not the case, these are mostly test cases where the DWARF is hand
Andrew> + written and includes a fixed address size, for example 8-bytes. When
Andrew> + we compile these tests on a 32-bit i386 target the gdbarch address
Andrew> + size is 4-bytes and the above attempt to create a suitable address
Andrew> + type fails.
Andrew> +
Andrew> + As we can't currently create an address type of a different size, we
Andrew> + instead substitute an unsigned integer for an address.
Andrew> +
Andrew> + I don't know if there are targets that have signed addresses and if
Andrew> + they would need a signed integer here. I figure we'll handle that
Andrew> + case when it presents itself as a problem. */

gdbarch.sh makes a distinction between addresses and pointers which, I
confess, I have never understood. However, based on this, I think at
least MIPS may have signed pointers. From mips-tdep.c:

set_gdbarch_pointer_to_address (gdbarch, signed_pointer_to_address);
set_gdbarch_address_to_pointer (gdbarch, address_to_signed_pointer);

Also, I wonder whether it wouldn't be simpler to just provide a way to
create a TYPE_CODE_PTR type with a specified size.

Tom