[gdb/symtab] Fix unhandled dwarf expression opcode with gcc-11 -gdwarf-5
authorTom de Vries <tdevries@suse.de>
Wed, 28 Jul 2021 08:17:44 +0000 (10:17 +0200)
committerTom de Vries <tdevries@suse.de>
Wed, 28 Jul 2021 08:17:44 +0000 (10:17 +0200)
[ I've confused things by forgetting to add -gdwarf-4 in $subject of
commit 0057a7ee0d9 "[gdb/testsuite] Add KFAILs for gdb.ada FAILs with
gcc-11".  So I'm adding here -gdwarf-5 in $subject, even though -gdwarf-5 is
the default for gcc-11.  I keep getting confused because of working with a
system gcc-11 compiler that was patched to switch the default back to
-gdwarf-4. ]

When running test-case gdb.ada/arrayptr.exp with gcc-11 (and default
-gdwarf-5), I run into:
...
(gdb) print pa_ptr.all^M
Unhandled dwarf expression opcode 0xff^M
(gdb) FAIL: gdb.ada/arrayptr.exp: scenario=all: print pa_ptr.all
...

What happens is that pa_ptr:
...
 <2><1523>: Abbrev Number: 3 (DW_TAG_variable)
    <1524>   DW_AT_name        : pa_ptr
    <1529>   DW_AT_type        : <0x14fa>
...
has type:
...
 <2><14fa>: Abbrev Number: 2 (DW_TAG_typedef)
    <14fb>   DW_AT_name        : foo__packed_array_ptr
    <1500>   DW_AT_type        : <0x1504>
 <2><1504>: Abbrev Number: 4 (DW_TAG_pointer_type)
    <1505>   DW_AT_byte_size   : 8
    <1505>   DW_AT_type        : <0x1509>
...
which is a pointer to a subrange:
...
 <2><1509>: Abbrev Number: 12 (DW_TAG_subrange_type)
    <150a>   DW_AT_lower_bound : 0
    <150b>   DW_AT_upper_bound : 0x3fffffffffffffffff
    <151b>   DW_AT_name        : foo__packed_array
    <151f>   DW_AT_type        : <0x15cc>
    <1523>   DW_AT_artificial  : 1
 <1><15cc>: Abbrev Number: 5 (DW_TAG_base_type)
    <15cd>   DW_AT_byte_size   : 16
    <15ce>   DW_AT_encoding    : 7      (unsigned)
    <15cf>   DW_AT_name        : long_long_long_unsigned
    <15d3>   DW_AT_artificial  : 1
...
with upper bound of form DW_FORM_data16.

In gdb/dwarf/attribute.h we have:
...
  /* Return non-zero if ATTR's value falls in the 'constant' class, or
     zero otherwise.  When this function returns true, you can apply
     the constant_value method to it.
     ...
     DW_FORM_data16 is not considered as constant_value cannot handle
     that.  */
  bool form_is_constant () const;
...
so instead we have attribute::form_is_block (DW_FORM_data16) == true.

Then in attr_to_dynamic_prop for the upper bound, we get a PROC_LOCEXPR
instead of a PROP_CONST and end up trying to evaluate the constant
0x3fffffffffffffffff as if it were a locexpr, which causes the
"Unhandled dwarf expression opcode 0xff".

In contrast, with -gdwarf-4 we have:
...
    <164c>   DW_AT_upper_bound : 18 byte block: \
      9e 10 ff ff ff ff ff ff ff ff 3f 0 0 0 0 0 0 0 \
      (DW_OP_implicit_value 16 byte block: \
        ff ff ff ff ff ff ff ff 3f 0 0 0 0 0 0 0 )
...

Fix the dwarf error by translating the DW_FORM_data16 constant into a
PROC_LOCEXPR, effectively by prepending 0x9e 0x10, such that we have same
result as with -gdwarf-4:
...
(gdb) print pa_ptr.all^M
That operation is not available on integers of more than 8 bytes.^M
(gdb) KFAIL: gdb.ada/arrayptr.exp: scenario=all: print pa_ptr.all \
  (PRMS: gdb/20991)
...

Tested on x86_64-linux, with gcc-11 and target board
unix/gdb:debug_flags=-gdwarf-5.

gdb/ChangeLog:

2021-07-28  Tom de Vries  <tdevries@suse.de>

* dwarf2/read.c (attr_to_dynamic_prop): Handle DW_FORM_data16.

gdb/ChangeLog
gdb/dwarf2/read.c

index a917cdf4526b9f20d4bcce9e832ccb768ea3acdd..f371a2d31fc4a6fcceac5f65f698f802636d31d7 100644 (file)
@@ -1,3 +1,7 @@
+2021-07-28  Tom de Vries  <tdevries@suse.de>
+
+       * dwarf2/read.c (attr_to_dynamic_prop): Handle DW_FORM_data16.
+
 2021-07-27  Tom de Vries  <tdevries@suse.de>
 
        PR testsuite/26904
index 760d4319c29697d16b7aa4890d7ed43b8cf44ebd..2b054f56e09f35cd4d1d5dbd3b877674dd901f91 100644 (file)
@@ -18231,7 +18231,22 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
       baton->locexpr.per_cu = cu->per_cu;
       baton->locexpr.per_objfile = per_objfile;
 
-      struct dwarf_block *block = attr->as_block ();
+      struct dwarf_block *block;
+      if (attr->form == DW_FORM_data16)
+       {
+         size_t data_size = 16;
+         block = XOBNEW (obstack, struct dwarf_block);
+         block->size = (data_size
+                        + 2 /* Extra bytes for DW_OP and arg.  */);
+         gdb_byte *data = XOBNEWVEC (obstack, gdb_byte, block->size);
+         data[0] = DW_OP_implicit_value;
+         data[1] = data_size;
+         memcpy (&data[2], attr->as_block ()->data, data_size);
+         block->data = data;
+       }
+      else
+       block = attr->as_block ();
+
       baton->locexpr.size = block->size;
       baton->locexpr.data = block->data;
       switch (attr->name)
This page took 0.037569 seconds and 4 git commands to generate.