binutils/dwarf: Don't print duplicate range list entries

Message ID 20200429095200.2193783-1-andrew.burgess@embecosm.com
State New
Headers show
Series
  • binutils/dwarf: Don't print duplicate range list entries
Related show

Commit Message

Andrew Burgess April 29, 2020, 9:52 a.m.
If multiple DWARF entries reference the same offset in the
.debug_ranges section then we will currently print duplicate range
lists when dumping the range information.

This looks something like this:

  Contents of the .debug_ranges section:

      Offset   Begin    End
      00000000 0000000000401160 00000000004011ca
      00000000 0000000000401040 0000000000401045
      00000000 <End of list>
      00000030 0000000000401169 0000000000401173
      00000030 0000000000401040 0000000000401045
      00000030 <End of list>
      00000030 0000000000401169 0000000000401173
      00000030 0000000000401040 0000000000401045
      00000030 <End of list>
      00000070 0000000000401160 00000000004011ca
      00000070 0000000000401040 0000000000401045
      00000070 0000000000401050 0000000000401065
      00000070 <End of list>

Notice the range of offset 0x30 is printed twice.

This patch adds some filtering when printing the ranges list, so these
duplicates are ignored.  After this patch the same output as above
would look like this:

  Contents of the .debug_ranges section:

      Offset   Begin    End
      00000000 0000000000401160 00000000004011ca
      00000000 0000000000401040 0000000000401045
      00000000 <End of list>
      00000030 0000000000401169 0000000000401173
      00000030 0000000000401040 0000000000401045
      00000030 <End of list>
      00000070 0000000000401160 00000000004011ca
      00000070 0000000000401040 0000000000401045
      00000070 0000000000401050 0000000000401065
      00000070 <End of list>

binutils/ChangeLog:

	* dwarf.c (display_debug_ranges): Ignore duplicate entries in
	range_entries for the same offset.
---
 binutils/ChangeLog |  5 +++++
 binutils/dwarf.c   | 10 ++++++++++
 2 files changed, 15 insertions(+)

-- 
2.25.3

Comments

David Faust via Binutils April 29, 2020, 12:21 p.m. | #1
Hi Andrew,

> If multiple DWARF entries reference the same offset in the

> .debug_ranges section then we will currently print duplicate range

> lists when dumping the range information.


But isn't this something that the user might want to know ?  
Eg they might be testing to see if these duplicate ranges exist or not.

We already have the concept of a raw .debug_line dump vs a processed
.debug_line dump.  Perhaps we should extend this to the .debug_ranges
section too ?

Cheers
  Nick
Andrew Burgess April 29, 2020, 12:42 p.m. | #2
* Nick Clifton <nickc@redhat.com> [2020-04-29 13:21:03 +0100]:

> Hi Andrew,

> 

> > If multiple DWARF entries reference the same offset in the

> > .debug_ranges section then we will currently print duplicate range

> > lists when dumping the range information.

> 

> But isn't this something that the user might want to know ?  

> Eg they might be testing to see if these duplicate ranges exist or not.

> 

> We already have the concept of a raw .debug_line dump vs a processed

> .debug_line dump.  Perhaps we should extend this to the .debug_ranges

> section too ?


But the duplicates don't exist.

The parsing of the .debug_ranges is really driven by the use of
DW_AT_ranges within a debugging entity.  Each DW_AT_ranges stores its
offset into the debug_info objects range_list.

Then, when we print the .debug_ranges for each referenced offset we
create a range_entry structure.

Finally we sort all of the range_entry structures based on their
offset, and print them.

My assumption here is that some clever compilers "share" parts of
their range lists, so given a .debug_ranges table like this:

   OFFSET_0   START_1   END_1
   OFFSET_2   START_2   END_2
   OFFSET_4   START_3   END_3
   OFFSET_6         0       0

One DW_AT_ranges can reference offset 0, and another can reference
offset 2, and another offset 4.  We would then print this like:

      Offset   Begin    End
      OFFSET_0 START_1  END_1
      OFFSET_0 START_2  END_2
      OFFSET_0 START_3  END_3
      OFFSET_0 <End of list>
      OFFSET_2 START_2  END_2
      OFFSET_2 START_3  END_3
      OFFSET_2 <End of list>
      OFFSET_4 START_3  END_3
      OFFSET_4 <End of list>

Which makes sense I think.  However, if what you instead have is
references to offset 0, offset 2, and offset 2, then you'll see this:

      Offset   Begin    End
      OFFSET_0 START_1  END_1
      OFFSET_0 START_2  END_2
      OFFSET_0 START_3  END_3
      OFFSET_0 <End of list>
      OFFSET_2 START_2  END_2
      OFFSET_2 START_3  END_3
      OFFSET_2 <End of list>
      OFFSET_2 START_2  END_2
      OFFSET_2 START_3  END_3
      OFFSET_2 <End of list>

Yes, the duplication does reflect the duplicate references, bug given
that when we print the DW_AT_ranges, all we see is:

     DW_AT_ranges	: OFFSET_2

When the user then goes to look at the .debug_ranges section it can be
confusing to see two lists both at OFFSET_2, at least, it confused me.

I can update the commit message if you think the patch is worth while
to better explain things.  Just let me know.

Thanks,
Andrew
David Faust via Binutils April 29, 2020, 4:23 p.m. | #3
Hi Andrew,

> But the duplicates don't exist.

> 

> The parsing of the .debug_ranges is really driven by the use of

> DW_AT_ranges within a debugging entity.  Each DW_AT_ranges stores its

> offset into the debug_info objects range_list.


Doh - sorry, I had misunderstood where the duplicates originated.

So in which case the patch is fine and I have gone ahead and applied it.

Cheers
  Nick

Patch

diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index c75059bd93a..e75bfb8bf70 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -6923,6 +6923,7 @@  display_debug_ranges (struct dwarf_section *section,
   int is_rnglists = strstr (section->name, "debug_rnglists") != NULL;
   /* Initialize it due to a false compiler warning.  */
   unsigned char address_size = 0;
+  dwarf_vma last_offset = 0;
 
   if (bytes == 0)
     {
@@ -7063,6 +7064,15 @@  display_debug_ranges (struct dwarf_section *section,
       next = section_begin + offset;
       base_address = debug_info_p->base_address;
 
+      /* If multiple DWARF entities reference the same range then we will
+         have multiple entries in the `range_entries' list for the same
+         offset.  Thanks to the sort above these will all be consecutive in
+         the `range_entries' list, so we can easily ignore duplicates
+         here.  */
+      if (i > 0 && last_offset == offset)
+        continue;
+      last_offset = offset;
+
       /* PR 17512: file: 001-101485-0.001:0.1.  */
       if (pointer_size < 2 || pointer_size > 8)
 	{