This is the mail archive of the gdb-cvs@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]

[binutils-gdb] internal-error using '@' (repeat) operator on array of dynamic objects


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=929b5ad40f70fbd5bdf37d30281a761d56c87b59

commit 929b5ad40f70fbd5bdf37d30281a761d56c87b59
Author: Joel Brobecker <brobecker@adacore.com>
Date:   Wed Jan 31 02:18:56 2018 -0500

    internal-error using '@' (repeat) operator on array of dynamic objects
    
    Using the following Ada declarations (the same as in
    gdb.ada/dyn_stride.exp)...
    
          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 => U, S => (others => ASCII.NUL)),
             2 => (I => 1, S => "A"),
             3 => (I => 2, S => "AB"));
    
    ... where "L" and "U" are variables, trying to apply the repeat
    operator to "A1(1)" yields to an internal error:
    
      | (gdb) print a1(1)@3
      | $5 = /[...]/gdbtypes.c:4883: internal-error: type* copy_type(const type*):
      | Assertion `TYPE_OBJFILE_OWNED (type)' failed.
    
    What happens first is that the ada-lang module evaluated the "A1(1)"
    sub-expression returning a structure where "I" (one of the fields
    in that structure) has a type which is dynamic, because it is
    a range type whose bounds are not statically known.
    
    Next, we apply the repeat ('@') operator, which is done via
    allocate_repeat_value, which creates an array type with the correct
    bounds to associate to our value, by calling lookup_array_range_type:
    
      | struct type *
      | lookup_array_range_type (struct type *element_type,
      |                          LONGEST low_bound, LONGEST high_bound)
      | {
      |   struct gdbarch *gdbarch = get_type_arch (element_type);
      |   struct type *index_type = builtin_type (gdbarch)->builtin_int;
      |   struct type *range_type
      |     = create_static_range_type (NULL, index_type, low_bound, high_bound);
      |
      |   return create_array_type (NULL, element_type, range_type);
      | }
    
    As we can see, this creates an array type whose index type is
    always owned by the gdbarch. This is where the problem lies.
    
    Next, we use that type to construct a struct value. That value
    then gets passed to the valprint module, which then checks
    whether our object is dynamic or not. And because field "I" above
    had a dynamic range type, we end up determining by association
    that the artificial repeat array itself is also dynamic. So
    we attempt to resolve the type, which leads to trying to copying
    that type. And because the artifical array created by
    lookup_array_range_type has an index which is not objfile-owned,
    we trip the assertion.
    
    This patch fixes the issue by enhancing lookup_array_range_type
    to create an index type which has the same owner as the element
    type.
    
    gdb/ChangeLog:
    
            * gdbtypes.c (lookup_array_range_type): Make sure the array's
            index type is objfile-owned if the element type is as well.
    
    gdb/testsuite/ChangeLog:
    
            * testsuite/gdb.ada/dyn_stride.exp: Add "print a1(1)@3" test.

Diff:
---
 gdb/ChangeLog                        |  5 +++++
 gdb/gdbtypes.c                       | 13 +++++++++----
 gdb/testsuite/ChangeLog              |  4 ++++
 gdb/testsuite/gdb.ada/dyn_stride.exp | 19 +++++++++++++++++++
 4 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2a344dd..c6651f5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2018-01-31  Joel Brobecker  <brobecker@adacore.com>
 
+	* gdbtypes.c (lookup_array_range_type): Make sure the array's
+	index type is objfile-owned if the element type is as well.
+
+2018-01-31  Joel Brobecker  <brobecker@adacore.com>
+
 	GDB 8.1 released.
 
 2018-01-30  Philipp Rudo  <prudo@linux.vnet.ibm.com>
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 18a0f2f..79bb659 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -1231,10 +1231,15 @@ struct type *
 lookup_array_range_type (struct type *element_type,
 			 LONGEST low_bound, LONGEST high_bound)
 {
-  struct gdbarch *gdbarch = get_type_arch (element_type);
-  struct type *index_type = builtin_type (gdbarch)->builtin_int;
-  struct type *range_type
-    = create_static_range_type (NULL, index_type, low_bound, high_bound);
+  struct type *index_type;
+  struct type *range_type;
+
+  if (TYPE_OBJFILE_OWNED (element_type))
+    index_type = objfile_type (TYPE_OWNER (element_type).objfile)->builtin_int;
+  else
+    index_type = builtin_type (get_type_arch (element_type))->builtin_int;
+  range_type = create_static_range_type (NULL, index_type,
+					 low_bound, high_bound);
 
   return create_array_type (NULL, element_type, range_type);
 }
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 19b3eda..fa0da60 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2018-01-31  Joel Brobecker  <brobecker@adacore.com>
+
+	* testsuite/gdb.ada/dyn_stride.exp: Add "print a1(1)@3" test.
+
 2018-01-30  Pedro Alves  <palves@redhat.com>
 
 	PR gdb/13211
diff --git a/gdb/testsuite/gdb.ada/dyn_stride.exp b/gdb/testsuite/gdb.ada/dyn_stride.exp
index 0267ca1..dae5106 100644
--- a/gdb/testsuite/gdb.ada/dyn_stride.exp
+++ b/gdb/testsuite/gdb.ada/dyn_stride.exp
@@ -39,3 +39,22 @@ gdb_test "print A1(3)" \
 
 gdb_test "print A1(1..3)" \
          "\\(\\(i => 0, s => \"\"\\), \\(i => 1, s => \"A\"\\), \\(i => 2, s => \"AB\"\\)\\)"
+
+# Test the use of the "repeat" operator (@).
+#
+# Note that, in this case, the repeat operator makes little sense
+# and is NOT equivalent to requesting an array slice. In the case
+# of "print a1(1)@3", the size of each element in the array is
+# variable from element to element.  So, when asked to repeat
+# one element of the array a number of times, you're not guaranteed
+# to get the same answer as in a slice; while the slice will
+# take into account the array stride, the repeat operator uses
+# the size of the object being repeated as its stride, which
+# is often not the same. So, in the test below, the output for
+# the second and third element is not entirely predictable, because
+# it reads part of their contents from a memory region which has
+# an undefined value (the "holes" between the each actual element
+# of the array).
+
+gdb_test "print a1(1)@3" \
+         " = \\(\\(i => 0, s => \"\"\\), \\(i => -?$decimal, s => .*\\), \\(i => -?$decimal, s => .*\\)\\)"


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