]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Backport patches from the mainline to fix the handling of DWARF-5 debug information:
authorNick Clifton <nickc@redhat.com>
Tue, 25 Aug 2020 14:39:00 +0000 (15:39 +0100)
committerNick Clifton <nickc@redhat.com>
Tue, 25 Aug 2020 14:39:00 +0000 (15:39 +0100)
binutils* testsuite/binutils-all/readelf.exp (readelf_wi_test): Also
recognize DW_LANG_C11.

bfd *  dwarf2.c (struct dwarf2_debug_file): Add dwarf_rnglists_buffer
and dwarf_rnglists_size fields.
(dwarf_debug_sections): Add debug_rnglists.
(dwarf_debug_section_enum): Likewise.
(read_debug_rnglists): New function.
(read_rangelist): New function to call either read_ranges or
read_rnglists. Rename original function to...
(read_ranges): ...this.
(read_rnglists): New function.

* dwarf2.c (read_attribute_value): Handle DW_FORM_data16.
(read_formatted_entries): Likewise. And skip zero entry.

bfd/ChangeLog
bfd/dwarf2.c
binutils/ChangeLog
binutils/testsuite/binutils-all/readelf.exp

index 6d1d01a566a0c209559e63905adf796a5604598e..4ad5aa840f1dbc57cf76168eef383c04c02a527b 100644 (file)
@@ -1,3 +1,23 @@
+2020-08-25  Nick Clifton  <nickc@redhat.com>
+
+       Backport from the mainline:
+       2020-08-25  Mark Wielaard  <mark@klomp.org>
+
+       *  dwarf2.c (struct dwarf2_debug_file): Add dwarf_rnglists_buffer
+       and dwarf_rnglists_size fields.
+       (dwarf_debug_sections): Add debug_rnglists.
+       (dwarf_debug_section_enum): Likewise.
+       (read_debug_rnglists): New function.
+       (read_rangelist): New function to call either read_ranges or
+       read_rnglists. Rename original function to...
+       (read_ranges): ...this.
+       (read_rnglists): New function.
+
+       2020-08-24  Mark Wielaard  <mark@klomp.org>
+
+       * dwarf2.c (read_attribute_value): Handle DW_FORM_data16.
+       (read_formatted_entries): Likewise. And skip zero entry.
+
 2020-08-15  Alan Modra  <amodra@gmail.com>
 
        PR 26389
index 9ed4a4a2871f03bc88c3c132a25453fe8423ba79..b8f0008a10da531c8119d154b03cf5713f6d76b4 100644 (file)
@@ -130,6 +130,12 @@ struct dwarf2_debug_file
   /* Length of the loaded .debug_ranges section.  */
   bfd_size_type dwarf_ranges_size;
 
+  /* Pointer to the .debug_rnglists section loaded into memory.  */
+  bfd_byte *dwarf_rnglists_buffer;
+
+  /* Length of the loaded .debug_rnglists section.  */
+  bfd_size_type dwarf_rnglists_size;
+
   /* A list of all previously read comp_units.  */
   struct comp_unit *all_comp_units;
 
@@ -327,6 +333,7 @@ const struct dwarf_debug_section dwarf_debug_sections[] =
   { ".debug_pubnames",         ".zdebug_pubnames" },
   { ".debug_pubtypes",         ".zdebug_pubtypes" },
   { ".debug_ranges",           ".zdebug_ranges" },
+  { ".debug_rnglists",         ".zdebug_rnglist" },
   { ".debug_static_func",      ".zdebug_static_func" },
   { ".debug_static_vars",      ".zdebug_static_vars" },
   { ".debug_str",              ".zdebug_str", },
@@ -360,6 +367,7 @@ enum dwarf_debug_section_enum
   debug_pubnames,
   debug_pubtypes,
   debug_ranges,
+  debug_rnglists,
   debug_static_func,
   debug_static_vars,
   debug_str,
@@ -1329,6 +1337,17 @@ read_attribute_value (struct attribute *  attr,
       attr->form = DW_FORM_sdata;
       attr->u.sval = implicit_const;
       break;
+    case DW_FORM_data16:
+      /* This is really a "constant", but there is no way to store that
+         so pretend it is a 16 byte block instead.  */
+      amt = sizeof (struct dwarf_block);
+      blk = (struct dwarf_block *) bfd_alloc (abfd, amt);
+      if (blk == NULL)
+       return NULL;
+      blk->size = 16;
+      info_ptr = read_n_bytes (info_ptr, info_ptr_end, blk);
+      attr->u.blk = blk;
+      break;
     default:
       _bfd_error_handler (_("DWARF error: invalid or unhandled FORM value: %#x"),
                          form);
@@ -2069,11 +2088,17 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
            case DW_FORM_udata:
              *uintp = attr.u.val;
              break;
+
+           case DW_FORM_data16:
+             /* MD5 data is in the attr.blk, but we are ignoring those.  */
+             break;
            }
        }
 
-      if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
-       return FALSE;
+      /* Skip the first "zero entry", which is the compilation dir/file.  */
+      if (datai != 0)
+       if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
+         return FALSE;
     }
 
   *bufp = buf;
@@ -2617,6 +2642,19 @@ read_debug_ranges (struct comp_unit * unit)
                       &file->dwarf_ranges_buffer, &file->dwarf_ranges_size);
 }
 
+/* Read in the .debug_rnglists section for future reference.  */
+
+static bfd_boolean
+read_debug_rnglists (struct comp_unit * unit)
+{
+  struct dwarf2_debug *stash = unit->stash;
+  struct dwarf2_debug_file *file = unit->file;
+
+  return read_section (unit->abfd, &stash->debug_sections[debug_rnglists],
+                      file->syms, 0,
+                      &file->dwarf_rnglists_buffer, &file->dwarf_rnglists_size);
+}
+
 /* Function table functions.  */
 
 static int
@@ -3107,8 +3145,8 @@ find_abstract_instance (struct comp_unit *unit,
 }
 
 static bfd_boolean
-read_rangelist (struct comp_unit *unit, struct arange *arange,
-               bfd_uint64_t offset)
+read_ranges (struct comp_unit *unit, struct arange *arange,
+            bfd_uint64_t offset)
 {
   bfd_byte *ranges_ptr;
   bfd_byte *ranges_end;
@@ -3153,6 +3191,107 @@ read_rangelist (struct comp_unit *unit, struct arange *arange,
   return TRUE;
 }
 
+static bfd_boolean
+read_rnglists (struct comp_unit *unit, struct arange *arange,
+              bfd_uint64_t offset)
+{
+  bfd_byte *rngs_ptr;
+  bfd_byte *rngs_end;
+  bfd_vma base_address = unit->base_address;
+  bfd_vma low_pc;
+  bfd_vma high_pc;
+  bfd *abfd = unit->abfd;
+
+  if (! unit->file->dwarf_rnglists_buffer)
+    {
+      if (! read_debug_rnglists (unit))
+       return FALSE;
+    }
+
+  rngs_ptr = unit->file->dwarf_rnglists_buffer + offset;
+  if (rngs_ptr < unit->file->dwarf_rnglists_buffer)
+    return FALSE;
+  rngs_end = unit->file->dwarf_rnglists_buffer;
+  rngs_end +=  unit->file->dwarf_rnglists_size;
+
+  for (;;)
+    {
+      enum dwarf_range_list_entry rlet;
+      unsigned int bytes_read;
+
+      if (rngs_ptr + 1 > rngs_end)
+       return FALSE;
+
+      rlet = read_1_byte (abfd, rngs_ptr, rngs_end);
+      rngs_ptr++;
+
+      switch (rlet)
+       {
+       case DW_RLE_end_of_list:
+         return TRUE;
+
+       case DW_RLE_base_address:
+         if (rngs_ptr + unit->addr_size > rngs_end)
+           return FALSE;
+         base_address = read_address (unit, rngs_ptr, rngs_end);
+         rngs_ptr += unit->addr_size;
+         continue;
+
+       case DW_RLE_start_length:
+         if (rngs_ptr + unit->addr_size > rngs_end)
+           return FALSE;
+         low_pc = read_address (unit, rngs_ptr, rngs_end);
+         rngs_ptr += unit->addr_size;
+         high_pc = low_pc;
+         high_pc += _bfd_safe_read_leb128 (abfd, rngs_ptr, &bytes_read,
+                                           FALSE, rngs_end);
+         rngs_ptr += bytes_read;
+         break;
+
+       case DW_RLE_offset_pair:
+         low_pc = base_address;
+         low_pc += _bfd_safe_read_leb128 (abfd, rngs_ptr, &bytes_read,
+                                          FALSE, rngs_end);
+         high_pc = base_address;
+         high_pc += _bfd_safe_read_leb128 (abfd, rngs_ptr, &bytes_read,
+                                           FALSE, rngs_end);
+         break;
+
+       case DW_RLE_start_end:
+         if (rngs_ptr + 2 * unit->addr_size > rngs_end)
+           return FALSE;
+         low_pc = read_address (unit, rngs_ptr, rngs_end);
+         rngs_ptr += unit->addr_size;
+         high_pc = read_address (unit, rngs_ptr, rngs_end);
+         rngs_ptr += unit->addr_size;
+         break;
+
+       /* TODO x-variants need .debug_addr support used for split-dwarf.  */
+       case DW_RLE_base_addressx:
+       case DW_RLE_startx_endx:
+       case DW_RLE_startx_length:
+       default:
+         return FALSE;
+       }
+
+      if ((low_pc == 0 && high_pc == 0) || low_pc == high_pc)
+       return FALSE;
+
+      if (!arange_add (unit, arange, low_pc, high_pc))
+       return FALSE;
+    }
+}
+
+static bfd_boolean
+read_rangelist (struct comp_unit *unit, struct arange *arange,
+               bfd_uint64_t offset)
+{
+  if (unit->version <= 4)
+    return read_ranges (unit, arange, offset);
+  else
+    return read_rnglists (unit, arange, offset);
+}
+
 static struct varinfo *
 lookup_var_by_offset (bfd_uint64_t offset, struct varinfo * table)
 {
index 8bfcfaa7a78619e4489dc165de06dbba99791935..2e7fecee8ca6438363655920b24a6b48e754c002 100644 (file)
@@ -1,3 +1,11 @@
+2020-08-25  Nick Clifton  <nickc@redhat.com>
+
+       Backport from the mainline:
+       2020-08-21  Mark Wielaard  <mark@klomp.org>
+
+       * testsuite/binutils-all/readelf.exp (readelf_wi_test): Also
+       recognize DW_LANG_C11.
+
 2020-08-12  Nick Clifton  <nickc@redhat.com>
 
        * po/sr.po: Updated Serbian translation.
index 0ca27482229ad04ddbc09596edac5d4b87f86d4f..8a62eeff582f9a1e059dc31da4cb84dc3fc5f5e8 100644 (file)
@@ -188,7 +188,7 @@ proc readelf_wi_test {} {
        ".*DW_TAG_subprogram.*"
        ".*DW_TAG_base_type.*"
        ".*DW_AT_producer.*(GNU C|indirect string).*"
-       ".*DW_AT_language.*ANSI C.*"
+       ".*DW_AT_language.*(ANSI C|C11).*"
        ".*DW_AT_name.*(testprog.c|indirect string).*"
        ".*DW_AT_name.*fn.*"
        ".*DW_AT_name.*(main|indirect string).*"