[Public] Hi, Binutils support for split-dwarf and dwarf5 is now added for gcc and clang. There are 2 patches. Basic sections dump like .debug_info.dwo, .debug_abbrev.dwo, .debug_str.dwo etc are supported in patch 1/2. location list and ranges list sections dump with split-dwarf and dwarf5 are supported in patch 2/2 and patch 2/2 is continuation of patch 1/2. Both the patches are attached and also inlined below. Separating these issues as individual patches might be easy to review, hence 2 patches are there. Issues fixed in patch 1/2 : There are few differences b/w dwarf4 and dwarf5 as shared below, w.r.t. split-dwarf support added like different attributes/forms used to represent DWO name and ID, .debug_str_offsets section etc. All these are addressed. I have tested these changes with gcc and clang compiled objects with split-dwarf and dwarf-5. DWARF4: * DW_AT_GNU_dwo_name [DW_FORM_strp] * DW_AT_GNU_dwo_id [DW_FORM_data8] * Above attribute are part of DW_TAG_compile_unit DWARF5: * DW_AT_dwo_name [DW_FORM_strp] * Above attribute is part of DW_TAG_skeleton_unit * .debug_str_offsets is used to refer to .debug_str section NOTE: DWO ID is not printed for dwarf 5 during initial dwo file dump information summary. But its dumped under .debug_info section dump. Because now there is no separate attribute in dwarf5 for DWO ID like it was there in dwarf4(DW_AT_GNU_dwo_id). Issues fixed in patch 2/2 : .debug_loclists.dwo and .debug_rnglists.dwo section dumps are taken care. I have tested these changes for clang compiled objects with split-dwarf and dwarf-5, where .debug_loclists.dwo and .debug_rnglists.dwo sections exist in the separate debug file (.dwo files) Regards, bhuvan Patch 1/2 inlined: From 1bda1e144f43d1f41fe30a934ba008561083dc07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cbhkumarn=E2=80=9D?= Bhuvanendra.KumarN@amd.com Date: Thu, 2 Jun 2022 17:44:02 +0530 Subject: [PATCH] [PATCH 1/2] Binutils support for split-dwarf and dwarf-5. This fix adds support for split-dwarf and dwarf5, for both gcc and clang. There are 2 patches. Basic sections dump like .debug_info.dwo, .debug_abbrev.dwo, .debug_str.dwo etc are supported in this patch 1/2. But location list and ranges list sections dump with split-dwarf and dwarf5 are supported in the next patch 2/2. There are few differences b/w dwarf4 and dwarf5, w.r.t. split-dwarf support added like different attributes/forms used to represent DWO name and ID, .debug_str_offsets section etc. All these are addressed. * dwarf.c (fetch_indexed_string): Use str_offsets_base to calculate the string offset. (read_and_display_attr_value): Set str_offsets_base i.e. string offset table base address. (process_debug_info): Include DW_TAG_skeleton_unit. (load_separate_debug_files): Load .debug_str_offsets if exists. Skip DWO ID dump for dwarf-5. * testsuite/binutils-all/readelf.exp: Added new test point. * testsuite/binutils-all/readelf.k5: New file. * testsuite/binutils-all/dwo_5.s: New file. --- binutils/dwarf.c | 11 +- binutils/testsuite/binutils-all/dwo_5.s | 257 ++++++++++++++++++++ binutils/testsuite/binutils-all/readelf.exp | 12 + binutils/testsuite/binutils-all/readelf.k5 | 7 + 4 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 binutils/testsuite/binutils-all/dwo_5.s create mode 100644 binutils/testsuite/binutils-all/readelf.k5 diff --git a/binutils/dwarf.c b/binutils/dwarf.c index caa3ce48d00..e8f0ea4cf0c 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -118,6 +118,8 @@ int dwarf_cutoff_level = -1; unsigned long dwarf_start_die; int dwarf_check = 0; +static dwarf_vma str_offsets_base = 0; +#define DEBUG_STR_OFFSETS_HEADER_LEN 8 /* Convenient constant, to avoid having to cast -1 to dwarf_vma when testing whether e.g. a locview list is present. */ @@ -779,7 +781,7 @@ fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set, return _(""); } - str_offset = byte_get (curr + index_offset, offset_size); + str_offset = byte_get (curr + index_offset + str_offsets_base, offset_size); str_offset -= str_section->address; if (str_offset >= str_section->size) { @@ -2485,6 +2487,8 @@ read_and_display_attr_value (unsigned long attribute, case DW_FORM_GNU_ref_alt: case DW_FORM_GNU_strp_alt: SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end); + if (attribute == DW_AT_str_offsets_base) + str_offsets_base = uvalue - DEBUG_STR_OFFSETS_HEADER_LEN; break; case DW_FORM_flag_present: @@ -4016,6 +4020,7 @@ process_debug_info (struct dwarf_section * section, need_base_address = 0; break; case DW_TAG_compile_unit: + case DW_TAG_skeleton_unit: need_base_address = 1; need_dwo_info = do_loc; break; @@ -4059,6 +4064,7 @@ process_debug_info (struct dwarf_section * section, level); } + str_offsets_base = 0; /* If a locview attribute appears before a location one, make sure we don't associate it with an earlier loclist. */ @@ -11889,6 +11895,7 @@ load_separate_debug_files (void * file, const char * filename) && load_debug_section (abbrev, file) && load_debug_section (info, file)) { + load_debug_section (str_index, file); free_dwo_info (); if (process_debug_info (& debug_displays[info].section, file, abbrev, @@ -11948,7 +11955,7 @@ load_separate_debug_files (void * file, const char * filename) printf (_(" Directory: %s\n"), dir ? dir : _("")); if (id != NULL) display_data (printf (_(" ID: ")), (unsigned char *) id, 8); - else + else if (debug_information[0].dwarf_version != 5) printf (_(" ID: \n")); printf ("\n\n"); } diff --git a/binutils/testsuite/binutils-all/dwo_5.s b/binutils/testsuite/binutils-all/dwo_5.s new file mode 100644 index 00000000000..e394467c2be --- /dev/null +++ b/binutils/testsuite/binutils-all/dwo_5.s @@ -0,0 +1,257 @@ + .file "a.c" + .text +.Ltext0: + .globl a + .type a, @function +a: +.LFB0: + .file 1 "a.c" + .loc 1 1 13 + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + .loc 1 1 22 + movl $111, %eax + .loc 1 1 1 + popq %rbp + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE0: + .size a, .-a +.Letext0: + .section .debug_addr,"",@progbits + .long 0xc + .value 0x5 + .byte 0x8 + .byte 0 +.Ldebug_addr0: + .quad .LFB0 + .section .debug_info.dwo,"e",@progbits +.Ldebug_info0: + .long 0x35 + .value 0x5 + .byte 0x5 + .byte 0x8 + .long .Ldebug_abbrev0 + .byte 0x46 + .byte 0x1c + .byte 0xf1 + .byte 0xfb + .byte 0xe5 + .byte 0x96 + .byte 0x7d + .byte 0x2b + .uleb128 0x1 + .uleb128 0x1 + .byte 0x1d + .string "a.c" + .uleb128 0 + .uleb128 0x2 + .string "a" + .byte 0x1 + .byte 0x1 + .byte 0x5 + .long 0x31 + .uleb128 0 + .quad .LFE0-.LFB0 + .uleb128 0x1 + .byte 0x9c + .uleb128 0x3 + .byte 0x4 + .byte 0x5 + .string "int" + .byte 0 + .section .debug_info,"",@progbits +.Lskeleton_debug_info0: + .long 0x31 + .value 0x5 + .byte 0x4 + .byte 0x8 + .long .Lskeleton_debug_abbrev0 + .byte 0x46 + .byte 0x1c + .byte 0xf1 + .byte 0xfb + .byte 0xe5 + .byte 0x96 + .byte 0x7d + .byte 0x2b + .uleb128 0x1 + .quad .Ltext0 + .quad .Letext0-.Ltext0 + .long .Ldebug_line0 + .long .LASF0 + .long .LASF1 + .long .Ldebug_addr0 + .section .debug_abbrev,"",@progbits +.Lskeleton_debug_abbrev0: + .uleb128 0x1 + .uleb128 0x4a + .byte 0 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x7 + .uleb128 0x10 + .uleb128 0x17 + .uleb128 0x76 + .uleb128 0xe + .uleb128 0x1b + .uleb128 0xe + .uleb128 0x2134 + .uleb128 0x19 + .uleb128 0x73 + .uleb128 0x17 + .byte 0 + .byte 0 + .byte 0 + .section .debug_abbrev.dwo,"e",@progbits +.Ldebug_abbrev0: + .uleb128 0x1 + .uleb128 0x11 + .byte 0x1 + .uleb128 0x25 + .uleb128 0x1a + .uleb128 0x13 + .uleb128 0xb + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x1b + .uleb128 0x1a + .byte 0 + .byte 0 + .uleb128 0x2 + .uleb128 0x2e + .byte 0 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x39 + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1b + .uleb128 0x12 + .uleb128 0x7 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x7a + .uleb128 0x19 + .byte 0 + .byte 0 + .uleb128 0x3 + .uleb128 0x24 + .byte 0 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x3e + .uleb128 0xb + .uleb128 0x3 + .uleb128 0x8 + .byte 0 + .byte 0 + .byte 0 + .section .debug_gnu_pubnames,"",@progbits + .long 0x15 + .value 0x2 + .long .Lskeleton_debug_info0 + .long 0x39 + .long 0x1c + .byte 0x30 + .string "a" + .long 0 + .section .debug_gnu_pubtypes,"",@progbits + .long 0x17 + .value 0x2 + .long .Lskeleton_debug_info0 + .long 0x39 + .long 0x31 + .byte 0x90 + .string "int" + .long 0 + .section .debug_aranges,"",@progbits + .long 0x2c + .value 0x2 + .long .Lskeleton_debug_info0 + .byte 0x8 + .byte 0 + .value 0 + .value 0 + .quad .Ltext0 + .quad .Letext0-.Ltext0 + .quad 0 + .quad 0 + .section .debug_line,"",@progbits +.Ldebug_line0: + .section .debug_line.dwo,"e",@progbits +.Lskeleton_debug_line0: + .long .LELT0-.LSLT0 +.LSLT0: + .value 0x5 + .byte 0x8 + .byte 0 + .long .LELTP0-.LASLTP0 +.LASLTP0: + .byte 0x1 + .byte 0x1 + .byte 0x1 + .byte 0xf6 + .byte 0xf2 + .byte 0xd + .byte 0 + .byte 0x1 + .byte 0x1 + .byte 0x1 + .byte 0x1 + .byte 0 + .byte 0 + .byte 0 + .byte 0x1 + .byte 0 + .byte 0 + .byte 0x1 + .byte 0x1 + .uleb128 0x1 + .uleb128 0x8 + .uleb128 0x1 + .string "/tmp" + .byte 0x2 + .uleb128 0x1 + .uleb128 0x8 + .uleb128 0x2 + .uleb128 0xb + .uleb128 0x2 + .string "a.c" + .byte 0 + .string "a.c" + .byte 0 +.LELTP0: +.LELT0: + .section .debug_str,"MS",@progbits,1 +.LASF1: + .string "/tmp" +.LASF0: + .string "a.dwo" + .section .debug_str_offsets.dwo,"e",@progbits + .long 0xc + .value 0x5 + .value 0 + .long 0 + .long 0x5 + .section .debug_str.dwo,"e",@progbits + .string "/tmp" + .string "GNU C17 10.0.0 20190813 (experimental) -mtune=generic -march=x86-64 -gdwarf-5 -gsplit-dwarf" + .ident "GCC: (GNU) 10.0.0 20190813 (experimental)" + .section .note.GNU-stack,"",@progbits diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp index 0f7a1f3b5a0..b68224d5019 100644 --- a/binutils/testsuite/binutils-all/readelf.exp +++ b/binutils/testsuite/binutils-all/readelf.exp @@ -572,6 +572,18 @@ if {![binutils_assemble $srcdir/$subdir/dwo.s tmpdir/dwo.o]} then { readelf_test {--debug-dump=links --debug-dump=no-follow-links} $tempfile readelf.k2 } +if {![binutils_assemble $srcdir/$subdir/dwo_5.s tmpdir/dwo_5.o]} then { + unsupported "readelf --debug-dump=links (failed to assemble dwo_5.s)" +} else { + if ![is_remote host] { + set tempfile tmpdir/dwo_5.o + } else { + set tempfile [remote_download host tmpdir/dwo_5.o] + } + + readelf_test {--debug-dump=links --debug-dump=no-follow-links} $tempfile readelf.k5 +} + if {![binutils_assemble $srcdir/$subdir/zero-sec.s tmpdir/zero-sec.o]} then { unsupported "readelf --enable-checks (failed to assemble zero-sec.s)" } else { diff --git a/binutils/testsuite/binutils-all/readelf.k5 b/binutils/testsuite/binutils-all/readelf.k5 new file mode 100644 index 00000000000..49779224f2c --- /dev/null +++ b/binutils/testsuite/binutils-all/readelf.k5 @@ -0,0 +1,7 @@ +The .debug_info section contains link\(s\) to dwo file\(s\): + + Name: a.dwo + Directory: /tmp + + + -- 2.17.1 Patch 2/2 inlined: From dab73681a6e19c16c799d150cc79cace3f8f894c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cbhkumarn=E2=80=9D?= Bhuvanendra.KumarN@amd.com Date: Thu, 2 Jun 2022 19:19:13 +0530 Subject: [PATCH] [PATCH 2/2] Binutils support for split-dwarf and dwarf-5. This fix adds support for split-dwarf and dwarf5. There are 2 patches. Basic sections dump like .debug_info.dwo, .debug_abbrev.dwo, .debug_str.dwo etc are supported in the previous patch 1/2. location list and ranges list sections dump with split-dwarf and dwarf5 are supported in this patch 2/2 and its continuation of patch 1/2. .debug_loclists.dwo and .debug_rnglists.dwo section dumps are taken care in this patch 2/2. * dwarf.c(read_and_display_attr_value): Handle DW_FORM_loclistx and DW_FORM_rnglistx for .dwo files. (process_debug_info): Load .debug_loclists.dwo and .debug_rnglists.dwo if exists. (load_separate_debug_files): Load .debug_loclists and .debug_rnglists if exists. Include 2 entries in debug_displays table. * dwarf.h (enum dwarf_section_display_enum): Include 2 entries. --- binutils/dwarf.c | 39 +++++++++++++++++++++++++++++++++++++-- binutils/dwarf.h | 2 ++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/binutils/dwarf.c b/binutils/dwarf.c index e8f0ea4cf0c..7b4bb445da4 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -120,6 +120,7 @@ unsigned long dwarf_start_die; int dwarf_check = 0; static dwarf_vma str_offsets_base = 0; #define DEBUG_STR_OFFSETS_HEADER_LEN 8 +#define DEBUG_LOC_RNGLISTS_SEC_HDR_LEN 12 /* Convenient constant, to avoid having to cast -1 to dwarf_vma when testing whether e.g. a locview list is present. */ @@ -2792,7 +2793,34 @@ read_and_display_attr_value (unsigned long attribute, offset = base + uvalue * pointer_size; - if (do_wide) + const char *suffix = strrchr (section->name, '.'); + bool dwo = suffix && strcmp (suffix, ".dwo") == 0; + + if (form == DW_FORM_loclistx) + { + if (!dwo) + printf (_("%c(index: 0x%s): %s"), delimiter, + dwarf_vmatoa ("x", uvalue), + dwarf_vmatoa ("x", debug_info_p->loc_offsets [uvalue])); + else + printf (_("%c(index: 0x%s): %s"), delimiter, + dwarf_vmatoa ("x", uvalue), + dwarf_vmatoa ("x", fetch_indexed_value (uvalue, loclists_dwo) + + DEBUG_LOC_RNGLISTS_SEC_HDR_LEN)); + } + else if (form == DW_FORM_rnglistx) + { + if (!dwo) + printf (_("%c(index: 0x%s): %s"), delimiter, + dwarf_vmatoa ("x", uvalue), + dwarf_vmatoa ("x", debug_info_p->range_lists [uvalue])); + else + printf (_("%c(index: 0x%s): %s"), delimiter, + dwarf_vmatoa ("x", uvalue), + dwarf_vmatoa ("x", fetch_indexed_value (uvalue, rnglists_dwo) + + DEBUG_LOC_RNGLISTS_SEC_HDR_LEN)); + } + else if (do_wide) /* We have already displayed the form name. */ printf (_("%c(index: 0x%s): %s"), delimiter, dwarf_vmatoa ("x", uvalue), @@ -3608,7 +3636,9 @@ process_debug_info (struct dwarf_section * section, load_debug_section_with_follow (abbrev_sec, file); load_debug_section_with_follow (loclists, file); load_debug_section_with_follow (rnglists, file); - + load_debug_section_with_follow (loclists_dwo, file); + load_debug_section_with_follow (rnglists_dwo, file); + if (debug_displays [abbrev_sec].section.start == NULL) { warn (_("Unable to locate %s section!\n"), @@ -11896,6 +11926,9 @@ load_separate_debug_files (void * file, const char * filename) && load_debug_section (info, file)) { load_debug_section (str_index, file); + load_debug_section (loclists, file); + load_debug_section (rnglists, file); + free_dwo_info (); if (process_debug_info (& debug_displays[info].section, file, abbrev, @@ -12265,10 +12298,12 @@ struct dwarf_section_display debug_displays[] = { { ".debug_line_str", ".zdebug_line_str", "", NO_ABBREVS }, display_debug_str, &do_debug_str, false }, { { ".debug_loc", ".zdebug_loc", ".dwloc", NO_ABBREVS }, display_debug_loc, &do_debug_loc, true }, { { ".debug_loclists", ".zdebug_loclists", "", NO_ABBREVS }, display_debug_loc, &do_debug_loc, true }, + { { ".debug_loclists.dwo", ".zdebug_loclists.dwo", "", NO_ABBREVS }, display_debug_loc, &do_debug_loc, true }, { { ".debug_pubtypes", ".zdebug_pubtypes", ".dwpbtyp", NO_ABBREVS }, display_debug_pubnames, &do_debug_pubtypes, false }, { { ".debug_gnu_pubtypes", ".zdebug_gnu_pubtypes", "", NO_ABBREVS }, display_debug_gnu_pubnames, &do_debug_pubtypes, false }, { { ".debug_ranges", ".zdebug_ranges", ".dwrnges", NO_ABBREVS }, display_debug_ranges, &do_debug_ranges, true }, { { ".debug_rnglists", ".zdebug_rnglists", "", NO_ABBREVS }, display_debug_ranges, &do_debug_ranges, true }, + { { ".debug_rnglists.dwo", ".zdebug_rnglists.dwo", "", NO_ABBREVS }, display_debug_ranges, &do_debug_ranges, true }, { { ".debug_static_func", ".zdebug_static_func", "", NO_ABBREVS }, display_debug_not_supported, NULL, false }, { { ".debug_static_vars", ".zdebug_static_vars", "", NO_ABBREVS }, display_debug_not_supported, NULL, false }, { { ".debug_types", ".zdebug_types", "", ABBREV (abbrev) }, display_debug_types, &do_debug_info, true }, diff --git a/binutils/dwarf.h b/binutils/dwarf.h index 040e674c6ce..86b635ef3c2 100644 --- a/binutils/dwarf.h +++ b/binutils/dwarf.h @@ -92,10 +92,12 @@ enum dwarf_section_display_enum line_str, loc, loclists, + loclists_dwo, pubtypes, gnu_pubtypes, ranges, rnglists, + rnglists_dwo, static_func, static_vars, types, -- 2.17.1