From 76868f3606fb9de04f49c441c1e3cdd3e943a34d Mon Sep 17 00:00:00 2001 From: "H.J. Lu" 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)" + } + } +}