Patchwork [RFA/commit,1/6] preserve the bit stride when resolving an array type.

login
register
mail settings
Submitter Joel Brobecker
Date April 21, 2015, 3:44 p.m.
Message ID <1429631064-4196-2-git-send-email-brobecker@adacore.com>
Download mbox | patch
Permalink /patch/6341/
State New
Headers show

Comments

Joel Brobecker - April 21, 2015, 3:44 p.m.
Consider the following (Ada) variable...

   A1 : Array_Type := (1 => (I => 0, S => <>),
                       2 => (I => 1, S => "A"),
                       3 => (I => 2, S => "AB"));

... where Array_Type is an array of records whose size is variable:

   subtype Small_Type is Integer range 0 .. 10;
   type Record_Type (I : Small_Type := 0) is record
      S : String (1 .. I);
   end record;
   type Array_Type is array (Integer range <>) of Record_Type;

Trying to print the value of this array currently results in the following
error:

    (gdb) p a1
    Cannot access memory at address 0x61c000

What happens in this case, is that the compiler describes our array
as an array with a specific stride (and bounds being static 1..3):

 <1><749>: Abbrev Number: 10 (DW_TAG_array_type)
    <74a>   DW_AT_name        : (indirect string, offset: 0xb6d): pck__T18s
    <74e>   DW_AT_byte_stride : 16
    <74f>   DW_AT_type        : <0x6ea>
 <2><757>: Abbrev Number: 11 (DW_TAG_subrange_type)
    <758>   DW_AT_type        : <0x75e>
    <75c>   DW_AT_upper_bound : 3

This is because we cannot use, in this case, the size of the record
to determine that stride, since the size of the record depends on
its contents. So the compiler helps us by providing that stride.

The problems start when trying to resolve that type. Because the elements
contained in that array type are dynamic, the array itself is considered
dynamic, and thus we end up creating a resolved version of that array.
And during that resolution, we were not handling the case where the array
had a stride. See gdbtypes.c::resolve_dynamic_array...

  return create_array_type (copy_type (type),
                            elt_type,
                            range_type);

As a result, we created an array whose stride was based on the size
of elt_type, which a record whose size isn't static and irrelevant
regardless.

This patch fixes is by calling create_array_type_with_stride instead.

As it happens, there is another issue for us to be able to print
the value of our array, but those are independent of this patch
and will be handled separately. For now, the patch allows us to
get rid of the first error, and the output is now:

     (gdb) p a1
     $1 = (

gdb/ChangeLog:

	* gdbtypes.c (resolve_dynamic_array): Use
	create_array_type_with_stride instead of create_array_type.
---
 gdb/gdbtypes.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Patch

diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 217ec70..fe00ea7 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -1898,9 +1898,9 @@  resolve_dynamic_array (struct type *type,
   else
     elt_type = TYPE_TARGET_TYPE (type);
 
-  return create_array_type (copy_type (type),
-			    elt_type,
-			    range_type);
+  return create_array_type_with_stride (copy_type (type),
+					elt_type, range_type,
+					TYPE_FIELD_BITSIZE (type, 0));
 }
 
 /* Resolve dynamic bounds of members of the union TYPE to static