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 <m...@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 <m...@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 <m...@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 <m...@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 <m...@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