From: Tom Tromey Date: Fri, 24 Apr 2020 19:40:31 +0000 (-0600) Subject: Add support for dynamic type lengths X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f8e89861cfb6acbfa097814f5864afd5563a3011;p=binutils-gdb.git Add support for dynamic type lengths In Ada, a type with variant parts can have a variable length. This patch adds support for this to gdb, by integrating the length computation into the dynamic type resolution code. gdb/ChangeLog 2020-04-24 Tom Tromey * dwarf2/read.c (read_structure_type): Handle dynamic length. * gdbtypes.c (is_dynamic_type_internal): Check TYPE_HAS_DYNAMIC_LENGTH. (resolve_dynamic_type_internal): Use TYPE_DYNAMIC_LENGTH. * gdbtypes.h (TYPE_HAS_DYNAMIC_LENGTH, TYPE_DYNAMIC_LENGTH): New macros. (enum dynamic_prop_node_kind) : New constant. gdb/testsuite/ChangeLog 2020-04-24 Tom Tromey * gdb.ada/variant.exp: New file * gdb.ada/variant/pkg.adb: New file * gdb.ada/variant/pck.adb: New file --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 962c997bc95..29e9a4778dc 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2020-04-24 Tom Tromey + + * dwarf2/read.c (read_structure_type): Handle dynamic length. + * gdbtypes.c (is_dynamic_type_internal): Check + TYPE_HAS_DYNAMIC_LENGTH. + (resolve_dynamic_type_internal): Use TYPE_DYNAMIC_LENGTH. + * gdbtypes.h (TYPE_HAS_DYNAMIC_LENGTH, TYPE_DYNAMIC_LENGTH): + New macros. + (enum dynamic_prop_node_kind) : New + constant. + 2020-04-24 Tom Tromey * dwarf2/read.c (struct variant_field): Rewrite. diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index dd808e08e21..f6d062451b3 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -15300,14 +15300,10 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) TYPE_LENGTH (type) = DW_UNSND (attr); else { - /* For the moment, dynamic type sizes are not supported - by GDB's struct type. The actual size is determined - on-demand when resolving the type of a given object, - so set the type's length to zero for now. Otherwise, - we record an expression as the length, and that expression - could lead to a very large value, which could eventually - lead to us trying to allocate that much memory when creating - a value of that type. */ + struct dynamic_prop prop; + if (attr_to_dynamic_prop (attr, die, cu, &prop, + cu->per_cu->addr_type ())) + add_dyn_prop (DYN_PROP_BYTE_SIZE, prop, type); TYPE_LENGTH (type) = 0; } } diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 1bd9d8a55c7..6d755e98b66 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1975,6 +1975,9 @@ is_dynamic_type_internal (struct type *type, int top_level) if (prop != nullptr && prop->kind != PROP_TYPE) return 1; + if (TYPE_HAS_DYNAMIC_LENGTH (type)) + return 1; + switch (TYPE_CODE (type)) { case TYPE_CODE_RANGE: @@ -2491,13 +2494,19 @@ resolve_dynamic_type_internal (struct type *type, int top_level) { struct type *real_type = check_typedef (type); - struct type *resolved_type = type; + struct type *resolved_type = nullptr; struct dynamic_prop *prop; CORE_ADDR value; if (!is_dynamic_type_internal (real_type, top_level)) return type; + gdb::optional type_length; + prop = TYPE_DYNAMIC_LENGTH (type); + if (prop != NULL + && dwarf2_evaluate_property (prop, NULL, addr_stack, &value)) + type_length = value; + if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) { resolved_type = copy_type (type); @@ -2553,6 +2562,15 @@ resolve_dynamic_type_internal (struct type *type, } } + if (resolved_type == nullptr) + return type; + + if (type_length.has_value ()) + { + TYPE_LENGTH (resolved_type) = *type_length; + remove_dyn_prop (DYN_PROP_BYTE_SIZE, resolved_type); + } + /* Resolve data_location attribute. */ prop = TYPE_DATA_LOCATION (resolved_type); if (prop != NULL diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 134515845f2..87b1bca3a22 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -355,6 +355,10 @@ DEF_ENUM_FLAGS_TYPE (enum type_instance_flag_value, type_instance_flags); #define TYPE_HAS_VARIANT_PARTS(t) \ (get_dyn_prop (DYN_PROP_VARIANT_PARTS, t) != nullptr) +/* * True if this type has a dynamic length. */ +#define TYPE_HAS_DYNAMIC_LENGTH(t) \ + (get_dyn_prop (DYN_PROP_BYTE_SIZE, t) != nullptr) + /* * Instruction-space delimited type. This is for Harvard architectures which have separate instruction and data address spaces (and perhaps others). @@ -552,6 +556,9 @@ enum dynamic_prop_node_kind /* A property holding variant parts. */ DYN_PROP_VARIANT_PARTS, + + /* A property holding the size of the type. */ + DYN_PROP_BYTE_SIZE, }; /* * List for dynamic type attributes. */ @@ -1445,6 +1452,8 @@ extern bool set_type_align (struct type *, ULONGEST); TYPE_DATA_LOCATION (thistype)->data.const_val #define TYPE_DATA_LOCATION_KIND(thistype) \ TYPE_DATA_LOCATION (thistype)->kind +#define TYPE_DYNAMIC_LENGTH(thistype) \ + get_dyn_prop (DYN_PROP_BYTE_SIZE, thistype) /* Property accessors for the type allocated/associated. */ #define TYPE_ALLOCATED_PROP(thistype) \ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 7426bdde4cd..66647002475 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-24 Tom Tromey + + * gdb.ada/variant.exp: New file + * gdb.ada/variant/pkg.adb: New file + * gdb.ada/variant/pck.adb: New file + 2020-04-24 Tom de Vries * lib/gdb.exp (clean_restart): Reset errcnt and warncnt. diff --git a/gdb/testsuite/gdb.ada/variant.exp b/gdb/testsuite/gdb.ada/variant.exp new file mode 100644 index 00000000000..b68bf60b192 --- /dev/null +++ b/gdb/testsuite/gdb.ada/variant.exp @@ -0,0 +1,40 @@ +# Copyright 2020 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +load_lib "ada.exp" + +standard_ada_testfile pkg + +foreach_with_prefix scenario {none all minimal} { + set flags {debug} + if {$scenario != "none"} { + lappend flags additional_flags=-fgnat-encodings=$scenario + } + + if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $flags] != ""} { + return -1 + } + + clean_restart ${testfile} + + set bp_location [gdb_get_line_number "STOP" ${testdir}/pkg.adb] + runto "pkg.adb:$bp_location" + + gdb_test "print r" "= \\(c => 100 'd'\\)" + gdb_test "print q" " = \\(c => 0 '\\\[\"00\"\\\]', x_first => 27\\)" + + gdb_test "print st1" " = \\(i => -4, one => 1, x => 2\\)" + gdb_test "print st2" " = \\(i => 99, one => 1, y => 77\\)" +} diff --git a/gdb/testsuite/gdb.ada/variant/pck.ads b/gdb/testsuite/gdb.ada/variant/pck.ads new file mode 100644 index 00000000000..41b6efd4da8 --- /dev/null +++ b/gdb/testsuite/gdb.ada/variant/pck.ads @@ -0,0 +1,37 @@ +-- Copyright 2020 Free Software Foundation, Inc. +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . + +package Pck is + + type Rec_Type (C : Character := 'd') is record + case C is + when Character'First => X_First : Integer; + when Character'Val (127) => X_127 : Integer; + when Character'Val (128) => X_128 : Integer; + when Character'Last => X_Last : Integer; + when others => null; + end case; + end record; + + type Second_Type (I : Integer) is record + One: Integer; + case I is + when -5 .. 5 => + X : Integer; + when others => + Y : Integer; + end case; + end record; +end Pck; diff --git a/gdb/testsuite/gdb.ada/variant/pkg.adb b/gdb/testsuite/gdb.ada/variant/pkg.adb new file mode 100644 index 00000000000..0cc38f5b253 --- /dev/null +++ b/gdb/testsuite/gdb.ada/variant/pkg.adb @@ -0,0 +1,30 @@ +-- Copyright 2020 Free Software Foundation, Inc. +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . + +with Pck; use Pck; + +procedure Pkg is + + R, Q : Rec_Type; + + ST1 : constant Second_Type := (I => -4, One => 1, X => 2); + ST2 : constant Second_Type := (I => 99, One => 1, Y => 77); + +begin + R := (C => 'd'); + Q := (C => Character'First, X_First => 27); + + null; -- STOP +end Pkg;