gdb/dwarf2read: Minimal handling of non-constant struct sizes.
authorJoel Brobecker <brobecker@adacore.com>
Mon, 23 Nov 2015 17:44:16 +0000 (09:44 -0800)
committerJoel Brobecker <brobecker@adacore.com>
Mon, 23 Nov 2015 17:44:16 +0000 (09:44 -0800)
Using the gdb.ada/var_rec_arr.exp test, where the program declares
an array of variant records...

   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;

... and then a variable A1 of type Array_Type, the following command
ocassionally trigger an internal error trying to allocate more memory
than we have left:

    (gdb) ptype a1(1)
    [...]/utils.c:1089: internal-error: virtual memory exhausted.
    A problem internal to GDB has been detected,
    [...]

What happens is that recent versions of GNAT are able to generate
DWARF expressions for type Record_Type, and therefore the record's
DW_AT_byte_size is not a constant, which unfortunately breaks
an assumption made by dwarf2read.c:read_structure_type when it does:

   attr = dwarf2_attr (die, DW_AT_byte_size, cu);
   if (attr)
     {
       TYPE_LENGTH (type) = DW_UNSND (attr);
     }

As a result of this, when ada_evaluate_subexp tries to create
a value_zero for a1(1) while processing the OP_FUNCALL operator
as part of evaluating the subscripting operation in no-side-effect
mode, we try to allocate a value with a bogus size, potentially
triggering the out-of-memory internal error.

This patch avoids this issue by setting the length to zero in
this case.  Until we decide to start supporting dynamic type
lengths in GDB's type struct, and it's not clear yet that
this is worth the effort (see added comment), that's probably
the best we can do.

gdb/ChangeLog:

        * dwarf2read.c (read_structure_type): Set the type's length
        to zero if it has a DW_AT_byte_size attribute which is not
        a constant.

gdb/testsuite/ChangeLog:

        * testsuite/gdb.ada/var_rec_arr.exp: Add "ptype a1(1)" test.

gdb/ChangeLog
gdb/dwarf2read.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.ada/var_rec_arr.exp

index 605eb39972e9005a256c2da4950391a80854c577..437dbc20d0e9e3d365ce228e0d7be25f77ee6d63 100644 (file)
@@ -1,3 +1,9 @@
+2015-11-23  Joel Brobecker  <brobecker@adacore.com>
+
+       * dwarf2read.c (read_structure_type): Set the type's length
+       to zero if it has a DW_AT_byte_size attribute which is not
+       a constant.
+
 2015-11-23  Tristan Gingold  <gingold@adacore.com>
 
        * darwin-nat.c (darwin_ptrace): Avoid a cast.
index 48921e78bfb4b197623fe396ada58022d71df7f9..298757cde6eed942ca6ad119af325b573cdcb8d0 100644 (file)
@@ -13218,7 +13218,20 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
   attr = dwarf2_attr (die, DW_AT_byte_size, cu);
   if (attr)
     {
-      TYPE_LENGTH (type) = DW_UNSND (attr);
+      if (attr_form_is_constant (attr))
+        TYPE_LENGTH (type) = DW_UNSND (attr);
+      else
+       {
+         /* For the moment, dynamic type sizes are not supported
+            by GDB's struct type.  The actual size is determined
+            on-demand when resolving the type of a given object,
+            so set the type's length to zero for now.  Otherwise,
+            we record an expression as the length, and that expression
+            could lead to a very large value, which could eventually
+            lead to us trying to allocate that much memory when creating
+            a value of that type.  */
+          TYPE_LENGTH (type) = 0;
+       }
     }
   else
     {
index 68ede89f5662c34594751587ed40023f7a264a64..ee01eb66b42b10a11f0af02eeeb92ed74afb4f12 100644 (file)
@@ -1,3 +1,7 @@
+2015-11-23  Joel Brobecker  <brobecker@adacore.com>
+
+       * testsuite/gdb.ada/var_rec_arr.exp: Add "ptype a1(1)" test.
+
 2015-11-20  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
         * gdb.base/callfuncs.exp (fetch_all_registers): Filter out the
index 82ca8572b4e0cbe7204a0a082c2100f700b872c2..66525e782889373dbba5d38ca87c63c3a51f2a61 100644 (file)
@@ -49,3 +49,9 @@ gdb_test "print a2(2)" \
 
 gdb_test "print a2(3)" \
          " = \\(i => 0, s => \"\"\\)"
+
+gdb_test "ptype a1(1)" \
+         [multi_line "type = record" \
+                     "    i: pck\\.small_type;" \
+                     "    s: access array \\((<>|1 \\.\\. i)\\) of character;" \
+                     "end record"]