compare object sizes before comparing them with value_contents_eq
authorJoel Brobecker <brobecker@adacore.com>
Thu, 30 Apr 2015 21:04:25 +0000 (23:04 +0200)
committerJoel Brobecker <brobecker@adacore.com>
Tue, 5 May 2015 17:51:38 +0000 (10:51 -0700)
This is an issue which I noticed while working on trying to print
an array of variant records. For instance, trying to print "A1",
an array of elements whose size is variable, defined as follow
(see gdb.ada/var_rec_arr testcase):

   subtype Small_Type is Integer range 0 .. 10;
   type Record_Type (I : Small_Type := 0) is record
      S : String (1 .. I);
   end record;
   function Ident (R : Record_Type) return Record_Type;

   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"));

The debugger sometimes prints the array as follow:

    (gdb) print A1
    $1 = ((i => 0, s => ""), (i => 0, s => ""), (i => 0, s => ""))

The problem happens inside the part of the loop printing the array's
elements, while trying to count the number of consecutive elements
that have the same value (in order to replace them by the "<repeats
nnn times>" message when the number exceeds a threshold). In particular,
in ada-valprint.c::val_print_packed_array_elements:

  elttype = TYPE_TARGET_TYPE (type);
  eltlen = TYPE_LENGTH (check_typedef (elttype));

  while (...)
    {
          if (!value_contents_eq (v0, value_embedded_offset (v0),
                                  v1, value_embedded_offset (v1),
                                  eltlen))
            break;

The value comparison is performed using value_contents_eq but makes
the assumption that elttype is not dynamic, which is not always true.
In particular, in the case above, elttype is dynamic and therefore
its TYPE_LENGTH changes from element to element.

As it happens in this case, the eltlen is zero, which causes the call
to value_contents_eq to return true, and therefore GDB thinks all
3 elements of the array are equal.

This patch fixes the issue by making sure that both v0 and v1, which
are values whose type we expect to be resolved, have identical lengths.
If not, then the two elements of the array cannot possibly have the
same value and we do not even need to do the binary comparison.

Unfortunately, this is still not enough to get GDB to print the correct
value for our array, because the assumption that v0 and v1 have a type
which has been resolved is actually not met. So, the second part of
the patch modifies the function that constructed the values to make
sure dynamic types do get resolved.

gdb/ChangeLog:

        * ada-valprint.c (val_print_packed_array_elements): Delete
        variable "len".  Add a type-length check when comparing two
        consecutive elements of the array.  Use the element's actual
        length in call to value_contents_eq.
        * ada-lang.c (ada_value_primitive_packed_val): Always return
        a value whose type has been resolved.

gdb/ChangeLog
gdb/ada-lang.c
gdb/ada-valprint.c

index 990bad71c514382ecab1c5e8603c23e7c6213adf..e01b98b53704d4777c2f23783d0df4a48517aa44 100644 (file)
@@ -1,3 +1,12 @@
+2015-05-05  Joel Brobecker  <brobecker@adacore.com>
+
+       * ada-valprint.c (val_print_packed_array_elements): Delete
+       variable "len".  Add a type-length check when comparing two
+       consecutive elements of the array.  Use the element's actual
+       length in call to value_contents_eq.
+       * ada-lang.c (ada_value_primitive_packed_val): Always return
+       a value whose type has been resolved.
+
 2015-05-05  Joel Brobecker  <brobecker@adacore.com>
 
        * ada-lang.c (ada_value_primitive_packed_val): Recompute
index d0aea26837caeda3b01680b58178e33aa2d82d8f..c56e8bb9c4346bc7cc926be3c36fc6258dc343e7 100644 (file)
@@ -2549,6 +2549,9 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr,
       targ += delta;
     }
 
+  if (is_dynamic_type (value_type (v)))
+    v = value_from_contents_and_address (value_type (v), value_contents (v),
+                                        0);
   return v;
 }
 
index 720854e2cad30d39532219bce9991a4620f0330a..ba12a7842e05668cbdafd858662abd7ba5137aa5 100644 (file)
@@ -129,13 +129,11 @@ val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr,
   unsigned int things_printed = 0;
   unsigned len;
   struct type *elttype, *index_type;
-  unsigned eltlen;
   unsigned long bitsize = TYPE_FIELD_BITSIZE (type, 0);
   struct value *mark = value_mark ();
   LONGEST low = 0;
 
   elttype = TYPE_TARGET_TYPE (type);
-  eltlen = TYPE_LENGTH (check_typedef (elttype));
   index_type = TYPE_INDEX_TYPE (type);
 
   {
@@ -184,9 +182,12 @@ val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr,
                                               (i * bitsize) / HOST_CHAR_BIT,
                                               (i * bitsize) % HOST_CHAR_BIT,
                                               bitsize, elttype);
+         if (TYPE_LENGTH (check_typedef (value_type (v0)))
+             != TYPE_LENGTH (check_typedef (value_type (v1))))
+           break;
          if (!value_contents_eq (v0, value_embedded_offset (v0),
                                  v1, value_embedded_offset (v1),
-                                 eltlen))
+                                 TYPE_LENGTH (check_typedef (value_type (v0)))))
            break;
        }