This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA/DWARF] Add array DW_AT_bit_stride and DW_AT_byte_stride support


Ping?

Thank you :)

On Wed, Jan 29, 2014 at 06:30:30PM +0400, Joel Brobecker wrote:
> Hello,
> 
> Consider the following declarations in Ada...
> 
>    type Item is range -32 .. 31;
>    for Item'Size use 6;
> 
>    type Table is array (Natural range 0 .. 4) of Item;
>    pragma Pack (Table);
> 
> ... which declare a packed array whose elements are 6 bits long.
> The debugger currently does not notice that the array is packed,
> and thus prints values of this type incorrectly. This can be seen
> in the "ptype" output:
> 
>     (gdb) ptype table
>     type = array (0 .. 4) of foo.item
> 
> Normally, the debugger should print:
> 
>     (gdb) ptype table
>     type = array (0 .. 4) of foo.item <packed: 6-bit elements>
> 
> The debugging information for this array looks like this:
> 
>         .uleb128 0xf    # (DIE (0x15c) DW_TAG_array_type)
>         .long   .LASF9  # DW_AT_name: "pck__table"
>         .byte   0x6     # DW_AT_bit_stride
>         .long   0x1a9   # DW_AT_type
>         .uleb128 0x10   # (DIE (0x16a) DW_TAG_subrange_type)
>         .long   0x3b    # DW_AT_type
>         .byte   0       # DW_AT_lower_bound
>         .byte   0x4     # DW_AT_upper_bound
>         .byte   0       # end of children of DIE 0x15c
> 
> The interesting part is the DW_AT_bit_stride attribute, which tells
> the size of the array elements is 6 bits, rather than the normal
> element type's size.
> 
> This patch adds support for this attribute by first creating
> gdbtypes.c::create_array_type_with_stride, which is an enhanced
> version of create_array_type taking an extra parameter as the stride.
> The old create_array_type can then be re-implemented very simply
> by calling the new create_array_type_with_stride.
> 
> We can then use this new function from dwarf2read, to create
> arrays with or without stride.
> 
> gdb/ChangeLog:
> 
>         * gdbtypes.h (create_array_type_with_stride): Add declaration.
>         * gdbtypes.c (create_array_type_with_stride): New function,
>         renaming create_array_type, but with an added parameter
>         called "bit_stride".
>         (create_array_type): Re-implement using
>         create_array_type_with_stride.
>         * dwarf2read.c (read_array_type): Add support for DW_AT_byte_stride
>         and DW_AT_bit_stride attributes.
> 
> gdb/testsuite/ChangeLog:
> 
>         * gdb.dwarf2/arr-stride.c: New file.
>         * gdb.dwarf2/arr-stride.exp: New file.
> 
> The test, relying purely on generating an assembly file, only
> verifies the type description of our array. But I was also
> able to verify manually that the debugger print values of these
> types correctly as well (which was not the case prior to this
> patch).
> ---
>  gdb/dwarf2read.c                        |  18 +++++-
>  gdb/gdbtypes.c                          |  27 +++++++-
>  gdb/gdbtypes.h                          |   4 ++
>  gdb/testsuite/gdb.dwarf2/arr-stride.c   |  20 ++++++
>  gdb/testsuite/gdb.dwarf2/arr-stride.exp | 108 ++++++++++++++++++++++++++++++++
>  5 files changed, 171 insertions(+), 6 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.dwarf2/arr-stride.c
>  create mode 100644 gdb/testsuite/gdb.dwarf2/arr-stride.exp
> 
> diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
> index 54c538a..1c9c188 100644
> --- a/gdb/dwarf2read.c
> +++ b/gdb/dwarf2read.c
> @@ -13254,6 +13254,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
>    int ndim = 0;
>    struct cleanup *back_to;
>    const char *name;
> +  unsigned int bit_stride = 0;
>  
>    element_type = die_type (die, cu);
>  
> @@ -13262,13 +13263,22 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
>    if (type)
>      return type;
>  
> +  attr = dwarf2_attr (die, DW_AT_byte_stride, cu);
> +  if (attr != NULL)
> +    bit_stride = DW_UNSND (attr) * 8;
> +
> +  attr = dwarf2_attr (die, DW_AT_bit_stride, cu);
> +  if (attr != NULL)
> +    bit_stride = DW_UNSND (attr);
> +
>    /* Irix 6.2 native cc creates array types without children for
>       arrays with unspecified length.  */
>    if (die->child == NULL)
>      {
>        index_type = objfile_type (objfile)->builtin_int;
>        range_type = create_range_type (NULL, index_type, 0, -1);
> -      type = create_array_type (NULL, element_type, range_type);
> +      type = create_array_type_with_stride (NULL, element_type, range_type,
> +					    bit_stride);
>        return set_die_type (die, type, cu);
>      }
>  
> @@ -13308,12 +13318,14 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
>        int i = 0;
>  
>        while (i < ndim)
> -	type = create_array_type (NULL, type, range_types[i++]);
> +	type = create_array_type_with_stride (NULL, type, range_types[i++],
> +					      bit_stride);
>      }
>    else
>      {
>        while (ndim-- > 0)
> -	type = create_array_type (NULL, type, range_types[ndim]);
> +	type = create_array_type_with_stride (NULL, type, range_types[ndim],
> +					      bit_stride);
>      }
>  
>    /* Understand Dwarf2 support for vector types (like they occur on
> diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
> index 042c17d..03d7ba9 100644
> --- a/gdb/gdbtypes.c
> +++ b/gdb/gdbtypes.c
> @@ -951,14 +951,18 @@ get_array_bounds (struct type *type, LONGEST *low_bound, LONGEST *high_bound)
>     Elements will be of type ELEMENT_TYPE, the indices will be of type
>     RANGE_TYPE.
>  
> +   If BIT_STRIDE is non-null, build a packed array type whose element
> +   size is BIT_STRIDE.  Otherwise, ignore this parameter.
> +
>     FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make
>     sure it is TYPE_CODE_UNDEF before we bash it into an array
>     type?  */
>  
>  struct type *
> -create_array_type (struct type *result_type, 
> -		   struct type *element_type,
> -		   struct type *range_type)
> +create_array_type_with_stride (struct type *result_type,
> +			       struct type *element_type,
> +			       struct type *range_type,
> +			       unsigned int bit_stride)
>  {
>    LONGEST low_bound, high_bound;
>  
> @@ -975,6 +979,9 @@ create_array_type (struct type *result_type,
>       In such cases, the array length should be zero.  */
>    if (high_bound < low_bound)
>      TYPE_LENGTH (result_type) = 0;
> +  else if (bit_stride > 0)
> +    TYPE_LENGTH (result_type) =
> +      (bit_stride * (high_bound - low_bound + 1) + 7) / 8;
>    else
>      TYPE_LENGTH (result_type) =
>        TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
> @@ -983,6 +990,8 @@ create_array_type (struct type *result_type,
>      (struct field *) TYPE_ZALLOC (result_type, sizeof (struct field));
>    TYPE_INDEX_TYPE (result_type) = range_type;
>    TYPE_VPTR_FIELDNO (result_type) = -1;
> +  if (bit_stride > 0)
> +    TYPE_FIELD_BITSIZE (result_type, 0) = bit_stride;
>  
>    /* TYPE_FLAG_TARGET_STUB will take care of zero length arrays.  */
>    if (TYPE_LENGTH (result_type) == 0)
> @@ -991,6 +1000,18 @@ create_array_type (struct type *result_type,
>    return result_type;
>  }
>  
> +/* Same as create_array_type_with_stride but with no bit_stride
> +   (BIT_STRIDE = -1), thus building an unpacked array.  */
> +
> +struct type *
> +create_array_type (struct type *result_type,
> +		   struct type *element_type,
> +		   struct type *range_type)
> +{
> +  return create_array_type_with_stride (result_type, element_type,
> +					range_type, 0);
> +}
> +
>  struct type *
>  lookup_array_range_type (struct type *element_type,
>  			 LONGEST low_bound, LONGEST high_bound)
> diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
> index 61ddeff..a1d9921 100644
> --- a/gdb/gdbtypes.h
> +++ b/gdb/gdbtypes.h
> @@ -1529,8 +1529,12 @@ extern struct type *lookup_function_type_with_arguments (struct type *,
>  extern struct type *create_range_type (struct type *, struct type *, LONGEST,
>  				       LONGEST);
>  
> +extern struct type *create_array_type_with_stride
> +  (struct type *, struct type *, struct type *, unsigned int);
> +
>  extern struct type *create_array_type (struct type *, struct type *,
>  				       struct type *);
> +
>  extern struct type *lookup_array_range_type (struct type *, LONGEST, LONGEST);
>  
>  extern struct type *create_string_type (struct type *, struct type *,
> diff --git a/gdb/testsuite/gdb.dwarf2/arr-stride.c b/gdb/testsuite/gdb.dwarf2/arr-stride.c
> new file mode 100644
> index 0000000..978ef8d
> --- /dev/null
> +++ b/gdb/testsuite/gdb.dwarf2/arr-stride.c
> @@ -0,0 +1,20 @@
> +/* Copyright 2014 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/>.  */
> +
> +int
> +main (void)
> +{
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.dwarf2/arr-stride.exp b/gdb/testsuite/gdb.dwarf2/arr-stride.exp
> new file mode 100644
> index 0000000..f2a1f39
> --- /dev/null
> +++ b/gdb/testsuite/gdb.dwarf2/arr-stride.exp
> @@ -0,0 +1,108 @@
> +# Copyright 2014 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 dwarf.exp
> +
> +# This test can only be run on targets which support DWARF-2 and use gas.
> +if {![dwarf2_support]} {
> +    return 0
> +}
> +
> +standard_testfile arr-stride.c arr-stride-dw.S
> +
> +# Make some DWARF for the test.
> +set asm_file [standard_output_file $srcfile2]
> +Dwarf::assemble $asm_file {
> +    cu {} {
> + 	DW_TAG_compile_unit {
> +                {DW_AT_language @DW_LANG_Ada95}
> +                {DW_AT_name     foo.adb}
> +                {DW_AT_comp_dir /tmp}
> +        } {
> +	    declare_labels integer_label array_elt_label array_label \
> +                big_array_label
> +
> +            integer_label: DW_TAG_base_type {
> +                {DW_AT_byte_size 4 DW_FORM_sdata}
> +                {DW_AT_encoding  @DW_ATE_signed}
> +                {DW_AT_name      integer}
> +            }
> +
> +            array_elt_label: DW_TAG_subrange_type {
> +                {DW_AT_lower_bound 0xe0 DW_FORM_data1}
> +                {DW_AT_upper_bound 0x1f DW_FORM_data1}
> +                {DW_AT_name        pck__item}
> +                {DW_AT_type        :$integer_label}
> +            }
> +
> +            DW_TAG_typedef {
> +                {DW_AT_name pck__table}
> +                {DW_AT_type :$array_label}
> +            }
> +
> +	    array_label: DW_TAG_array_type {
> +		{DW_AT_name pck__table}
> +                {DW_AT_bit_stride 6 DW_FORM_data1}
> +		{DW_AT_type :$array_elt_label}
> +	    } {
> +		DW_TAG_subrange_type {
> +		    {DW_AT_type        :$integer_label}
> +		    {DW_AT_lower_bound 0 DW_FORM_data1}
> +		    {DW_AT_upper_bound 4 DW_FORM_data1}
> +		}
> +	    }
> +
> +            DW_TAG_typedef {
> +                {DW_AT_name pck__big_table}
> +                {DW_AT_type :$big_array_label}
> +            }
> +
> +	    big_array_label: DW_TAG_array_type {
> +		{DW_AT_name pck__big_table}
> +                {DW_AT_byte_stride 1 DW_FORM_data1}
> +		{DW_AT_type :$array_elt_label}
> +	    } {
> +		DW_TAG_subrange_type {
> +		    {DW_AT_type        :$integer_label}
> +		    {DW_AT_lower_bound 0 DW_FORM_data1}
> +		    {DW_AT_upper_bound 4 DW_FORM_data1}
> +		}
> +	    }
> +	}
> +    }
> +}
> +
> +if  {[gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile}1.o \
> +	  object {nodebug}] != ""} {
> +    return -1
> +}
> +
> +if  {[gdb_compile $asm_file ${binfile}2.o object {nodebug}] != ""} {
> +    return -1
> +}
> +
> +if  {[gdb_compile [list ${binfile}1.o ${binfile}2.o] \
> +	  "${binfile}" executable {}] != ""} {
> +    return -1
> +}
> +
> +clean_restart ${testfile}
> +
> +gdb_test_no_output "set language ada"
> +
> +gdb_test "ptype pck.table" \
> +         "type = array \\(0 \\.\\. 4\\) of pck\\.item <packed: 6-bit elements>"
> +
> +gdb_test "ptype pck.big_table" \
> +         "type = array \\(0 \\.\\. 4\\) of pck\\.item <packed: 8-bit elements>"
> -- 
> 1.8.3.2

-- 
Joel


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]