public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Fix issues with reading rnglists, especially from dwo files,  for DWARF v5
@ 2020-06-01 17:16 Caroline Tice
  2020-06-01 20:33 ` Tom Tromey
  0 siblings, 1 reply; 29+ messages in thread
From: Caroline Tice @ 2020-06-01 17:16 UTC (permalink / raw)
  To: gdb-patches; +Cc: Caroline Tice, Eric Christopher, Stan Shebs

[-- Attachment #1: Type: text/plain, Size: 1842 bytes --]

While experimenting with GDB on DWARF 5 with split debug (dwo files),
I discovered that GDB was not reading the rnglist index
properly (it needed to be reprocessed in the same way the loclist
index does), and that there was no code for reading rnglists out of
dwo files at all.  Also, the rnglist address reading function
(dwarf2_rnglists_process) was adding the base address to all rnglist
entries, when it's only supposed to add it to the DW_RLE_offset_pair
entries (http://dwarfstd.org/doc/DWARF5.pdf, p. 53), and was not
handling several entry types.

This patch fixes these issues.  I verified that it fixes the issues I
saw and that it does not cause any testsuite regressions (on x86_64
ubuntu linux).  Is there anything else I need to do? Is this Ok to
commit?

-- Caroline Tice
cmtice@google.com

gdb/ChangeList:

2020-06-01  Caroline Tice  <cmtice@google.com>

        * dwarf2/read.c (struct dwop_section_names): Add rnglists_dwo.
        (dwop_section_names): Add .debug_rnglists.dwo, .zdebug_rnglists.dwo.
        (struct dwo_sectionds): Add rnglists field.
        (struct virtual_v2_dwo_sections): Add loclists_offset, loclists_size,
        rnglists_offset, rnglists_size.
        (cu_debug_rnglist_section): New function (decl & definition).
        (dwarf2_locate_dwo_sections): Add code to read rnglists_dwo section.
        (dwarf2_rnglists_process): Add cases for DW_RLE_base_addressx,
        DW_RLE_startx_length, DW_RLE_startx_endx.  Also, update to only add
        the base address to DW_RLE_offset_pairs (not to all ranges).
        (read_full_die_1): Add code to read DW_AT_rnglists_base and assign to
        cu->ranges_base.
        (read_rnglist_index): New function.
        (read_attribute_reprocess):  Add code for DW_FORM_rnglistx.
        (read_attribute_value): Mark DW_FORM_rnglistx with need_reprocess.

[-- Attachment #2: gdb-dwo-rnglists.patch --]
[-- Type: application/octet-stream, Size: 9666 bytes --]

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index e6566f9649..bcc5d3b90d 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -340,6 +340,7 @@ static const struct dwop_section_names
   struct dwarf2_section_names loclists_dwo;
   struct dwarf2_section_names macinfo_dwo;
   struct dwarf2_section_names macro_dwo;
+  struct dwarf2_section_names rnglists_dwo;
   struct dwarf2_section_names str_dwo;
   struct dwarf2_section_names str_offsets_dwo;
   struct dwarf2_section_names types_dwo;
@@ -355,6 +356,7 @@ dwop_section_names =
   { ".debug_loclists.dwo", ".zdebug_loclists.dwo" },
   { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo" },
   { ".debug_macro.dwo", ".zdebug_macro.dwo" },
+  { ".debug_rnglists.dwo", ".zdebug_rnglists.dwo" },
   { ".debug_str.dwo", ".zdebug_str.dwo" },
   { ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo" },
   { ".debug_types.dwo", ".zdebug_types.dwo" },
@@ -650,6 +652,7 @@ struct dwo_sections
   struct dwarf2_section_info loclists;
   struct dwarf2_section_info macinfo;
   struct dwarf2_section_info macro;
+  struct dwarf2_section_info rnglists;
   struct dwarf2_section_info str;
   struct dwarf2_section_info str_offsets;
   /* In the case of a virtual DWO file, these two are unused.  */
@@ -793,12 +796,18 @@ struct virtual_v2_dwo_sections
   bfd_size_type loc_offset;
   bfd_size_type loc_size;
 
+  bfd_size_type loclists_offset;
+  bfd_size_type loclists_size;
+
   bfd_size_type macinfo_offset;
   bfd_size_type macinfo_size;
 
   bfd_size_type macro_offset;
   bfd_size_type macro_size;
 
+  bfd_size_type rnglists_offset;
+  bfd_size_type rnglists_size;
+
   bfd_size_type str_offsets_offset;
   bfd_size_type str_offsets_size;
 
@@ -1384,6 +1393,10 @@ static int dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *,
 /* Return the .debug_loclists section to use for cu.  */
 static struct dwarf2_section_info *cu_debug_loc_section (struct dwarf2_cu *cu);
 
+/* Return the .debug_rnglists section to use for cu.  */
+static struct dwarf2_section_info *cu_debug_rnglist_section (struct
+							     dwarf2_cu *cu);
+
 /* How dwarf2_get_pc_bounds constructed its *LOWPC and *HIGHPC return
    values.  Keep the items ordered with increasing constraints compliance.  */
 enum pc_bounds_kind
@@ -12397,6 +12410,11 @@ dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp, void *dwo_sections_ptr)
       dwo_sections->macro.s.section = sectp;
       dwo_sections->macro.size = bfd_section_size (sectp);
     }
+  else if (section_is_p (sectp->name, &names->rnglists_dwo))
+    {
+      dwo_sections->rnglists.s.section = sectp;
+      dwo_sections->rnglists.size = bfd_section_size (sectp);
+    }
   else if (section_is_p (sectp->name, &names->str_dwo))
     {
       dwo_sections->str.s.section = sectp;
@@ -13751,6 +13769,7 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
   const gdb_byte *buffer;
   CORE_ADDR baseaddr;
   bool overflow = false;
+  ULONGEST addr_index;
 
   base = cu->base_address;
 
@@ -13792,6 +13811,11 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
 	  base = cu->header.read_address (obfd, buffer, &bytes_read);
 	  buffer += bytes_read;
 	  break;
+        case DW_RLE_base_addressx:
+          addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+          buffer += bytes_read;
+          base = read_addr_index (cu, addr_index);
+          break;
 	case DW_RLE_start_length:
 	  if (buffer + cu->header.addr_size > buf_end)
 	    {
@@ -13810,6 +13834,19 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
 	      break;
 	    }
 	  break;
+        case DW_RLE_startx_length:
+          addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+          buffer += bytes_read;
+          range_beginning = read_addr_index (cu, addr_index);
+          if (buffer > buf_end)
+            {
+              overflow = true;
+              break;
+            }
+          range_end = (range_beginning
+                       + read_unsigned_leb128 (obfd, buffer, &bytes_read));
+          buffer += bytes_read;
+          break;
 	case DW_RLE_offset_pair:
 	  range_beginning = read_unsigned_leb128 (obfd, buffer, &bytes_read);
 	  buffer += bytes_read;
@@ -13838,7 +13875,20 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
 	  range_end = cu->header.read_address (obfd, buffer, &bytes_read);
 	  buffer += bytes_read;
 	  break;
-	default:
+        case DW_RLE_startx_endx:
+          addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+          buffer += bytes_read;
+          range_beginning = read_addr_index (cu, addr_index);
+          if (buffer > buf_end)
+            {
+              overflow = true;
+              break;
+            }
+          addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+          buffer += bytes_read;
+          range_end = read_addr_index (cu, addr_index);
+          break;
+ 	default:
 	  complaint (_("Invalid .debug_rnglists data (no base address)"));
 	  return false;
 	}
@@ -13866,8 +13916,12 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
       if (range_beginning == range_end)
 	continue;
 
-      range_beginning += *base;
-      range_end += *base;
+      /* Only DW_RLE_offset_pair needs the base address added.  */
+      if (rlet == DW_RLE_offset_pair)
+	{
+	  range_beginning += *base;
+	  range_end += *base;
+	}
 
       /* A not-uncommon case of bad debug info.
 	 Don't pollute the addrmap with bad data.  */
@@ -18115,6 +18169,11 @@ read_full_die_1 (const struct die_reader_specs *reader,
   auto maybe_addr_base = die->addr_base ();
   if (maybe_addr_base.has_value ())
     cu->addr_base = *maybe_addr_base;
+
+  attr =  die->attr (DW_AT_rnglists_base);
+  if (attr != nullptr)
+    cu->ranges_base = DW_UNSND (attr);
+
   for (int index : indexes_that_need_reprocess)
     read_attribute_reprocess (reader, &die->attrs[index]);
   *diep = die;
@@ -19043,6 +19102,49 @@ read_loclist_index (struct dwarf2_cu *cu, ULONGEST loclist_index)
     return bfd_get_64 (abfd, info_ptr) + loclist_base;
 }
 
+/* Given a DW_FORM_rnglistx value rnglist_index, fetch the offset from the
+   array of offsets in the .debug_rnglists section.  */
+static CORE_ADDR
+read_rnglist_index (struct dwarf2_cu *cu, ULONGEST rnglist_index)
+{
+  struct dwarf2_per_objfile *dwarf2_per_objfile = cu->per_objfile;
+  struct objfile *objfile = dwarf2_per_objfile->objfile;
+  bfd *abfd = objfile->obfd;
+  ULONGEST rnglist_header_size =
+    (cu->header.initial_length_size == 4 ? LOCLIST_HEADER_SIZE32
+     : LOCLIST_HEADER_SIZE64);
+  ULONGEST rnglist_base =
+      (cu->dwo_unit) ? rnglist_header_size : cu->ranges_base;
+
+  struct dwarf2_section_info *section = cu_debug_rnglist_section (cu);
+  if (section == nullptr)
+    error(_("Cannot find .debug_rnglists section [in module %s]"),
+	  objfile_name(objfile));
+  section->read (objfile);
+  if (section->buffer == NULL)
+    error(_("DW_FORM_rnglistx used without .debug_rnglists section "
+	    "[in module %s]"),
+       objfile_name (objfile));
+  struct loclist_header header;
+  read_loclist_header (&header, section);
+  if (rnglist_index >= header.offset_entry_count)
+    error(_("DW_FORM_rnglistx index pointing outside of "
+	    ".debug_rnglists offset array [in module %s]"),
+	    objfile_name(objfile));
+  if (rnglist_base + rnglist_index * cu->header.offset_size
+        >= section->size)
+    error(_("DW_FORM_rnglistx pointing outside of "
+            ".debug_rnglists section [in module %s]"),
+          objfile_name(objfile));
+  const gdb_byte *info_ptr
+    = section->buffer + rnglist_base + rnglist_index * cu->header.offset_size;
+
+  if (cu->header.offset_size == 4)
+    return read_4_bytes (abfd, info_ptr) + rnglist_base;
+  else
+    return read_8_bytes (abfd, info_ptr) + rnglist_base;
+}
+
 /* Process the attributes that had to be skipped in the first round. These
    attributes are the ones that need str_offsets_base or addr_base attributes.
    They could not have been processed in the first round, because at the time
@@ -19061,6 +19163,9 @@ read_attribute_reprocess (const struct die_reader_specs *reader,
       case DW_FORM_loclistx:
 	 DW_UNSND (attr) = read_loclist_index (cu, DW_UNSND (attr));
 	 break;
+      case DW_FORM_rnglistx:
+        DW_UNSND (attr) = read_rnglist_index (cu, DW_UNSND (attr));
+        break;
       case DW_FORM_strx:
       case DW_FORM_strx1:
       case DW_FORM_strx2:
@@ -19242,8 +19347,10 @@ read_attribute_value (const struct die_reader_specs *reader,
       DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
       break;
-    case DW_FORM_udata:
     case DW_FORM_rnglistx:
+      *need_reprocess = true;
+      /* FALLTHROUGH */
+    case DW_FORM_udata:
       DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
       break;
@@ -23332,6 +23439,24 @@ cu_debug_loc_section (struct dwarf2_cu *cu)
 				  : &per_objfile->per_bfd->loc);
 }
 
+/* Return the .debug_rnglists section to use for CU.  */
+static struct dwarf2_section_info *
+cu_debug_rnglist_section (struct dwarf2_cu *cu)
+{
+  if (cu->header.version < 5)
+    error (_(".debug_rnglists section cannot be used in DWARF %d"),
+	   cu->header.version);
+  struct dwarf2_per_objfile *dwarf2_per_objfile = cu->per_objfile;
+
+  if (cu->dwo_unit)
+    {
+      struct dwo_sections *sections = &cu->dwo_unit->dwo_file->sections;
+
+      return &sections->rnglists;
+    }
+  return &dwarf2_per_objfile->per_bfd->rnglists;
+}
+
 /* A helper function that fills in a dwarf2_loclist_baton.  */
 
 static void

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2020-07-16 16:09 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-01 17:16 [PATCH] Fix issues with reading rnglists, especially from dwo files, for DWARF v5 Caroline Tice
2020-06-01 20:33 ` Tom Tromey
2020-06-02 17:04   ` Caroline Tice
2020-06-03 14:49     ` Tom Tromey
2020-06-04 21:39       ` Caroline Tice
2020-06-09 23:32         ` Caroline Tice
2020-06-16 15:37           ` Caroline Tice
2020-06-18 20:27           ` Tom Tromey
2020-06-23 19:04             ` Caroline Tice
2020-07-01  0:09               ` Caroline Tice
2020-07-01  0:34               ` Simon Marchi
2020-07-01  0:36                 ` Simon Marchi
2020-07-01 19:57                   ` Caroline Tice
2020-07-02  5:41                     ` Simon Marchi
2020-07-03 22:47                       ` [PATCH V3] " Caroline Tice
2020-07-04  5:11                         ` Simon Marchi
2020-07-09 15:48                           ` [PATCH V4] " Caroline Tice
2020-07-11 17:54                             ` Simon Marchi
2020-07-14 15:47                               ` [PATCH V5] " Caroline Tice
2020-07-15  2:04                                 ` Simon Marchi
2020-07-15  3:15                                   ` Simon Marchi
2020-07-15 16:57                                     ` Caroline Tice
2020-07-15 17:04                                       ` H.J. Lu
2020-07-15 22:35                                         ` Caroline Tice
2020-07-16  2:34                                           ` Simon Marchi
2020-07-16  4:46                                             ` Caroline Tice
2020-07-16 15:41                                               ` Simon Marchi
2020-07-16 15:46                                                 ` Caroline Tice
2020-07-16 16:09                                                   ` Simon Marchi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).