binutils/backport-dwarf-Also-match-abbrev-base-when-searching.patch

188 lines
6.7 KiB
Diff

From 76868f3606fb9de04f49c441c1e3cdd3e943a34d Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Thu, 29 Oct 2020 09:19:25 -0700
Subject: [PATCH] dwarf: Also match abbrev base when searching abbrev list
A .debug_abbrev section can have multiple CUs. When caching abbrev list,
we need to check abbrev base to support multiple CUs.
PR binutils/26808
* dwarf.c (abbrev_list): Add abbrev_base.
(new_abbrev_list): Add an abbrev_base argument and record it.
(find_abbrev_list_by_abbrev_offset): Add an abbrev_base argument
and match it.
(process_debug_info): Pass abbrev_base to new_abbrev_list and
find_abbrev_list_by_abbrev_offset.
(display_debug_abbrev): Pass 0 abbrev_base to new_abbrev_list
and find_abbrev_list_by_abbrev_offset.
* testsuite/binutils-all/x86-64/pr26808.dump: New file.
* testsuite/binutils-all/x86-64/pr26808.dwp.bz2: Likewise.
* testsuite/binutils-all/x86-64/x86-64.exp: Run PR binutils/26808
test.
---
binutils/dwarf.c | 52 +-
.../testsuite/binutils-all/x86-64/x86-64.exp | 31 +
2 files changed, 61 insertions(+), 22 deletions(-)
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 5cfa528594ff..14a7791c8cc4 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -876,6 +876,7 @@ typedef struct abbrev_list
{
abbrev_entry * first_abbrev;
abbrev_entry * last_abbrev;
+ dwarf_vma abbrev_base;
dwarf_vma abbrev_offset;
struct abbrev_list * next;
unsigned char * start_of_next_abbrevs;
@@ -955,10 +956,11 @@ free_all_abbrevs (void)
}
static abbrev_list *
-new_abbrev_list (dwarf_vma abbrev_offset)
+new_abbrev_list (dwarf_vma abbrev_base, dwarf_vma abbrev_offset)
{
abbrev_list * list = (abbrev_list *) xcalloc (sizeof * list, 1);
+ list->abbrev_base = abbrev_base;
list->abbrev_offset = abbrev_offset;
list->next = abbrev_lists;
@@ -968,12 +970,14 @@ new_abbrev_list (dwarf_vma abbrev_offset)
}
static abbrev_list *
-find_abbrev_list_by_abbrev_offset (dwarf_vma abbrev_offset)
+find_abbrev_list_by_abbrev_offset (dwarf_vma abbrev_base,
+ dwarf_vma abbrev_offset)
{
abbrev_list * list;
for (list = abbrev_lists; list != NULL; list = list->next)
- if (list->abbrev_offset == abbrev_offset)
+ if (list->abbrev_base == abbrev_base
+ && list->abbrev_offset == abbrev_offset)
return list;
return NULL;
@@ -3455,6 +3459,8 @@ process_debug_info (struct dwarf_section * section,
{
DWARF2_Internal_CompUnit compunit;
unsigned char * hdrptr;
+ dwarf_vma abbrev_base;
+ size_t abbrev_size;
dwarf_vma cu_offset;
unsigned int offset_size;
unsigned int initial_length_size;
@@ -3499,25 +3505,25 @@ process_debug_info (struct dwarf_section * section,
SAFE_BYTE_GET_AND_INC (compunit.cu_abbrev_offset, hdrptr, offset_size, end);
- list = find_abbrev_list_by_abbrev_offset (compunit.cu_abbrev_offset);
+ if (this_set == NULL)
+ {
+ abbrev_base = 0;
+ abbrev_size = debug_displays [abbrev_sec].section.size;
+ }
+ else
+ {
+ abbrev_base = this_set->section_offsets [DW_SECT_ABBREV];
+ abbrev_size = this_set->section_sizes [DW_SECT_ABBREV];
+ }
+
+ list = find_abbrev_list_by_abbrev_offset (abbrev_base,
+ compunit.cu_abbrev_offset);
if (list == NULL)
{
- dwarf_vma abbrev_base;
- size_t abbrev_size;
unsigned char * next;
- if (this_set == NULL)
- {
- abbrev_base = 0;
- abbrev_size = debug_displays [abbrev_sec].section.size;
- }
- else
- {
- abbrev_base = this_set->section_offsets [DW_SECT_ABBREV];
- abbrev_size = this_set->section_sizes [DW_SECT_ABBREV];
- }
-
- list = new_abbrev_list (compunit.cu_abbrev_offset);
+ list = new_abbrev_list (abbrev_base,
+ compunit.cu_abbrev_offset);
next = process_abbrev_set
(((unsigned char *) debug_displays [abbrev_sec].section.start
+ abbrev_base + compunit.cu_abbrev_offset),
@@ -3739,12 +3745,14 @@ process_debug_info (struct dwarf_section * section,
(unsigned long) debug_displays [abbrev_sec].section.size);
else
{
- list = find_abbrev_list_by_abbrev_offset (compunit.cu_abbrev_offset);
+ list = find_abbrev_list_by_abbrev_offset (abbrev_base,
+ compunit.cu_abbrev_offset);
if (list == NULL)
{
unsigned char * next;
- list = new_abbrev_list (compunit.cu_abbrev_offset);
+ list = new_abbrev_list (abbrev_base,
+ compunit.cu_abbrev_offset);
next = process_abbrev_set
(((unsigned char *) debug_displays [abbrev_sec].section.start
+ abbrev_base + compunit.cu_abbrev_offset),
@@ -6071,10 +6079,10 @@ display_debug_abbrev (struct dwarf_section *section,
dwarf_vma offset;
offset = start - section->start;
- list = find_abbrev_list_by_abbrev_offset (offset);
+ list = find_abbrev_list_by_abbrev_offset (0, offset);
if (list == NULL)
{
- list = new_abbrev_list (offset);
+ list = new_abbrev_list (0, offset);
start = process_abbrev_set (start, end, list);
list->start_of_next_abbrevs = start;
}
diff --git a/binutils/testsuite/binutils-all/x86-64/x86-64.exp b/binutils/testsuite/binutils-all/x86-64/x86-64.exp
index 7bd49ab619df..5f02ed35ade7 100644
--- a/binutils/testsuite/binutils-all/x86-64/x86-64.exp
+++ b/binutils/testsuite/binutils-all/x86-64/x86-64.exp
@@ -27,3 +27,34 @@ foreach t $test_list {
verbose [file rootname $t]
run_dump_test [file rootname $t]
}
+
+set t $srcdir/$subdir/pr26808.dwp.bz2
+# We need to strip the ".bz2", but can leave the dirname.
+set test $subdir/[file tail $t]
+set testname [file rootname $test]
+verbose $testname
+if {[catch "system \"bzip2 -dc $t > $tempfile\""] != 0} {
+ untested "bzip2 -dc ($testname)"
+} else {
+ send_log "$READELF -wi $tempfile > tmpdir/pr26808.out 2> /dev/null\n"
+ verbose "$READELF -wi $tempfile > tmpdir/pr26808.out 2> /dev/null" 1
+ set got [catch "system \"$READELF -wi $tempfile > tmpdir/pr26808.out 2> /dev/null\""]
+
+ if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]]} then {
+ fail $testname
+ } else {
+ send_log "cmp tmpdir/pr26808.out $srcdir/$subdir/pr26808.dump\n"
+ verbose "cmp tmpdir/pr26808.out $srcdir/$subdir/pr26808.dump" 1
+ set status [remote_exec build cmp "tmpdir/pr26808.out $srcdir/$subdir/pr26808.dump"]
+ set exec_output [lindex $status 1]
+ set exec_output [prune_warnings $exec_output]
+
+ if [string match "" $exec_output] then {
+ pass "readelf -wi ($testname)"
+ } else {
+ send_log "$exec_output\n"
+ verbose "$exec_output" 1
+ fail "readelf -wi ($testname)"
+ }
+ }
+}