From: Andrew Burgess Date: Tue, 7 May 2019 23:01:14 +0000 (+0100) Subject: gdb/dwarf: Ensure the target type of ranges is not void X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b86352cfc17fb7f07d5da9efcfd59f8b2bd08eee;p=binutils-gdb.git gdb/dwarf: Ensure the target type of ranges is not void If a DW_TAG_subrange_type DWARF entry has no DW_AT_type then a default type based on the size of an address on the current target is assumed. We store this type as the target type for GDB's range types. Currently GDB can create ranges for which the target type is VOID, this is incorrect but seems to cause no problems. I believe the reason this doesn't cause any issues is because the languages (for example Ada) that actually make use of a ranges target type also have compilers that generate DWARF that includes a DW_AT_type attribute. However, gfortran does not include a DW_AT_type, its DWARF instead relies on the default target type. This isn't currently a problem for GDB as gfortran doesn't make use of the target type when printing subranges, but it shouldn't hurt to fix this issue now. I've added an assert into create_range_type that will catch this issue if it comes up again. This was tested on an x86-64/GNU-Linux machine with both the Ada and gfortran compilers available with both '--target_board=unix' and '--target_board=unix/-m32'. There are no user visible changes after this commit. gdb/ChangeLog: * dwarf2read.c (read_subrange_index_type): New function. (read_subrange_type): Move code into new function and call it. * gdbtypes.c (create_range_type): Add some asserts. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 29b675d0bcf..c8c2b4014d1 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2019-07-12 Andrew Burgess + + * dwarf2read.c (read_subrange_index_type): New function. + (read_subrange_type): Move code into new function and call it. + * gdbtypes.c (create_range_type): Add some asserts. + 2019-07-12 Andrew Burgess * dwarf2loc.c (dwarf2_evaluate_property): Change return type, and diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index f4796776db8..e918792eabd 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -17752,6 +17752,56 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, return 1; } +/* Read the DW_AT_type attribute for a sub-range. If this attribute is not + present (which is valid) then compute the default type based on the + compilation units address size. */ + +static struct type * +read_subrange_index_type (struct die_info *die, struct dwarf2_cu *cu) +{ + struct type *index_type = die_type (die, cu); + + /* Dwarf-2 specifications explicitly allows to create subrange types + without specifying a base type. + In that case, the base type must be set to the type of + the lower bound, upper bound or count, in that order, if any of these + three attributes references an object that has a type. + If no base type is found, the Dwarf-2 specifications say that + a signed integer type of size equal to the size of an address should + be used. + For the following C code: `extern char gdb_int [];' + GCC produces an empty range DIE. + FIXME: muller/2010-05-28: Possible references to object for low bound, + high bound or count are not yet handled by this code. */ + if (TYPE_CODE (index_type) == TYPE_CODE_VOID) + { + struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile; + struct gdbarch *gdbarch = get_objfile_arch (objfile); + int addr_size = gdbarch_addr_bit (gdbarch) /8; + struct type *int_type = objfile_type (objfile)->builtin_int; + + /* Test "int", "long int", and "long long int" objfile types, + and select the first one having a size above or equal to the + architecture address size. */ + if (int_type && TYPE_LENGTH (int_type) >= addr_size) + index_type = int_type; + else + { + int_type = objfile_type (objfile)->builtin_long; + if (int_type && TYPE_LENGTH (int_type) >= addr_size) + index_type = int_type; + else + { + int_type = objfile_type (objfile)->builtin_long_long; + if (int_type && TYPE_LENGTH (int_type) >= addr_size) + index_type = int_type; + } + } + } + + return index_type; +} + /* Read the given DW_AT_subrange DIE. */ static struct type * @@ -17766,7 +17816,8 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) const char *name; ULONGEST negative_mask; - orig_base_type = die_type (die, cu); + orig_base_type = read_subrange_index_type (die, cu); + /* If ORIG_BASE_TYPE is a typedef, it will not be TYPE_UNSIGNED, whereas the real type might be. So, we use ORIG_BASE_TYPE when creating the range type, but we use the result of check_typedef @@ -17848,45 +17899,6 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) sect_offset_str (die->sect_off), objfile_name (cu->per_cu->dwarf2_per_objfile->objfile)); } - - } - - /* Dwarf-2 specifications explicitly allows to create subrange types - without specifying a base type. - In that case, the base type must be set to the type of - the lower bound, upper bound or count, in that order, if any of these - three attributes references an object that has a type. - If no base type is found, the Dwarf-2 specifications say that - a signed integer type of size equal to the size of an address should - be used. - For the following C code: `extern char gdb_int [];' - GCC produces an empty range DIE. - FIXME: muller/2010-05-28: Possible references to object for low bound, - high bound or count are not yet handled by this code. */ - if (TYPE_CODE (base_type) == TYPE_CODE_VOID) - { - struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile; - struct gdbarch *gdbarch = get_objfile_arch (objfile); - int addr_size = gdbarch_addr_bit (gdbarch) /8; - struct type *int_type = objfile_type (objfile)->builtin_int; - - /* Test "int", "long int", and "long long int" objfile types, - and select the first one having a size above or equal to the - architecture address size. */ - if (int_type && TYPE_LENGTH (int_type) >= addr_size) - base_type = int_type; - else - { - int_type = objfile_type (objfile)->builtin_long; - if (int_type && TYPE_LENGTH (int_type) >= addr_size) - base_type = int_type; - else - { - int_type = objfile_type (objfile)->builtin_long_long; - if (int_type && TYPE_LENGTH (int_type) >= addr_size) - base_type = int_type; - } - } } /* Normally, the DWARF producers are expected to use a signed diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index d7a14b7ace9..177455e6126 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -914,6 +914,11 @@ create_range_type (struct type *result_type, struct type *index_type, const struct dynamic_prop *low_bound, const struct dynamic_prop *high_bound) { + /* The INDEX_TYPE should be a type capable of holding the upper and lower + bounds, as such a zero sized, or void type makes no sense. */ + gdb_assert (TYPE_CODE (index_type) != TYPE_CODE_VOID); + gdb_assert (TYPE_LENGTH (index_type) > 0); + if (result_type == NULL) result_type = alloc_type_copy (index_type); TYPE_CODE (result_type) = TYPE_CODE_RANGE;