[PATCH] libdw: Recognize GNU DebugFission split units.

Mark Wielaard mark@klomp.org
Tue May 15 12:04:00 GMT 2018


The split dwarf dwo unit id and type are not in the CU header itself, but
can be found in the CU DIE DW_AT_GNU_dwo attributes. Use this to set the
correct unit_type and id for GNU DebugFission split units. Also show this
information in eu-readelf when printing units.

Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 libdw/ChangeLog      |  9 +++++++++
 libdw/libdwP.h       | 15 ++++++---------
 libdw/libdw_findcu.c | 23 ++++++++++++++++++++---
 src/ChangeLog        |  5 +++++
 src/readelf.c        |  3 ++-
 5 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index e41e5c8..385f52c 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,12 @@
+2018-05-15  Mark Wielaard  <mark@klomp.org>
+
+	* libdwP.h (__libdw_first_die_from_cu_start): Adjust commented out
+	asserts.
+	* libdw_findcu.c (__libdw_intern_next_unit): For version 4 DWARF if
+	the cudie has a DW_AT_GNU_dwi_id set the unit_id8 and unit_type to
+	DW_UT_skeleton or DW_UT_split_compile based on whether the cudie has
+	child DIEs and a DW_AT_GNU_dwo_name attribute.
+
 2018-05-14  Mark Wielaard  <mark@klomp.org>
 
 	* dwarf.h: Add GNU Debug Fission extensions. DW_AT_GNU_dwo_name,
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index da0383f..25a5ad3 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -360,15 +360,12 @@ __libdw_first_die_from_cu_start (Dwarf_Off cu_start,
 /*
   assert (offset_size == 4 || offset_size == 8);
   assert (version >= 2 && version <= 5);
-  assert (version >= 5 || (unit_type == DW_UT_compile
-			   || unit_type == DW_UT_partial
-			   || unit_type == DW_UT_type));
-  assert (version != 5 || (unit_type == DW_UT_compile
-			   || unit_type == DW_UT_partial
-			   || unit_type == DW_UT_skeleton
-			   || unit_type == DW_UT_split_compile
-			   || unit_type == DW_UT_type
-			   || unit_type == DW_UT_split_type));
+  assert (unit_type == DW_UT_compile
+	  || unit_type == DW_UT_partial
+	  || unit_type == DW_UT_skeleton
+	  || unit_type == DW_UT_split_compile
+	  || unit_type == DW_UT_type
+	  || unit_type == DW_UT_split_type);
 */
 
   Dwarf_Off off = cu_start;
diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c
index 3899c08..0a65c97 100644
--- a/libdw/libdw_findcu.c
+++ b/libdw/libdw_findcu.c
@@ -123,7 +123,7 @@ __libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
   newp->startp = data->d_buf + newp->start;
   newp->endp = data->d_buf + newp->end;
 
-  /* v4 debug type units have version == 4 and unit_type == 1.  */
+  /* v4 debug type units have version == 4 and unit_type == DW_UT_type.  */
   if (debug_types)
     newp->unit_type = DW_UT_type;
   else if (version < 5)
@@ -133,9 +133,26 @@ __libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
 
       /* But set it correctly from the actual CUDIE tag.  */
       Dwarf_Die cudie = CUDIE (newp);
-      int tag = dwarf_tag (&cudie);
+      int tag = INTUSE(dwarf_tag) (&cudie);
       if (tag == DW_TAG_compile_unit)
-	newp->unit_type = DW_UT_compile;
+	{
+	  Dwarf_Attribute dwo_id;
+	  if (INTUSE(dwarf_attr) (&cudie, DW_AT_GNU_dwo_id, &dwo_id) != NULL)
+	    {
+	      Dwarf_Word id8;
+	      if (INTUSE(dwarf_formudata) (&dwo_id, &id8) == 0)
+		{
+		  if (INTUSE(dwarf_haschildren) (&cudie) == 0
+		      && INTUSE(dwarf_hasattr) (&cudie,
+						DW_AT_GNU_dwo_name) == 1)
+		    newp->unit_type = DW_UT_skeleton;
+		  else
+		    newp->unit_type = DW_UT_split_compile;
+
+		  newp->unit_id8 = id8;
+		}
+	    }
+	}
       else if (tag == DW_TAG_partial_unit)
 	newp->unit_type = DW_UT_partial;
       else if (tag == DW_TAG_type_unit)
diff --git a/src/ChangeLog b/src/ChangeLog
index 778d053..5a74e83 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+2018-05-15  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_units): Print unit type and id for any
+	unit type that has it even when version < 5.
+
 2018-05-14  Mark Wielaard  <mark@klomp.org>
 
 	* readelf.c (print_ops): Handle DW_OP_GNU_addr_index and
diff --git a/src/readelf.c b/src/readelf.c
index 6d503c7..bb03d2c 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -6577,7 +6577,8 @@ print_debug_units (Dwfl_Module *dwflmod,
 			   ", Offset size: %" PRIu8 "\n"),
 		  (uint64_t) offset, version, abbroffset, addrsize, offsize);
 
-	  if (version >= 5)
+	  if (version >= 5 || (unit_type != DW_UT_compile
+			       && unit_type != DW_UT_partial))
 	    {
 	      printf (gettext (" Unit type: %s (%" PRIu8 ")"),
 			       dwarf_unit_name (unit_type), unit_type);
-- 
1.8.3.1



More information about the Elfutils-devel mailing list