public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Caroline Tice <cmtice@google.com>
To: Tom Tromey <tom@tromey.com>
Cc: Caroline Tice via Gdb-patches <gdb-patches@sourceware.org>,
	Eric Christopher <echristo@google.com>
Subject: Re: [PATCH] Fix issues with reading rnglists, especially from dwo files, for DWARF v5
Date: Tue, 9 Jun 2020 16:32:15 -0700	[thread overview]
Message-ID: <CABtf2+RRjkCa4gkyAsRwxGwqkJ5g=jyN7uk7Au7ym5y4+qCrqw@mail.gmail.com> (raw)
In-Reply-To: <CABtf2+SZUXnSNHNJpm7LFU2vg1cd=62dzX2_LKfc98yaeQhGDw@mail.gmail.com>

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

While playing with this a bit more (getting ready to work on my .dwp
file patch), I noticed that there was an important bit I left out of
the original patch: dwarf2_rnglists_process, in the original code,
always reads out of the rnglist section in the main objfile, even when
there is a .rnglist section in a .dwo file that it should be reading
instead.  I had some local code that fixes this, but it didn't make it
into my previous patch (I apologize for that).  The attached patch has
been updated to contain this fix as well.  It also contains my fixes
and testcase from the previous patch.

I ran the testsuite again (adding the -gdwarf-5 and -gsplit-dwarf
flags in testsuite/lib/gdb.exp), and compiling everything with clang:

$ make check RUNTESTFLAGS="CC_FOR_TARGET=${CLANG_CC}
CXX_FOR_TARGET=${CLANG_CXX}"

This time my patched GDB passed quite a few tests that the unpatched
version failed (when compiled with clang and passed the flags):

Testsuite summary from unpatched GDB:

=== gdb Summary ===
# of expected passes 55725
# of unexpected failures 2956
# of unexpected successes 83
# of expected failures 169
# of known failures 57
# of unresolved testcases 115
# of untested testcases 175
# of unsupported tests 272
# of paths in test names 1
# of duplicate test names 269


Testsuite summary from patched GDB:

=== gdb Summary ===

# of expected passes 56173
# of unexpected failures 2523
# of unexpected successes 2
# of expected failures 250
# of known failures 57
# of unresolved testcases 111
# of untested testcases 174
# of unsupported tests 272
# of paths in test names 1
# of duplicate test names 269

Some of the tests that have more passes with the patch include:
gdb.base/break-entry.exp, gdb.base/info-fun.exp,
gdb.base/info-shared.exp,gdb.base/return-nodebug.exp,
gdb.dwarf2/fission-base.exp
(I can send you a complete list if you really want it)

Anyway below is the updated patch for review.

-- Caroline
cmtice@google.com

gdb/ChangeLog:

2020-06-09  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 dwarf2_cu): Add cu_ranges_from_skeleton field.
        (struct dwo_sections): Add rnglists field.
        (dwarf2_ranges_read): Add tag parameter.
        (cu_debug_rnglist_section): New function (decl & definition).
        (cutu_reader::cutu_reader): Before replacing the skeleton unit
        comp_unit_die with the dwo comp_unit_die, check to see if the skeleton
        unit die has a DW_AT_ranges, and if so set the cu_ranges_from_skeleton
        field in the cu.
        (dwarf2_locate_dwo_sections): Add code to read rnglists_dwo section.
        (dwarf2_rnglists_process): Add a dwarf_tag parameter, for the kind of
        die whose range is being checked; add code to read the rnglist section
        from the dwo file rather than from the main objfile, if appropriate.
        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).
        (dwarf2_ranges_process): Add dwarf tag parameter and pass it to
        dwarf2_rnglists_process.
        (dwarf2_ranges_read): Add dwarf tag parameter and pass it to
        dwarf2_ranges_process.
        (dwarf2_get_pc_bounds): Check for DW_FORM_rnglistx when setting
        need_ranges_base.  Also pass die tag to dwarf2_ranges_read.
        (dwarf2_record_block_ranges): Check for DW_FORM_rnglistx when setting
        need_ranges_base.  Also pass die tag to dwarf2_ranges_read.
        (read_full_die_1): Add code to read DW_AT_rnglists_base and assign to
        cu->ranges_base.
        (partial_die_info::read): Check for DW_FORM_rnglistx when setting
        need_ranges_base.  Also pass die tag to dwarf2_ranges_read.
        (read_rnglist_index): New function.
        (read_attribute_reprocess):  Add code for DW_FORM_rnglistx.
        (read_attribute_value): Mark DW_FORM_rnglistx with need_reprocess.

gdb/testsuite/ChangeLog:

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

        * gdb.dwarf2/dw5-rnglist-test.cc: New file.
        * gdb.dwarf2/dw5-rnglist-test.exp: New file.


On Thu, Jun 4, 2020 at 2:39 PM Caroline Tice <cmtice@google.com> wrote:
>
> I've been playing with running the testsuite with -gdwarf-5
> -gsplit-dwarf and using the clang compiler. I did not find any tests
> that showed the issues I was running into (but I did discover a small
> bug in my patch, which my newer patch fixes).  With my fixed patch,
> there are no testsuite differences.  I have created a new testsuite
> test case, which does fail with current ToT and passes with my patch,
> but that only works if you compile it with clang -- if you compile it
> with GCC it passes in both cases (because GCC is not generating the
> DW_FORM_rmglistx that my patch is handling/fixing).
>
> I've updated the patch to include the requested format changes, remove
> the pieces that are only used in an upcoming patch,  fix the small
> issue I found while testing, and I've added the test to the testsuite.
> To run the test and see the issue:
>
> $  make check RUNTESTFLAGS="CC_FOR_TARGET=${CLANG_CC}
> CXX_FOR_TARGET=${CLANG_CXX} dw5-rnglist-test.exp"
>
> gdb/ChangeLog (updated)
>
> 2020-06-04  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_sections): Add rnglists field.
>         (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).
>         (dwarf2_get_pc_bounds): Check for DW_FORM_rnglistx when setting
>         need_ranges_base.
>         (dwarf2_record_block_ranges): Check for DW_FORM_rnglistx when setting
>         need_ranges_base.
>         (read_full_die_1): Add code to read DW_AT_rnglists_base and assign to
>         cu->ranges_base.
>         (partial_die_info::read): Check for DW_FORM_rnglistx when setting
>         need_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.
>
> gdb/testsuite/ChangeLog:
>
> 2020-06-04  Caroline Tice  <cmtice@google.com>
>
>         * gdb.dwarf2/dw5-rnglist-test.cc: New file.
>         * gdb.dwarf2/dw5-rnglist-test.exp: New file.
>
>
>
>
>
> On Wed, Jun 3, 2020 at 7:49 AM Tom Tromey <tom@tromey.com> wrote:
> >
> > Caroline> $ clang++ -gdwarf-5 -O0 -gsplit-dwarf pre-order.cpp
> > Caroline> pre-order-common.cpp -o pre-order
> >
> > I wonder if the test suite can be run this way.
> >
> > Caroline> Oh.  Those get used in my next upcoming patch (where I update GDB to
> > Caroline> handle DWARFv5 .dwp files).  I can either leave them in this patch, or
> > Caroline> remove them from here and put them in the next one, whichever you
> > Caroline> prefer.
> >
> > I think it's better for patches to be reasonably self-contained when
> > possible.
> >
> > Also, there were other patches for DWARFv5 on the list in "recent" (this
> > year) times.  I wonder if those are relevant / related.
> >
> > Tom

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

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index e6566f9649..e6031c4683 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" },
@@ -448,6 +450,9 @@ struct dwarf2_cu
   /* Base address of this compilation unit.  */
   gdb::optional<CORE_ADDR> base_address;
 
+  /* CU rnglist ranges came from skeleton unit. */
+  bool cu_ranges_from_skeleton = false;
+
   /* The language we are debugging.  */
   enum language language = language_unknown;
   const struct language_defn *language_defn = nullptr;
@@ -650,6 +655,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.  */
@@ -1379,11 +1385,16 @@ static void read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu);
 static void read_variable (struct die_info *die, struct dwarf2_cu *cu);
 
 static int dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *,
-			       struct dwarf2_cu *, dwarf2_psymtab *);
+			       struct dwarf2_cu *, dwarf2_psymtab *,
+			       dwarf_tag);
 
 /* 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
@@ -7181,6 +7192,11 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
 	      dummy_p = true;
 	      return;
 	    }
+          /* if (dwarf2_attr_no_follow (comp_unit_die, DW_AT_ranges)) */
+          if (comp_unit_die->attr (DW_AT_ranges) != nullptr)
+            {
+              cu->cu_ranges_from_skeleton = true;
+            }
 	  comp_unit_die = dwo_comp_unit_die;
 	}
       else
@@ -12397,6 +12413,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;
@@ -13741,7 +13762,7 @@ read_variable (struct die_info *die, struct dwarf2_cu *cu)
 template <typename Callback>
 static bool
 dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
-			 Callback &&callback)
+			 dwarf_tag tag, Callback &&callback)
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
   struct objfile *objfile = per_objfile->objfile;
@@ -13751,17 +13772,40 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
   const gdb_byte *buffer;
   CORE_ADDR baseaddr;
   bool overflow = false;
+  ULONGEST addr_index;
+  bool ignore_dwo_unit = false;
+  struct dwarf2_section_info *rnglists_section;
 
   base = cu->base_address;
 
-  per_objfile->per_bfd->rnglists.read (objfile);
-  if (offset >= per_objfile->per_bfd->rnglists.size)
+  /* If the DW_AT_ranges attribute was part of a DW_TAG_skeleton_unit that was
+     changed into a DW_TAG_compile_unit after calling read_cutu_die_from_dwo,
+     we want to use the rnglist in the objfile rather than the one in the
+     dwo_unit. */
+  if (tag == DW_TAG_compile_unit &&
+      cu->cu_ranges_from_skeleton)
+    ignore_dwo_unit = true;
+
+  /* Elsee, if there's a dwo_unit, we want the rnglist from the dwo file.  */
+  if (cu->dwo_unit &&
+      cu->dwo_unit->dwo_file->sections.rnglists.size > 0 &&
+      !ignore_dwo_unit)
+    {
+      rnglists_section = &cu->dwo_unit->dwo_file->sections.rnglists;
+    }
+  else
+    {
+      rnglists_section = &per_objfile->per_bfd->rnglists;
+    }
+
+  rnglists_section->read (objfile);
+  if (offset >= rnglists_section->size)
     {
       complaint (_("Offset %d out of bounds for DW_AT_ranges attribute"),
 		 offset);
       return false;
     }
-  buffer = per_objfile->per_bfd->rnglists.buffer + offset;
+  buffer = rnglists_section->buffer + offset;
 
   baseaddr = objfile->text_section_offset ();
 
@@ -13769,8 +13813,8 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
     {
       /* Initialize it due to a false compiler warning.  */
       CORE_ADDR range_beginning = 0, range_end = 0;
-      const gdb_byte *buf_end = (per_objfile->per_bfd->rnglists.buffer
-				 + per_objfile->per_bfd->rnglists.size);
+      const gdb_byte *buf_end = (rnglists_section->buffer
+				 + rnglists_section->size);
       unsigned int bytes_read;
 
       if (buffer == buf_end)
@@ -13792,6 +13836,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 +13859,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 +13900,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 +13941,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.  */
@@ -13900,7 +13979,7 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
 
 template <typename Callback>
 static int
-dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu,
+dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, dwarf_tag tag,
 		       Callback &&callback)
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
@@ -13916,7 +13995,7 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu,
   CORE_ADDR baseaddr;
 
   if (cu_header->version >= 5)
-    return dwarf2_rnglists_process (offset, cu, callback);
+    return dwarf2_rnglists_process (offset, cu, tag, callback);
 
   base = cu->base_address;
 
@@ -14002,7 +14081,7 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu,
 static int
 dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
 		    CORE_ADDR *high_return, struct dwarf2_cu *cu,
-		    dwarf2_psymtab *ranges_pst)
+		    dwarf2_psymtab *ranges_pst, dwarf_tag tag)
 {
   struct objfile *objfile = cu->per_objfile->objfile;
   struct gdbarch *gdbarch = objfile->arch ();
@@ -14012,7 +14091,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
   CORE_ADDR high = 0;
   int retval;
 
-  retval = dwarf2_ranges_process (offset, cu,
+  retval = dwarf2_ranges_process (offset, cu, tag,
     [&] (CORE_ADDR range_beginning, CORE_ADDR range_end)
     {
       if (ranges_pst != NULL)
@@ -14105,7 +14184,8 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
 	  /* DW_AT_rnglists_base does not apply to DIEs from the DWO skeleton.
 	     We take advantage of the fact that DW_AT_ranges does not appear
 	     in DW_TAG_compile_unit of DWO files.  */
-	  int need_ranges_base = die->tag != DW_TAG_compile_unit;
+	  int need_ranges_base = (die->tag != DW_TAG_compile_unit
+				  && attr->form != DW_FORM_rnglistx);
 	  unsigned int ranges_offset = (DW_UNSND (attr)
 					+ (need_ranges_base
 					   ? cu->ranges_base
@@ -14113,7 +14193,8 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
 
 	  /* Value of the DW_AT_ranges attribute is the offset in the
 	     .debug_ranges section.  */
-	  if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu, pst))
+	  if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu, pst,
+				   die->tag))
 	    return PC_BOUNDS_INVALID;
 	  /* Found discontinuous range of addresses.  */
 	  ret = PC_BOUNDS_RANGES;
@@ -14276,7 +14357,8 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
       /* DW_AT_rnglists_base does not apply to DIEs from the DWO skeleton.
 	 We take advantage of the fact that DW_AT_ranges does not appear
 	 in DW_TAG_compile_unit of DWO files.  */
-      int need_ranges_base = die->tag != DW_TAG_compile_unit;
+      int need_ranges_base = (die->tag != DW_TAG_compile_unit
+			      && attr->form != DW_FORM_rnglistx);
 
       /* The value of the DW_AT_ranges attribute is the offset of the
          address range list in the .debug_ranges section.  */
@@ -14284,7 +14366,7 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
 			      + (need_ranges_base ? cu->ranges_base : 0));
 
       std::vector<blockrange> blockvec;
-      dwarf2_ranges_process (offset, cu,
+      dwarf2_ranges_process (offset, cu, die->tag,
 	[&] (CORE_ADDR start, CORE_ADDR end)
 	{
 	  start += baseaddr;
@@ -18115,6 +18197,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;
@@ -18633,7 +18720,8 @@ partial_die_info::read (const struct die_reader_specs *reader,
 	    /* It would be nice to reuse dwarf2_get_pc_bounds here,
 	       but that requires a full DIE, so instead we just
 	       reimplement it.  */
-	    int need_ranges_base = tag != DW_TAG_compile_unit;
+	    int need_ranges_base = (tag != DW_TAG_compile_unit
+				    && attr.form != DW_FORM_rnglistx);
 	    unsigned int ranges_offset = (DW_UNSND (&attr)
 					  + (need_ranges_base
 					     ? cu->ranges_base
@@ -18642,7 +18730,7 @@ partial_die_info::read (const struct die_reader_specs *reader,
 	    /* Value of the DW_AT_ranges attribute is the offset in the
 	       .debug_ranges section.  */
 	    if (dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, cu,
-				    nullptr))
+				    nullptr, tag))
 	      has_pc_info = 1;
 	  }
 	  break;
@@ -19043,6 +19131,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 +19192,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 +19376,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 +23468,25 @@ 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;
+
+      if (sections->rnglists.size > 0)
+	return &sections->rnglists;
+    }
+  return &dwarf2_per_objfile->per_bfd->rnglists;
+}
+
 /* A helper function that fills in a dwarf2_loclist_baton.  */
 
 static void
diff --git a/testsuite/gdb.dwarf2/dw5-rnglist-test.cc b/testsuite/gdb.dwarf2/dw5-rnglist-test.cc
new file mode 100644
index 0000000..4d650e1279
--- /dev/null
+++ b/testsuite/gdb.dwarf2/dw5-rnglist-test.cc
@@ -0,0 +1,71 @@
+#include <iostream>
+#include <vector>
+
+struct node {
+  int id;
+  node *left;
+  node *right;
+  bool visited;
+};
+
+node  node_array[50];
+unsigned int CUR_IDX = 0;
+
+node * make_node (int val)
+{
+  node *new_node = &(node_array[CUR_IDX++]);
+  new_node->left = NULL;
+  new_node->right = NULL;
+  new_node->id = val;
+  new_node->visited = false;
+
+  return new_node;
+}
+
+void tree_insert (node *root, int val)
+{
+  if (val < root->id)
+    {
+      if (root->left)
+        tree_insert (root->left, val);
+      else
+        root->left = make_node(val);
+    }
+  else if (val > root->id)
+    {
+      if (root->right)
+        tree_insert (root->right, val);
+      else
+        root->right = make_node(val);
+    }
+}
+
+void inorder(node *root) {
+  std::vector<node *> todo;
+  todo.push_back(root);
+  while (!todo.empty()){
+    node *curr = todo.back();
+    todo.pop_back(); /* break-here */
+    if (curr->visited) {
+      std::cout << curr->id << " ";
+    } else {
+      curr->visited = true;
+      if (curr->right) { todo.push_back(curr->right); }
+      todo.push_back(curr);
+      if (curr->left) { todo.push_back(curr->left); }
+    }
+  }
+}
+
+int main (int argc, char **argv)
+{
+  node *root = make_node (35);
+
+  tree_insert (root, 28);
+  tree_insert (root, 20);
+  tree_insert (root, 60);
+
+  inorder (root);
+
+  return 0;
+}
diff --git a/testsuite/gdb.dwarf2/dw5-rnglist-test.exp b/testsuite/gdb.dwarf2/dw5-rnglist-test.exp
new file mode 100644
index 0000000..b5c6c3bfe3
--- /dev/null
+++ b/testsuite/gdb.dwarf2/dw5-rnglist-test.exp
@@ -0,0 +1,40 @@
+# Copyright 2011-2020 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Check that GDB can find the variables in a lexical block with a
+# DW_FORM_rnglistx DW_AT_ranges field.  This test is intended for DWARF-5,
+# compiled with clang++.
+
+standard_testfile .cc
+
+# This test is intended for targets which support DWARF-5.
+# Since we pass an explicit -gdwarf-5 to the compiler,
+# we let that be the test of whether the target supports it.
+
+if { [prepare_for_testing "failed to prepare" "${testfile}" \
+          $srcfile {debug c++ additional_flags=-gdwarf-5 \
+                        additional_flags=-O0}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_breakpoint [gdb_get_line_number "break-here"]
+gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+gdb_test "print curr" "\\\(node \\\*\\\) $hex <node_array>"
+gdb_test "print *curr" "= {id = 35, left = $hex <node_array\\+$decimal>, right = $hex <node_array\\+$decimal>, visited = false}"

  reply	other threads:[~2020-06-09 23:32 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-01 17:16 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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CABtf2+RRjkCa4gkyAsRwxGwqkJ5g=jyN7uk7Au7ym5y4+qCrqw@mail.gmail.com' \
    --to=cmtice@google.com \
    --cc=echristo@google.com \
    --cc=gdb-patches@sourceware.org \
    --cc=tom@tromey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).