Compute proper length for dynamic types of TYPE_CODE_TYPEDEF

This patch fixes gdb/21356 in which we hit an assertion in
value_contents_bits_eq:

(gdb) p container_object2
(gdb) p container_object2
$1 = {_container_member2 = 15, _vla_struct_object2 = {_some_member = 0,
    _vla_field = {
../../src/gdb/value.c:829: internal-error: \
  int value_contents_bits_eq(const value*, int, const value*, int, int): \
  Assertion `offset1 + length \
             <= TYPE_LENGTH (val1->enclosing_type) * TARGET_CHAR_BIT' failed.

This is happening because TYPE_LENGTH (val1->enclosing_type) is erroneously
based on enclosing_type, which is a typedef, instead of the actual underlying
type.

This can be traced back to resolve_dynamic_struct, where the size of the
type is computed:
...
        TYPE_FIELD_TYPE (resolved_type, i)
          = resolve_dynamic_type_internal (TYPE_FIELD_TYPE (resolved_type, i),
                                           &pinfo, 0);
        gdb_assert (TYPE_FIELD_LOC_KIND (resolved_type, i)
                    == FIELD_LOC_KIND_BITPOS);

        new_bit_length = TYPE_FIELD_BITPOS (resolved_type, i);
        if (TYPE_FIELD_BITSIZE (resolved_type, i) != 0)
          new_bit_length += TYPE_FIELD_BITSIZE (resolved_type, i);
        else
          new_bit_length += (TYPE_LENGTH (TYPE_FIELD_TYPE (resolved_type, i))
                             * TARGET_CHAR_BIT);
...

In this function, resolved_type is TYPE_CODE_TYPEDEF which is not what we
want to use to calculate the size of the actual field.

This patch fixes this and the similar problem in resolve_dynamic_union.

gdb/ChangeLog:
2020-06-11  Keith Seitz  <keiths@redhat.com>

	PR gdb/21356
	* gdbtypes.c (resolve_dynamic_union, resolve_dynamic_struct):
	Resolve typedefs for type length calculations.

gdb/testsuite/ChangeLog:
2020-06-11  Keith Seitz  <keiths@redhat.com>

	PR gdb/21356
	* gdb.base/vla-datatypes.c (vla_factory): Add typedef for struct
	vla_struct.
	Add new struct vla_typedef and union vla_typedef_union and
	corresponding instantiation objects.
	Initialize new objects.
	* gdb.base/vla-datatypes.exp: Add tests for vla_typedef_struct_object
	and vla_typedef_union_object.
	Fixup type for vla_struct_object.
This commit is contained in:
Keith Seitz
2020-06-11 14:34:44 +02:00
committed by Tom de Vries
parent a8baf0a32b
commit 2f33032a93
5 changed files with 60 additions and 6 deletions

View File

@ -1,3 +1,9 @@
2020-06-11 Keith Seitz <keiths@redhat.com>
PR gdb/21356
* gdbtypes.c (resolve_dynamic_union, resolve_dynamic_struct):
Resolve typedefs for type length calculations.
2020-06-10 Tom de Vries <tdevries@suse.de> 2020-06-10 Tom de Vries <tdevries@suse.de>
PR ada/24713 PR ada/24713

View File

@ -2264,8 +2264,10 @@ resolve_dynamic_union (struct type *type,
t = resolve_dynamic_type_internal (resolved_type->field (i).type (), t = resolve_dynamic_type_internal (resolved_type->field (i).type (),
addr_stack, 0); addr_stack, 0);
resolved_type->field (i).set_type (t); resolved_type->field (i).set_type (t);
if (TYPE_LENGTH (t) > max_len)
max_len = TYPE_LENGTH (t); struct type *real_type = check_typedef (t);
if (TYPE_LENGTH (real_type) > max_len)
max_len = TYPE_LENGTH (real_type);
} }
TYPE_LENGTH (resolved_type) = max_len; TYPE_LENGTH (resolved_type) = max_len;
@ -2521,8 +2523,12 @@ resolve_dynamic_struct (struct type *type,
if (TYPE_FIELD_BITSIZE (resolved_type, i) != 0) if (TYPE_FIELD_BITSIZE (resolved_type, i) != 0)
new_bit_length += TYPE_FIELD_BITSIZE (resolved_type, i); new_bit_length += TYPE_FIELD_BITSIZE (resolved_type, i);
else else
new_bit_length += (TYPE_LENGTH (resolved_type->field (i).type ()) {
* TARGET_CHAR_BIT); struct type *real_type
= check_typedef (resolved_type->field (i).type ());
new_bit_length += (TYPE_LENGTH (real_type) * TARGET_CHAR_BIT);
}
/* Normally, we would use the position and size of the last field /* Normally, we would use the position and size of the last field
to determine the size of the enclosing structure. But GCC seems to determine the size of the enclosing structure. But GCC seems

View File

@ -1,3 +1,15 @@
2020-06-11 Keith Seitz <keiths@redhat.com>
PR gdb/21356
* gdb.base/vla-datatypes.c (vla_factory): Add typedef for struct
vla_struct.
Add new struct vla_typedef and union vla_typedef_union and
corresponding instantiation objects.
Initialize new objects.
* gdb.base/vla-datatypes.exp: Add tests for vla_typedef_struct_object
and vla_typedef_union_object.
Fixup type for vla_struct_object.
2020-06-11 Tom de Vries <tdevries@suse.de> 2020-06-11 Tom de Vries <tdevries@suse.de>
* lib/gdb.exp (with_override): New proc, factored out of ... * lib/gdb.exp (with_override): New proc, factored out of ...

View File

@ -50,7 +50,10 @@ vla_factory (int n)
{ {
int something; int something;
int vla_field[n]; int vla_field[n];
} vla_struct_object; };
/* Define a typedef for a VLA structure. */
typedef struct vla_struct vla_struct_typedef;
vla_struct_typedef vla_struct_object;
struct inner_vla_struct struct inner_vla_struct
{ {
@ -59,14 +62,33 @@ vla_factory (int n)
int after; int after;
} inner_vla_struct_object; } inner_vla_struct_object;
/* Define a structure which uses a typedef for the VLA field
to make sure that GDB creates the proper type for this field,
preventing a possible assertion failure (see gdb/21356). */
struct vla_struct_typedef_struct_member
{
int something;
vla_struct_typedef vla_object;
} vla_struct_typedef_struct_member_object;
union vla_union union vla_union
{ {
int vla_field[n]; int vla_field[n];
} vla_union_object; } vla_union_object;
/* Like vla_struct_typedef_struct_member but a union type. */
union vla_struct_typedef_union_member
{
int something;
vla_struct_typedef vla_object;
} vla_struct_typedef_union_member_object;
vla_struct_object.something = n; vla_struct_object.something = n;
inner_vla_struct_object.something = n; inner_vla_struct_object.something = n;
inner_vla_struct_object.after = n; inner_vla_struct_object.after = n;
vla_struct_typedef_struct_member_object.something = n * 2;
vla_struct_typedef_struct_member_object.vla_object.something = n * 3;
vla_struct_typedef_union_member_object.vla_object.something = n + 1;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
{ {
int_vla[i] = i*2; int_vla[i] = i*2;
@ -85,6 +107,10 @@ vla_factory (int n)
vla_struct_object.vla_field[i] = i*2; vla_struct_object.vla_field[i] = i*2;
vla_union_object.vla_field[i] = i*2; vla_union_object.vla_field[i] = i*2;
inner_vla_struct_object.vla_field[i] = i*2; inner_vla_struct_object.vla_field[i] = i*2;
vla_struct_typedef_struct_member_object.vla_object.vla_field[i]
= i * 3;
vla_struct_typedef_union_member_object.vla_object.vla_field[i]
= i * 3 - 1;
} }
size_t int_size = sizeof(int_vla); /* vlas_filled */ size_t int_size = sizeof(int_vla); /* vlas_filled */

View File

@ -45,6 +45,10 @@ gdb_test "print vla_struct_object" \
"\\\{something = 5, vla_field = \\\{0, 2, 4, 6, 8\\\}\\\}" "\\\{something = 5, vla_field = \\\{0, 2, 4, 6, 8\\\}\\\}"
gdb_test "print vla_union_object" \ gdb_test "print vla_union_object" \
"\\\{vla_field = \\\{0, 2, 4, 6, 8\\\}\\\}" "\\\{vla_field = \\\{0, 2, 4, 6, 8\\\}\\\}"
gdb_test "print vla_struct_typedef_struct_member_object" \
"\\\{something = 10, vla_object = \\\{something = 15, vla_field = \\\{0, 3, 6, 9, 12\\\}\\\}\\\}"
gdb_test "print vla_struct_typedef_union_member_object" \
"\\\{something = 6, vla_object = \\\{something = 6, vla_field = \\\{-1, 2, 5, 8, 11\\\}\\\}\\\}"
# Check whatis of VLA's. # Check whatis of VLA's.
gdb_test "whatis int_vla" "type = int \\\[5\\\]" gdb_test "whatis int_vla" "type = int \\\[5\\\]"
@ -61,7 +65,7 @@ gdb_test "whatis unsigned_short_vla" \
gdb_test "whatis unsigned_char_vla" "type = unsigned char \\\[5\\\]" gdb_test "whatis unsigned_char_vla" "type = unsigned char \\\[5\\\]"
gdb_test "whatis foo_vla" "type = struct foo \\\[5\\\]" gdb_test "whatis foo_vla" "type = struct foo \\\[5\\\]"
gdb_test "whatis bar_vla" "type = BAR \\\[5\\\]" gdb_test "whatis bar_vla" "type = BAR \\\[5\\\]"
gdb_test "whatis vla_struct_object" "type = struct vla_struct" gdb_test "whatis vla_struct_object" "type = vla_struct_typedef"
gdb_test "whatis vla_union_object" "type = union vla_union" gdb_test "whatis vla_union_object" "type = union vla_union"
# Check ptype of VLA's. # Check ptype of VLA's.