This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] 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>
---
 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  <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;
 
-- 
2.17.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]