From 50ea0877550b5fc2c31a44576cdba1b51897eb2c Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 13 Nov 2020 16:02:39 +0000 Subject: [PATCH] Fix readelf's and objdump's dislplay of DWO links when multiple links are present. PR 26829 * dwarf.c (struct dwo_info): Add cu_offset field. (add_dwo_info): Add cu_offset parameter. Record in new dwo_info struct. (add_dwo_name): Add cu_offset field. (add_dwo_dir): Add cu_offset field. (add_dwo_id): Add cu_offset field. (read_and_display_attr_value): Pass cu_offset to dwo recording functions. (load_separate_debug_files): Accumulate name, dir and id values and display once for each CU. * testsuite/binutils-all/dwo.sL Use a separate CU for the second dwo link. * testsuite/binutils-all/readelf.k2: Update expected output. --- binutils/ChangeLog | 17 ++++ binutils/dwarf.c | 95 ++++++++++++++-------- binutils/testsuite/binutils-all/dwo.s | 13 ++- binutils/testsuite/binutils-all/readelf.k2 | 2 +- 4 files changed, 87 insertions(+), 40 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 44192460cb6..6770c9b97f6 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,20 @@ +2020-11-13 Nick Clifton + + PR 26829 + * dwarf.c (struct dwo_info): Add cu_offset field. + (add_dwo_info): Add cu_offset parameter. Record in new dwo_info + struct. + (add_dwo_name): Add cu_offset field. + (add_dwo_dir): Add cu_offset field. + (add_dwo_id): Add cu_offset field. + (read_and_display_attr_value): Pass cu_offset to dwo recording + functions. + (load_separate_debug_files): Accumulate name, dir and id values + and display once for each CU. + * testsuite/binutils-all/dwo.sL Use a separate CU for the second + dwo link. + * testsuite/binutils-all/readelf.k2: Update expected output. + 2020-11-11 Bernd Edlinger * dwarf.c (display_debug_rnglists_list): Only bias the diff --git a/binutils/dwarf.c b/binutils/dwarf.c index c454d058b22..149755da1d0 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -67,6 +67,7 @@ typedef struct dwo_info { dwo_type type; const char * value; + dwarf_vma cu_offset; struct dwo_info * next; } dwo_info; @@ -1892,32 +1893,33 @@ get_AT_name (unsigned long attribute) } static void -add_dwo_info (const char * field, dwo_type type) +add_dwo_info (const char * value, dwarf_vma cu_offset, dwo_type type) { dwo_info * dwinfo = xmalloc (sizeof * dwinfo); - dwinfo->type = type; - dwinfo->value = field; - dwinfo->next = first_dwo_info; + dwinfo->type = type; + dwinfo->value = value; + dwinfo->cu_offset = cu_offset; + dwinfo->next = first_dwo_info; first_dwo_info = dwinfo; } static void -add_dwo_name (const char * name) +add_dwo_name (const char * name, dwarf_vma cu_offset) { - add_dwo_info (name, DWO_NAME); + add_dwo_info (name, cu_offset, DWO_NAME); } static void -add_dwo_dir (const char * dir) +add_dwo_dir (const char * dir, dwarf_vma cu_offset) { - add_dwo_info (dir, DWO_DIR); + add_dwo_info (dir, cu_offset, DWO_DIR); } static void -add_dwo_id (const char * id) +add_dwo_id (const char * id, dwarf_vma cu_offset) { - add_dwo_info (id, DWO_ID); + add_dwo_info (id, cu_offset, DWO_ID); } static void @@ -2876,16 +2878,16 @@ read_and_display_attr_value (unsigned long attribute, switch (form) { case DW_FORM_strp: - add_dwo_name ((const char *) fetch_indirect_string (uvalue)); + add_dwo_name ((const char *) fetch_indirect_string (uvalue), cu_offset); break; case DW_FORM_GNU_strp_alt: - add_dwo_name ((const char *) fetch_alt_indirect_string (uvalue)); + add_dwo_name ((const char *) fetch_alt_indirect_string (uvalue), cu_offset); break; case DW_FORM_GNU_str_index: - add_dwo_name (fetch_indexed_string (uvalue, this_set, offset_size, FALSE)); + add_dwo_name (fetch_indexed_string (uvalue, this_set, offset_size, FALSE), cu_offset); break; case DW_FORM_string: - add_dwo_name ((const char *) orig_data); + add_dwo_name ((const char *) orig_data, cu_offset); break; default: warn (_("Unsupported form (%s) for attribute %s\n"), @@ -2900,19 +2902,19 @@ read_and_display_attr_value (unsigned long attribute, switch (form) { case DW_FORM_strp: - add_dwo_dir ((const char *) fetch_indirect_string (uvalue)); + add_dwo_dir ((const char *) fetch_indirect_string (uvalue), cu_offset); break; case DW_FORM_GNU_strp_alt: - add_dwo_dir (fetch_alt_indirect_string (uvalue)); + add_dwo_dir (fetch_alt_indirect_string (uvalue), cu_offset); break; case DW_FORM_line_strp: - add_dwo_dir ((const char *) fetch_indirect_line_string (uvalue)); + add_dwo_dir ((const char *) fetch_indirect_line_string (uvalue), cu_offset); break; case DW_FORM_GNU_str_index: - add_dwo_dir (fetch_indexed_string (uvalue, this_set, offset_size, FALSE)); + add_dwo_dir (fetch_indexed_string (uvalue, this_set, offset_size, FALSE), cu_offset); break; case DW_FORM_string: - add_dwo_dir ((const char *) orig_data); + add_dwo_dir ((const char *) orig_data, cu_offset); break; default: warn (_("Unsupported form (%s) for attribute %s\n"), @@ -2927,7 +2929,7 @@ read_and_display_attr_value (unsigned long attribute, { case DW_FORM_data8: /* FIXME: Record the length of the ID as well ? */ - add_dwo_id ((const char *) (data - 8)); + add_dwo_id ((const char *) (data - 8), cu_offset); break; default: warn (_("Unsupported form (%s) for attribute %s\n"), @@ -11148,18 +11150,50 @@ load_separate_debug_files (void * file, const char * filename) { free_dwo_info (); - if (process_debug_info (& debug_displays[info].section, file, abbrev, TRUE, FALSE)) + if (process_debug_info (& debug_displays[info].section, file, abbrev, + TRUE, FALSE)) { bfd_boolean introduced = FALSE; dwo_info * dwinfo; const char * dir = NULL; const char * id = NULL; + const char * name = NULL; for (dwinfo = first_dwo_info; dwinfo != NULL; dwinfo = dwinfo->next) { + /* Accumulate NAME, DIR and ID fields. */ switch (dwinfo->type) { case DWO_NAME: + if (name != NULL) + warn (_("Multiple DWO_NAMEs encountered for the same CU\n")); + name = dwinfo->value; + break; + + case DWO_DIR: + /* There can be multiple DW_AT_comp_dir entries in a CU, + so do not complain. */ + dir = dwinfo->value; + break; + + case DWO_ID: + if (id != NULL) + warn (_("multiple DWO_IDs encountered for the same CU\n")); + id = dwinfo->value; + break; + + default: + error (_("Unexpected DWO INFO type")); + break; + } + + /* If we have reached the end of our list, or we are changing + CUs, then display the information that we have accumulated + so far. */ + if (name != NULL + && (dwinfo->next == NULL + || dwinfo->next->cu_offset != dwinfo->cu_offset)) + { if (do_debug_links) { if (! introduced) @@ -11169,30 +11203,19 @@ load_separate_debug_files (void * file, const char * filename) introduced = TRUE; } - printf (_(" Name: %s\n"), dwinfo->value); + printf (_(" Name: %s\n"), name); printf (_(" Directory: %s\n"), dir ? dir : _("")); if (id != NULL) display_data (printf (_(" ID: ")), (unsigned char *) id, 8); else - printf (_(" ID: \n")); + printf (_(" ID: \n")); printf ("\n\n"); } if (do_follow_links) - load_dwo_file (filename, dwinfo->value, dir, id); - break; - - case DWO_DIR: - dir = dwinfo->value; - break; + load_dwo_file (filename, name, dir, id); - case DWO_ID: - id = dwinfo->value; - break; - - default: - error (_("Unexpected DWO INFO type")); - break; + name = dir = id = NULL; } } } diff --git a/binutils/testsuite/binutils-all/dwo.s b/binutils/testsuite/binutils-all/dwo.s index 5c37c423420..96db12926df 100644 --- a/binutils/testsuite/binutils-all/dwo.s +++ b/binutils/testsuite/binutils-all/dwo.s @@ -34,8 +34,8 @@ string_end: /* Create a .debug_info section that contains the dwo links. */ .section .debug_info,"",%progbits - .4byte debugE - debugS ;# Length of Compilation Unit Info -debugS: + .4byte debugE1 - debugS1 ;# Length of Compilation Unit Info +debugS1: .short 0x4 ;# DWARF version number. .4byte 0x0 ;# Offset into .debug_abbrev section. .byte 0x4 ;# Pointer Size (in bytes). @@ -43,6 +43,13 @@ debugS: .uleb128 0x1 ;# Use abbrev #1. This needs strings from the .debug_str section. .4byte string1 .4byte string2 +debugE1: + + .4byte debugE2 - debugS2 ;# Length of Compilation Unit Info +debugS2: + .short 0x4 ;# DWARF version number. + .4byte 0x0 ;# Offset into .debug_abbrev section. + .byte 0x4 ;# Pointer Size (in bytes). .uleb128 0x2 ;# Use abbrev #2. .asciz "file.dwo" @@ -52,7 +59,7 @@ debugS: ;# Minimal section alignment on alpha-* is 2, so ensure no new invalid CU ;# will be started. .balign 2, 0 -debugE: +debugE2: .section .debug_abbrev,"",%progbits diff --git a/binutils/testsuite/binutils-all/readelf.k2 b/binutils/testsuite/binutils-all/readelf.k2 index e2ea0ad2808..1ca9ef49339 100644 --- a/binutils/testsuite/binutils-all/readelf.k2 +++ b/binutils/testsuite/binutils-all/readelf.k2 @@ -6,4 +6,4 @@ The \.debug_info section contains link\(s\) to dwo file\(s\): Name: debugfile\.dwo Directory: /path/to/dwo/files - ID: (12|dd) (34|cc) (56|bb) (78|aa) (78|aa) (56|bb) (34|cc) (12|dd) + ID: -- 2.30.2