From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28707 invoked by alias); 20 May 2018 19:28:50 -0000 Mailing-List: contact elfutils-devel-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Post: List-Help: List-Subscribe: Sender: elfutils-devel-owner@sourceware.org Received: (qmail 28695 invoked by uid 89); 20 May 2018 19:28:48 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Checked: by ClamAV 0.99.4 on sourceware.org X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.7 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS,T_FILL_THIS_FORM_SHORT autolearn=ham version=3.3.2 spammy=c99, offsets, Display, C99 X-Spam-Status: No, score=-24.7 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS,T_FILL_THIS_FORM_SHORT autolearn=ham version=3.3.2 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on sourceware.org X-Spam-Level: X-HELO: gnu.wildebeest.org Received: from wildebeest.demon.nl (HELO gnu.wildebeest.org) (212.238.236.112) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 20 May 2018 19:28:46 +0000 Received: from librem.wildebeest.org (ip4da134f7.direct-adsl.nl [77.161.52.247]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by gnu.wildebeest.org (Postfix) with ESMTPSA id F0A1730277C7; Sun, 20 May 2018 21:28:43 +0200 (CEST) Received: by librem.wildebeest.org (Postfix, from userid 1000) id 7237614071F; Sun, 20 May 2018 21:28:42 +0200 (CEST) From: Mark Wielaard To: elfutils-devel@sourceware.org Cc: Mark Wielaard Subject: [PATCH] readelf: print split CUs when given --debug-dump=info+ Date: Sun, 20 May 2018 19:28:00 -0000 Message-Id: <20180520192826.4933-1-mark@klomp.org> X-Mailer: git-send-email 2.17.0 X-Spam-Flag: NO X-IsSubscribed: yes X-SW-Source: 2018-q2/txt/msg00066.txt.bz2 To show the difference between "regular" CUs and split CUs print offsets and references between { and } instead of [ and ]. When --debug-dump=info+ is given (implied by -w) instead of --debug-dump=info any skeleton unit will be immediately followed by the corresponding split compile unit (from the .dwo file). DWARF section [27] '.debug_info' at offset 0x1075: [Offset] Compilation unit at offset 0: Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4 Unit type: skeleton (4), Unit id: 0xc152129eb4b99599 [ b] compile_unit abbrev: 1 ranges (sec_offset) range list [ 0] low_pc (addr) +000000000000000000 stmt_list (sec_offset) 0 GNU_dwo_name (strp) "foo.dwo" comp_dir (strp) "/tmp" GNU_pubnames (flag_present) yes GNU_addr_base (sec_offset) 0 GNU_dwo_id (data8) 0xc152129eb4b99599 GNU_ranges_base (sec_offset) 0 Split compilation unit at offset 0: Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4 Unit type: skeleton (4), Unit id: 0xc152129eb4b99599 { b} compile_unit abbrev: 1 producer (GNU_str_index) "GNU C11 7.3.0 -gsplit-dwarf -g" language (data1) C99 (12) name (GNU_str_index) "foo.c" comp_dir (GNU_str_index) "/tmp" GNU_dwo_id (data8) 0xc152129eb4b99599 { 18} subprogram abbrev: 2 external (flag_present) yes name (GNU_str_index) "main" decl_file (data1) foo.c (1) decl_line (data1) 1 type (ref4) { 2b} high_pc (data8) 3 frame_base (exprloc) [ 0] call_frame_cfa GNU_all_call_sites (flag_present) yes { 2b} base_type abbrev: 3 byte_size (data1) 4 encoding (data1) signed (5) name (string) "int" Signed-off-by: Mark Wielaard --- src/ChangeLog | 12 ++++++ src/readelf.c | 107 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 101 insertions(+), 18 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 9a6adab1..e1872775 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,15 @@ +2018-01-19 Mark Wielaard + + * readelf.c (options): Add info+. + (show_split_units): New static boolean defaulting to false. + (parse_opt): For all (no arg) --debug-dump set show_split_units + to yes. For "info+" enable section_info and show_split_units. + (attrcb_args): Add is_split field. + (attr_callback): Use is_split to format DIE offsets differently. + (print_debug_units): Likewise. Get subdie (type or split) only + when needed. When not silent reiterate over split DIEs when + found. + 2018-05-15 Mark Wielaard * readelf.c (print_debug_units): Print unit type and id for any diff --git a/src/readelf.c b/src/readelf.c index bb03d2c2..466d941e 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -112,7 +112,7 @@ static const struct argp_option options[] = { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 }, { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL, N_("Display DWARF section content. SECTION can be one of abbrev, " - "aranges, decodedaranges, frame, gdb_index, info, loc, line, " + "aranges, decodedaranges, frame, gdb_index, info, info+, loc, line, " "decodedline, ranges, pubnames, str, macinfo, macro or exception"), 0 }, { "hex-dump", 'x', "SECTION", 0, N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 }, @@ -215,6 +215,9 @@ static bool decodedline = false; /* True if we want to show more information about compressed sections. */ static bool print_decompress = false; +/* True if we want to show split compile units for debug_info skeletons. */ +static bool show_split_units = false; + /* Select printing of debugging sections. */ static enum section_e { @@ -422,6 +425,7 @@ parse_opt (int key, char *arg, { print_debug_sections = section_all; implicit_debug_sections = section_info; + show_split_units = true; } else if (strcmp (arg, "abbrev") == 0) print_debug_sections |= section_abbrev; @@ -441,6 +445,11 @@ parse_opt (int key, char *arg, print_debug_sections |= section_frame; else if (strcmp (arg, "info") == 0) print_debug_sections |= section_info; + else if (strcmp (arg, "info+") == 0) + { + print_debug_sections |= section_info; + show_split_units = true; + } else if (strcmp (arg, "loc") == 0) { print_debug_sections |= section_loc; @@ -6075,6 +6084,7 @@ struct attrcb_args Dwarf_Die *die; int level; bool silent; + bool is_split; unsigned int version; unsigned int addrsize; unsigned int offset_size; @@ -6088,6 +6098,7 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) struct attrcb_args *cbargs = (struct attrcb_args *) arg; const int level = cbargs->level; Dwarf_Die *die = cbargs->die; + bool is_split = cbargs->is_split; unsigned int attr = dwarf_whatattr (attrp); if (unlikely (attr == 0)) @@ -6180,9 +6191,13 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) if (unlikely (dwarf_formref_die (attrp, &ref) == NULL)) goto attrval_out; - printf (" %*s%-20s (%s) [%6" PRIxMAX "]\n", + printf (" %*s%-20s (%s) ", (int) (level * 2), "", dwarf_attr_name (attr), - dwarf_form_name (form), (uintmax_t) dwarf_dieoffset (&ref)); + dwarf_form_name (form)); + if (is_split) + printf ("{%6" PRIxMAX "}\n", (uintmax_t) dwarf_dieoffset (&ref)); + else + printf ("[%6" PRIxMAX "]\n", (uintmax_t) dwarf_dieoffset (&ref)); break; case DW_FORM_ref_sig8: @@ -6521,7 +6536,6 @@ print_debug_units (Dwfl_Module *dwflmod, Dwarf_CU cu_mem; uint8_t unit_type; Dwarf_Die cudie; - Dwarf_Die subdie; /* We cheat a little because we want to see only the CUs from .debug_info or .debug_types. We know the Dwarf_CU struct layout. Set it up at @@ -6539,7 +6553,7 @@ print_debug_units (Dwfl_Module *dwflmod, next_cu: unit_res = dwarf_get_units (dbg, cu, &cu, &version, &unit_type, - &cudie, &subdie); + &cudie, NULL); if (unit_res == 1) goto do_return; @@ -6560,14 +6574,21 @@ print_debug_units (Dwfl_Module *dwflmod, { Dwarf_Off offset = cu->start; if (debug_types && version < 5) - printf (gettext (" Type unit at offset %" PRIu64 ":\n" - " Version: %" PRIu16 ", Abbreviation section offset: %" - PRIu64 ", Address size: %" PRIu8 - ", Offset size: %" PRIu8 - "\n Type signature: %#" PRIx64 - ", Type offset: %#" PRIx64 " [%" PRIx64 "]\n"), - (uint64_t) offset, version, abbroffset, addrsize, offsize, - unit_id, (uint64_t) subdie_off, dwarf_dieoffset (&subdie)); + { + Dwarf_Die typedie; + Dwarf_Off dieoffset; + dieoffset = dwarf_dieoffset (dwarf_offdie_types (dbg, subdie_off, + &typedie)); + printf (gettext (" Type unit at offset %" PRIu64 ":\n" + " Version: %" PRIu16 + ", Abbreviation section offset: %" PRIu64 + ", Address size: %" PRIu8 + ", Offset size: %" PRIu8 + "\n Type signature: %#" PRIx64 + ", Type offset: %#" PRIx64 " [%" PRIx64 "]\n"), + (uint64_t) offset, version, abbroffset, addrsize, offsize, + unit_id, (uint64_t) subdie_off, dieoffset); + } else { printf (gettext (" Compilation unit at offset %" PRIu64 ":\n" @@ -6589,8 +6610,15 @@ print_debug_units (Dwfl_Module *dwflmod, printf (", Unit id: 0x%.16" PRIx64 "", unit_id); if (unit_type == DW_UT_type || unit_type == DW_UT_split_type) - printf (", Unit DIE off: %#" PRIx64 " [%" PRIx64 "]", - subdie_off, dwarf_dieoffset (&subdie)); + { + Dwarf_Die typedie; + Dwarf_Off dieoffset; + dwarf_cu_info (cu, NULL, NULL, NULL, &typedie, + NULL, NULL, NULL); + dieoffset = dwarf_dieoffset (&typedie); + printf (", Unit DIE off: %#" PRIx64 " [%" PRIx64 "]", + subdie_off, dieoffset); + } printf ("\n"); } } @@ -6608,17 +6636,21 @@ print_debug_units (Dwfl_Module *dwflmod, struct attrcb_args args = { .dwflmod = dwflmod, - .dbg = dbg, .silent = silent, .version = version, .addrsize = addrsize, .offset_size = offsize }; + bool is_split = false; int level = 0; dies[0] = cudie; args.cu = dies[0].cu; + args.dbg = dbg; + args.is_split = is_split; + /* We might return here again for the split CU subdie. */ + do_cu: do { Dwarf_Off offset = dwarf_dieoffset (&dies[level]); @@ -6643,8 +6675,11 @@ print_debug_units (Dwfl_Module *dwflmod, if (!silent) { unsigned int code = dwarf_getabbrevcode (dies[level].abbrev); - printf (" [%6" PRIx64 "] %*s%-20s abbrev: %u\n", - (uint64_t) offset, (int) (level * 2), "", + if (is_split) + printf (" {%6" PRIx64 "} ", (uint64_t) offset); + else + printf (" [%6" PRIx64 "] ", (uint64_t) offset); + printf ("%*s%-20s abbrev: %u\n", (int) (level * 2), "", dwarf_tag_name (tag), code); } @@ -6686,6 +6721,42 @@ print_debug_units (Dwfl_Module *dwflmod, } while (level >= 0); + /* We might want to show the split compile unit if this was a skeleton. */ + if (!silent && show_split_units && unit_type == DW_UT_skeleton) + { + Dwarf_Die subdie; + if (dwarf_cu_info (cu, NULL, NULL, NULL, &subdie, NULL, NULL, NULL) != 0 + || dwarf_tag (&subdie) == DW_TAG_invalid) + error (0, 0, gettext ("Could not find split compile unit")); + else + { + Dwarf_CU *split_cu = subdie.cu; + dwarf_cu_die (split_cu, &result, NULL, &abbroffset, + &addrsize, &offsize, &unit_id, &subdie_off); + Dwarf_Off offset = cu->start; + + printf (gettext (" Split compilation unit at offset %" PRIu64 ":\n" + " Version: %" PRIu16 + ", Abbreviation section offset: %" PRIu64 + ", Address size: %" PRIu8 + ", Offset size: %" PRIu8 "\n"), + (uint64_t) offset, version, abbroffset, addrsize, offsize); + printf (gettext (" Unit type: %s (%" PRIu8 ")"), + dwarf_unit_name (unit_type), unit_type); + printf (", Unit id: 0x%.16" PRIx64 "", unit_id); + printf ("\n"); + + unit_type = DW_UT_split_compile; + is_split = true; + level = 0; + dies[0] = subdie; + args.cu = dies[0].cu; + args.dbg = split_cu->dbg; + args.is_split = is_split; + goto do_cu; + } + } + /* And again... */ goto next_cu; -- 2.17.0