libdw: Recognize GNU DebugFission split units.
authorMark Wielaard <mark@klomp.org>
Mon, 14 May 2018 15:29:05 +0000 (17:29 +0200)
committerMark Wielaard <mark@klomp.org>
Sat, 19 May 2018 11:24:20 +0000 (13:24 +0200)
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
libdw/libdwP.h
libdw/libdw_findcu.c
src/ChangeLog
src/readelf.c

index e41e5c8..385f52c 100644 (file)
@@ -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,
index da0383f..25a5ad3 100644 (file)
@@ -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;
index 3899c08..0a65c97 100644 (file)
@@ -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)
index 4f08312..9a6adab 100644 (file)
@@ -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
index 6d503c7..bb03d2c 100644 (file)
@@ -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);