diff options
-rw-r--r-- | gdb/ChangeLog | 13 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 27 | ||||
-rw-r--r-- | gdb/gdbtypes.c | 80 | ||||
-rw-r--r-- | gdb/gdbtypes.h | 6 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gdb/testsuite/gdb.ada/dyn_stride.exp | 38 | ||||
-rw-r--r-- | gdb/testsuite/gdb.ada/dyn_stride/foo.adb | 42 |
7 files changed, 197 insertions, 13 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3199eaa..2c25683 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,18 @@ 2018-01-02 Joel Brobecker <brobecker@adacore.com> + * gdbtypes.h (enum dynamic_prop_node_kind) <DYN_PROP_BYTE_STRIDE>: + New enum value. + (create_array_type_with_stride): Add byte_stride_prop parameter. + * gdbtypes.c (create_array_type_with_stride) <byte_stride_prop>: + New parameter. Update all callers in this file. + (array_type_has_dynamic_stride): New function. + (is_dynamic_type_internal, resolve_dynamic_array): Add handling + of arrays with dynamic byte strides. + * dwarf2read.c (read_array_type): Add support for dynamic + DW_AT_byte_stride attributes. + +2018-01-02 Joel Brobecker <brobecker@adacore.com> + * dwarf2read.c (read_unspecified_type): Treat DW_TAG_enumeration_type DIEs from Ada units as stubs. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 4dbd5c3..a3028e5 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -16312,6 +16312,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) struct type *element_type, *range_type, *index_type; struct attribute *attr; const char *name; + struct dynamic_prop *byte_stride_prop = NULL; unsigned int bit_stride = 0; element_type = die_type (die, cu); @@ -16323,7 +16324,25 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_byte_stride, cu); if (attr != NULL) - bit_stride = DW_UNSND (attr) * 8; + { + int stride_ok; + + byte_stride_prop + = (struct dynamic_prop *) alloca (sizeof (struct dynamic_prop)); + stride_ok = attr_to_dynamic_prop (attr, die, cu, byte_stride_prop); + if (!stride_ok) + { + complaint (&symfile_complaints, + _("unable to read array DW_AT_byte_stride " + " - DIE at 0x%x [in module %s]"), + to_underlying (die->sect_off), + objfile_name (cu->objfile)); + /* Ignore this attribute. We will likely not be able to print + arrays of this type correctly, but there is little we can do + to help if we cannot read the attribute's value. */ + byte_stride_prop = NULL; + } + } attr = dwarf2_attr (die, DW_AT_bit_stride, cu); if (attr != NULL) @@ -16336,7 +16355,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) index_type = objfile_type (objfile)->builtin_int; range_type = create_static_range_type (NULL, index_type, 0, -1); type = create_array_type_with_stride (NULL, element_type, range_type, - bit_stride); + byte_stride_prop, bit_stride); return set_die_type (die, type, cu); } @@ -16369,14 +16388,14 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) while (i < range_types.size ()) type = create_array_type_with_stride (NULL, type, range_types[i++], - bit_stride); + byte_stride_prop, bit_stride); } else { size_t ndim = range_types.size (); while (ndim-- > 0) type = create_array_type_with_stride (NULL, type, range_types[ndim], - bit_stride); + byte_stride_prop, bit_stride); } /* Understand Dwarf2 support for vector types (like they occur on diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 96b8610..7ba62df 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1090,6 +1090,14 @@ discrete_position (struct type *type, LONGEST val, LONGEST *pos) Elements will be of type ELEMENT_TYPE, the indices will be of type RANGE_TYPE. + BYTE_STRIDE_PROP, when not NULL, provides the array's byte stride. + This byte stride property is added to the resulting array type + as a DYN_PROP_BYTE_STRIDE. As a consequence, the BYTE_STRIDE_PROP + argument can only be used to create types that are objfile-owned + (see add_dyn_prop), meaning that either this function must be called + with an objfile-owned RESULT_TYPE, or an objfile-owned RANGE_TYPE. + + BIT_STRIDE is taken into account only when BYTE_STRIDE_PROP is NULL. If BIT_STRIDE is not zero, build a packed array type whose element size is BIT_STRIDE. Otherwise, ignore this parameter. @@ -1101,14 +1109,27 @@ struct type * create_array_type_with_stride (struct type *result_type, struct type *element_type, struct type *range_type, + struct dynamic_prop *byte_stride_prop, unsigned int bit_stride) { + if (byte_stride_prop != NULL + && byte_stride_prop->kind == PROP_CONST) + { + /* The byte stride is actually not dynamic. Pretend we were + called with bit_stride set instead of byte_stride_prop. + This will give us the same result type, while avoiding + the need to handle this as a special case. */ + bit_stride = byte_stride_prop->data.const_val * 8; + byte_stride_prop = NULL; + } + if (result_type == NULL) result_type = alloc_type_copy (range_type); TYPE_CODE (result_type) = TYPE_CODE_ARRAY; TYPE_TARGET_TYPE (result_type) = element_type; - if (has_static_range (TYPE_RANGE_DATA (range_type)) + if (byte_stride_prop == NULL + && has_static_range (TYPE_RANGE_DATA (range_type)) && (!type_not_associated (result_type) && !type_not_allocated (result_type))) { @@ -1144,7 +1165,10 @@ create_array_type_with_stride (struct type *result_type, TYPE_FIELDS (result_type) = (struct field *) TYPE_ZALLOC (result_type, sizeof (struct field)); TYPE_INDEX_TYPE (result_type) = range_type; - if (bit_stride > 0) + if (byte_stride_prop != NULL) + add_dyn_prop (DYN_PROP_BYTE_STRIDE, *byte_stride_prop, result_type, + TYPE_OBJFILE (result_type)); + else if (bit_stride > 0) TYPE_FIELD_BITSIZE (result_type, 0) = bit_stride; /* TYPE_TARGET_STUB will take care of zero length arrays. */ @@ -1163,7 +1187,7 @@ create_array_type (struct type *result_type, struct type *range_type) { return create_array_type_with_stride (result_type, element_type, - range_type, 0); + range_type, NULL, 0); } struct type * @@ -1824,6 +1848,17 @@ stub_noname_complaint (void) complaint (&symfile_complaints, _("stub type has NULL name")); } +/* Return nonzero if TYPE has a DYN_PROP_BYTE_STRIDE dynamic property + attached to it, and that property has a non-constant value. */ + +static int +array_type_has_dynamic_stride (struct type *type) +{ + struct dynamic_prop *prop = get_dyn_prop (DYN_PROP_BYTE_STRIDE, type); + + return (prop != NULL && prop->kind != PROP_CONST); +} + /* Worker for is_dynamic_type. */ static int @@ -1869,11 +1904,16 @@ is_dynamic_type_internal (struct type *type, int top_level) { gdb_assert (TYPE_NFIELDS (type) == 1); - /* The array is dynamic if either the bounds are dynamic, - or the elements it contains have a dynamic contents. */ + /* The array is dynamic if either the bounds are dynamic... */ if (is_dynamic_type_internal (TYPE_INDEX_TYPE (type), 0)) return 1; - return is_dynamic_type_internal (TYPE_TARGET_TYPE (type), 0); + /* ... or the elements it contains have a dynamic contents... */ + if (is_dynamic_type_internal (TYPE_TARGET_TYPE (type), 0)) + return 1; + /* ... or if it has a dynamic stride... */ + if (array_type_has_dynamic_stride (type)) + return 1; + return 0; } case TYPE_CODE_STRUCT: @@ -1969,6 +2009,7 @@ resolve_dynamic_array (struct type *type, struct type *range_type; struct type *ary_dim; struct dynamic_prop *prop; + unsigned int bit_stride = 0; gdb_assert (TYPE_CODE (type) == TYPE_CODE_ARRAY); @@ -2000,8 +2041,31 @@ resolve_dynamic_array (struct type *type, else elt_type = TYPE_TARGET_TYPE (type); - return create_array_type_with_stride (type, elt_type, range_type, - TYPE_FIELD_BITSIZE (type, 0)); + prop = get_dyn_prop (DYN_PROP_BYTE_STRIDE, type); + if (prop != NULL) + { + int prop_eval_ok + = dwarf2_evaluate_property (prop, NULL, addr_stack, &value); + + if (prop_eval_ok) + { + remove_dyn_prop (DYN_PROP_BYTE_STRIDE, type); + bit_stride = (unsigned int) (value * 8); + } + else + { + /* Could be a bug in our code, but it could also happen + if the DWARF info is not correct. Issue a warning, + and assume no byte/bit stride (leave bit_stride = 0). */ + warning (_("cannot determine array stride for type %s"), + TYPE_NAME (type) ? TYPE_NAME (type) : "<no name>"); + } + } + else + bit_stride = TYPE_FIELD_BITSIZE (type, 0); + + return create_array_type_with_stride (type, elt_type, range_type, NULL, + bit_stride); } /* Resolve dynamic bounds of members of the union TYPE to static diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index a286d44..5942b5a 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -418,6 +418,9 @@ enum dynamic_prop_node_kind /* A property representing DW_AT_allocated. The presence of this attribute indicated that the object of the type can be associated. */ DYN_PROP_ASSOCIATED, + + /* A property providing an array's byte stride. */ + DYN_PROP_BYTE_STRIDE, }; /* * List for dynamic type attributes. */ @@ -1791,7 +1794,8 @@ extern struct type *create_static_range_type (struct type *, struct type *, extern struct type *create_array_type_with_stride - (struct type *, struct type *, struct type *, unsigned int); + (struct type *, struct type *, struct type *, + struct dynamic_prop *, unsigned int); extern struct type *create_range_type (struct type *, struct type *, const struct dynamic_prop *, diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 909d11d..06f0f47 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2018-01-02 Joel Brobecker <brobecker@adacore.com> + + * gdb.ada/dyn_stride: New testcase. + 2017-12-27 Stafford Horne <shorne@gmail.com> * gdb.xml/extra-regs.xml: Add example foo reggroup. diff --git a/gdb/testsuite/gdb.ada/dyn_stride.exp b/gdb/testsuite/gdb.ada/dyn_stride.exp new file mode 100644 index 0000000..33723d4 --- /dev/null +++ b/gdb/testsuite/gdb.ada/dyn_stride.exp @@ -0,0 +1,38 @@ +# Copyright 2015-2018 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 <http://www.gnu.org/licenses/>. + +load_lib "ada.exp" + +standard_ada_testfile foo + +if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" } { + return -1 +} + +clean_restart ${testfile} + +set bp_location [gdb_get_line_number "STOP" ${testdir}/foo.adb] +if ![runto "foo.adb:$bp_location" ] then { + return -1 +} + +gdb_test "print A1(1)" \ + "\\(i => 0, s => \"\"\\)" + +gdb_test "print A1(2)" \ + "\\(i => 1, s => \"A\"\\)" + +gdb_test "print A1(3)" \ + "\\(i => 2, s => \"AB\"\\)" diff --git a/gdb/testsuite/gdb.ada/dyn_stride/foo.adb b/gdb/testsuite/gdb.ada/dyn_stride/foo.adb new file mode 100644 index 0000000..12ab8ce --- /dev/null +++ b/gdb/testsuite/gdb.ada/dyn_stride/foo.adb @@ -0,0 +1,42 @@ +-- Copyright 2015-2018 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 <http://www.gnu.org/licenses/>. + +procedure Foo is + + procedure Nested (L, U : Integer) is + subtype Small_Type is Integer range L .. U; + type Record_Type (I : Small_Type := L) is record + S : String (1 .. I); + end record; + type Array_Type is array (Integer range <>) of Record_Type; + + A1 : Array_Type := + (1 => (I => 0, S => <>), + 2 => (I => 1, S => "A"), + 3 => (I => 2, S => "AB")); + + procedure Discard (R : Record_Type) is + begin + null; + end Discard; + + begin + Discard (A1 (1)); -- STOP + end; + +begin + Nested (0, 10); + Nested (-10, 10); +end Foo; |