aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2018-01-19 15:45:16 +0100
committerMark Wielaard <mark@klomp.org>2018-05-24 17:37:00 +0200
commit184fd30d1a453dc165ffc187b22dec6d196522ad (patch)
tree6d884017cbc7719a75ca61130b595860cbd84814 /src
parentac6960d6b8602df97b5964f66ffc7cd91fd16e5b (diff)
downloadelfutils-184fd30d1a453dc165ffc187b22dec6d196522ad.tar.gz
readelf: print split CUs when given --debug-dump=info+
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 <mark@klomp.org>
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog12
-rw-r--r--src/readelf.c107
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 <mark@klomp.org>
+
+ * 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 <mark@klomp.org>
* 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;