[PATCH] readelf: Fix regression with multiple files and implicit debug_info reading.
Commit 314e9d7d "readelf: Handle .debug_info first if any other debug section needs it" introduced a regression when handling multiple files. The implicit and explicit printing of debuginfo weren't reset and so the second file would not show (or scan) the .debug_info section when needed. Fix by resetting the implicit and explicit section printing flags. Add a testcase that prints the .debug_loc section for two files and check that the CUs are resolved. Signed-off-by: Mark Wielaard --- src/ChangeLog | 5 + src/readelf.c | 10 +- tests/ChangeLog | 4 tests/run-readelf-twofiles.sh | 43 ++- 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index b6f66bd..e7ba6cb 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2018-05-29 Mark Wielaard + + * readelf.c (print_debug): Record and reset section_info status in + implicit_debug_sections and print_debug_sections. + 2018-05-28 Mark Wielaard * readelf.c (print_debug_units): Turn "Could not find split compile diff --git a/src/readelf.c b/src/readelf.c index bfa1d16..390f244 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -10894,7 +10894,9 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr) we must make sure to handle it before handling any other debug section. Various other sections depend on the CU DIEs being scanned (silently) first. */ - if ((implicit_debug_sections & section_info) != 0) + bool implicit_info = (implicit_debug_sections & section_info) != 0; + bool explicit_info = (print_debug_sections & section_info) != 0; + if (implicit_info) { Elf_Scn *scn = NULL; while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) @@ -11012,6 +11014,12 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr) dwfl_end (skel_dwfl); free (skel_name); + /* Turn implicit and/or explicit back on in case we go over another file. */ + if (implicit_info) +implicit_debug_sections |= section_info; + if (explicit_info) +print_debug_sections |= section_info; + reset_listptr (&known_locsptr); reset_listptr (&known_loclistsptr); reset_listptr (&known_rangelistptr); diff --git a/tests/ChangeLog b/tests/ChangeLog index 4d69515..682fffc 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +2018-05-29 Mark Wielaard + + * run-readelf-twofiles.sh: Add --debug-dump=loc testcase. + 2018-05-28 Mark Wielaard * run-readelf-info-plus.sh: New test. diff --git a/tests/run-readelf-twofiles.sh b/tests/run-readelf-twofiles.sh index 46eec7b..fc5f3e7 100755 --- a/tests/run-readelf-twofiles.sh +++ b/tests/run-readelf-twofiles.sh @@ -1,5 +1,5 @@ #! /bin/sh -# Copyright (C) 2011 Red Hat, Inc. +# Copyright (C) 2011, 2018 Red Hat, Inc. # This file is part of elfutils. # # This file is free software; you can redistribute it and/or modify @@ -21,4 +21,45 @@ testfiles testfile14 testrun >/dev/null ${abs_top_builddir}/src/readelf -w testfile14 testfile14 +testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=loc testfile14 testfile14 << EOF + +testfile14: + + +DWARF section [33] '.debug_loc' at offset 0xca9: + + CU [ b] base: 0x00400468 + [ 0] range 34, 35 + 0x0040049c .. + 0x0040049c + [ 0] breg7 -8 + range 35, 46 + 0x0040049d .. + 0x004004ad + [ 0] breg7 0 + range 46, 47 + 0x004004ae .. + 0x004004ae + [ 0] breg7 -8 + +testfile14: + + +DWARF section [33] '.debug_loc' at offset 0xca9: + + CU [ b] base: 0x00400468 + [ 0] range 34, 35 + 0x0040049c .. + 0x0040049c + [ 0] breg7 -8 + range 35, 46 + 0x0040049d .. + 0x004004ad + [ 0] breg7 0 + range 46, 47 + 0x004004ae .. + 0x004004ae + [ 0] breg7 -8 +EOF + exit 0 -- 1.8.3.1
[PATCH] readelf, libdw: Add GNU DebugFission .debug_loc support.
GNU DebugFission .debug_loc location lists uses the .debug_loc section in the split dwarf .dwo file. The encoding is a mix of old style DWARF .debug_loc and new style .debug_loclists. Add two testcases for the readelf and libdw decoders. Signed-off-by: Mark Wielaard --- libdw/ChangeLog | 9 +++ libdw/dwarf.h| 10 libdw/dwarf_ranges.c | 65 +- src/ChangeLog| 5 ++ src/readelf.c| 80 +-- tests/ChangeLog | 5 ++ tests/run-readelf-loc.sh | 141 +++ tests/run-varlocs.sh | 74 + 8 files changed, 382 insertions(+), 7 deletions(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index d187930..eb0b01a 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,12 @@ +2018-05-29 Mark Wielaard + + * dwarf.h: Add GNU DebugFission list entry encodings + DW_LLE_GNU_end_of_list_entry, + DW_LLE_GNU_base_address_selection_entry, + DW_LLE_GNU_start_end_entry and DW_LLE_GNU_start_length_entry. + * dwarf_ranges.c (__libdw_read_begin_end_pair_inc): Handle + GNU DebugFission list entries. + 2018-05-28 Mark Wielaard * libdw_find_split_unit.c (__libdw_find_split_unit): End split_dwarf diff --git a/libdw/dwarf.h b/libdw/dwarf.h index 8985a9d..dc59733 100644 --- a/libdw/dwarf.h +++ b/libdw/dwarf.h @@ -915,6 +915,16 @@ enum }; +/* GNU DebugFission list entry encodings (.debug_loc.dwo). */ +enum + { +DW_LLE_GNU_end_of_list_entry = 0x0, +DW_LLE_GNU_base_address_selection_entry = 0x1, +DW_LLE_GNU_start_end_entry = 0x2, +DW_LLE_GNU_start_length_entry = 0x3 + }; + + /* DWARF call frame instruction encodings. */ enum { diff --git a/libdw/dwarf_ranges.c b/libdw/dwarf_ranges.c index 0f3ee6b..f67d8a5 100644 --- a/libdw/dwarf_ranges.c +++ b/libdw/dwarf_ranges.c @@ -49,7 +49,70 @@ __libdw_read_begin_end_pair_inc (Dwarf_CU *cu, int sec_index, Dwarf_Addr *basep) { Dwarf *dbg = cu->dbg; - if (sec_index == IDX_debug_ranges || sec_index == IDX_debug_loc) + if (sec_index == IDX_debug_loc + && cu->version < 5 + && cu->unit_type == DW_UT_split_compile) +{ + /* GNU DebugFission. */ + const unsigned char *addr = *addrp; + if (addrend - addr < 1) + goto invalid; + + const char code = *addr++; + uint64_t begin = 0, end = 0, base = *basep, addr_idx; + switch (code) + { + case DW_LLE_GNU_end_of_list_entry: + *addrp = addr; + return 2; + + case DW_LLE_GNU_base_address_selection_entry: + if (addrend - addr < 1) + goto invalid; + get_uleb128 (addr_idx, addr, addrend); + if (__libdw_addrx (cu, addr_idx, &base) != 0) + return -1; + *basep = base; + *addrp = addr; + return 1; + + case DW_LLE_GNU_start_end_entry: + if (addrend - addr < 1) + goto invalid; + get_uleb128 (addr_idx, addr, addrend); + if (__libdw_addrx (cu, addr_idx, &begin) != 0) + return -1; + if (addrend - addr < 1) + goto invalid; + get_uleb128 (addr_idx, addr, addrend); + if (__libdw_addrx (cu, addr_idx, &end) != 0) + return -1; + + *beginp = begin; + *endp = end; + *addrp = addr; + return 0; + + case DW_LLE_GNU_start_length_entry: + if (addrend - addr < 1) + goto invalid; + get_uleb128 (addr_idx, addr, addrend); + if (__libdw_addrx (cu, addr_idx, &begin) != 0) + return -1; + if (addrend - addr < 4) + goto invalid; + end = read_4ubyte_unaligned_inc (dbg, addr); + + *beginp = begin; + *endp = begin + end; + *addrp = addr; + return 0; + + default: + goto invalid; + } +} + else if (sec_index == IDX_debug_ranges || sec_index == IDX_debug_loc) { Dwarf_Addr escape = (width == 8 ? (Elf64_Addr) -1 : (Elf64_Addr) (Elf32_Addr) -1); diff --git a/src/ChangeLog b/src/ChangeLog index e7ba6cb..f424fb7 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,10 @@ 2018-05-29 Mark Wielaard + * readelf.c (print_debug_loc_section): Handle GNU DebugFission list + entries. + +2018-05-29 Mark Wielaard + * readelf.c (print_debug): Record and reset section_info status in implicit_debug_sections and print_debug_sections. diff --git a/src/readelf.c b/src/readelf.c index 390f244..2ccbea5 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -9276,15 +9276,81 @@ print_debug_loc_section (Dwfl_Module *dwflmod, continue; } - if (unlikely (data->d_size - offset < (size_t) address_size * 2)) - { + /* GNU DebugFission encoded addresses as addrx. */ + bool is_debugfission = ((cu != NULL +
Re: [PATCH] libdwfl: Allow partial relocations also for debug files.
On Sun, 2018-05-27 at 14:13 +0200, Mark Wielaard wrote: > __libdwfl_relocate is called for get_dwarf and get_elf. We allow not all > relocations to be resolved for Elf files, but required all relocations > (in the debug sections) to be fully resoled in Dwarf files. This used to > mostly work out with .o ET_REL files when the main Elf was gotten before > the Dwarf. But with .dwo files, we (readelf) might open the .o file just > for the (skeleton) Dwarf. In this case it could happen not all relocations > in the debug sections could be resolved (.debug_info and .debug_addr might > contain referenes to undefined symbols). So allow partial relocations > also for debug files. Pushed to master.
Re: [PATCH] readelf: Handle .debug_loclists.
On Sun, 2018-05-27 at 14:25 +0200, Mark Wielaard wrote: > The new DWARF5 .debug_loclists sections are like .debug_rnglists, but > plus locations. For Split Dwarf GCC generates the .debug_loclists fully > in the split .dwo file. Any references to addresses need to be resolved > through the skeleton .debug_addr section. Pushed to master.
[PATCH] libdw: Handle split Dwarf Dies in dwarf_die_addr_die.
dwarf_die_addr_die can be used to turn an Dwarf_Die addr back into a full Dwarf_Die, just given the original Dwarf debug handle. This now also works for Dwarf_Dies which originated from a split Dwarf. Whenever a split Dwarf_CU is found the Dwarf it originated from is registered with the Dwarf that the skeleton Dwarf_CU came from. All registered split Dwarfs are then searched by dwarf_die_addr_die if the addr didn't match the main Dwarf or the alt Dwarf. One limitation in this implementation is that only DIEs that come from the main .debug_info in the .dwo are supported. Theoretically there could also be DIEs in an .debug_type or from other/multiple (comdat) sections. New tests are added for dwarf-4, dwarf-5, split-dwarf-4, split-dwarf-5 and version 4 and 5 dwo files. Signed-off-by: Mark Wielaard --- libdw/ChangeLog | 13 +++ libdw/dwarf_cuoffset.c | 2 +- libdw/dwarf_die_addr_die.c | 14 +++- libdw/libdwP.h | 9 libdw/libdw_find_split_unit.c | 9 libdw/libdw_findcu.c| 49 + tests/ChangeLog | 7 ++ tests/dwarf-die-addr-die.c | 14 tests/run-dwarf-die-addr-die.sh | 14 9 files changed, 129 insertions(+), 2 deletions(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index eb0b01a..e3b15f0 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,5 +1,18 @@ 2018-05-29 Mark Wielaard + * dwarf_cuoffset.c (dwarf_cuoffset): Check die->cu is not NULL. + * dwarf_die_addr_die.c (dwarf_die_addr_die): Also search split + Dwarfs. + * libdwP.h (struct Dwarf): Add split_tree field. + (__libdw_find_split_dbg_addr): New internal function definition. + (__libdw_finddbg_cb): Likewise. + * libdw_find_split_unit.c (__libdw_find_split_unit): Insert split + Dwarf into skeleton dbg split_tree. + * libdw_findcu.c (__libdw_finddbg_cb): New function. + (__libdw_find_split_dbg_addr): Likewise. + +2018-05-29 Mark Wielaard + * dwarf.h: Add GNU DebugFission list entry encodings DW_LLE_GNU_end_of_list_entry, DW_LLE_GNU_base_address_selection_entry, diff --git a/libdw/dwarf_cuoffset.c b/libdw/dwarf_cuoffset.c index ba37648..f13b02f 100644 --- a/libdw/dwarf_cuoffset.c +++ b/libdw/dwarf_cuoffset.c @@ -38,7 +38,7 @@ Dwarf_Off dwarf_cuoffset (Dwarf_Die *die) { - return (die == NULL + return ((die == NULL || die->cu == NULL) ? (Dwarf_Off) -1l : (Dwarf_Off) (die->addr - die->cu->startp)); } diff --git a/libdw/dwarf_die_addr_die.c b/libdw/dwarf_die_addr_die.c index 02d63b7..6572916 100644 --- a/libdw/dwarf_die_addr_die.c +++ b/libdw/dwarf_die_addr_die.c @@ -30,6 +30,8 @@ # include #endif +#include + #include #include "libdwP.h" @@ -50,7 +52,17 @@ dwarf_die_addr_die (Dwarf *dbg, void *addr, Dwarf_Die *result) } if (cu == NULL) -return NULL; +{ + Dwarf *split = __libdw_find_split_dbg_addr (dbg, addr); + if (split != NULL) + cu = __libdw_findcu_addr (split, addr); +} + + if (cu == NULL) +{ + memset (result, '\0', sizeof (Dwarf_Die)); + return NULL; +} *result = (Dwarf_Die) { .addr = addr, .cu = cu }; diff --git a/libdw/libdwP.h b/libdw/libdwP.h index dd47009..1c8dd0d 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -193,6 +193,9 @@ struct Dwarf Dwarf_Off next_tu_offset; Dwarf_Sig8_Hash sig8_hash; + /* Search tree for split Dwarf associated with CUs in this debug. */ + void *split_tree; + /* Search tree for .debug_macro operator tables. */ void *macro_ops; @@ -619,6 +622,10 @@ extern struct Dwarf_CU *__libdw_findcu (Dwarf *dbg, Dwarf_Off offset, bool tu) extern struct Dwarf_CU *__libdw_findcu_addr (Dwarf *dbg, void *addr) __nonnull_attribute__ (1) internal_function; +/* Find split Dwarf for given DIE address. */ +extern struct Dwarf *__libdw_find_split_dbg_addr (Dwarf *dbg, void *addr) + __nonnull_attribute__ (1) internal_function; + /* Find the split (or skeleton) unit. */ extern struct Dwarf_CU *__libdw_find_split_unit (Dwarf_CU *cu) internal_function; @@ -1261,6 +1268,8 @@ __libdw_cu_locs_base (Dwarf_CU *cu) return cu->locs_base; } +/* Helper function for tsearch/tfind split_tree Dwarf. */ +int __libdw_finddbg_cb (const void *arg1, const void *arg2); /* Link skeleton and split compile units. */ static inline void diff --git a/libdw/libdw_find_split_unit.c b/libdw/libdw_find_split_unit.c index d6527e0..dc62e0d 100644 --- a/libdw/libdw_find_split_unit.c +++ b/libdw/libdw_find_split_unit.c @@ -34,6 +34,7 @@ #include "libelfP.h" #include +#include #include #include #include @@ -84,6 +85,14 @@ __libdw_find_split_unit (Dwarf_CU *cu) if (split->unit_type == DW_UT_split_compile && cu->unit_id8 == split->unit_id8) { +
Re: [PATCH] libdw: Handle split Dwarf Dies in dwarf_die_addr_die.
On Tue, 2018-05-29 at 23:57 +0200, Mark Wielaard wrote: > dwarf_die_addr_die can be used to turn an Dwarf_Die addr back into a > full Dwarf_Die, just given the original Dwarf debug handle. This now > also works for Dwarf_Dies which originated from a split Dwarf. Whenever > a split Dwarf_CU is found the Dwarf it originated from is registered > with the Dwarf that the skeleton Dwarf_CU came from. All registered > split Dwarfs are then searched by dwarf_die_addr_die if the addr didn't > match the main Dwarf or the alt Dwarf. > > One limitation in this implementation is that only DIEs that come from > the main .debug_info in the .dwo are supported. Theoretically there could > also be DIEs in an .debug_type or from other/multiple (comdat) sections. > > New tests are added for dwarf-4, dwarf-5, split-dwarf-4, split-dwarf-5 > and version 4 and 5 dwo files. And clearly I hadn't done a make distcheck because then I would have known that valgrind would warn about leaking the new search tree. Simple fix: diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c index 23a50a0..29795c1 100644 --- a/libdw/dwarf_end.c +++ b/libdw/dwarf_end.c @@ -91,6 +91,9 @@ dwarf_end (Dwarf *dwarf) /* Search tree for decoded .debug_lines units. */ tdestroy (dwarf->files_lines, noop_free); + /* And the split Dwarf. */ + tdestroy (dwarf->split_tree, noop_free); + struct libdw_memblock *memp = dwarf->mem_tail; /* The first block is allocated together with the Dwarf object. */ while (memp->prev != NULL)
Re: [PATCH] libdw: Handle .debug_loclists in dwarf_getlocation.
On Mon, 2018-05-28 at 13:32 +0200, Mark Wielaard wrote: > Handle all new DW_LLE opcodes in .debug_loclists in dwarf_getlocation. > __libdw_read_begin_end_pair_inc now also handles a default location > (which is simply the range [0,-1]). Since expression blocks can now > also come from the .debug_loclists section add a new fake_loclists_cu > necessary for checking bounds while parsing expression blocks. Adapt > varlocs test to handle .debug only files. Run it on testfileranges5.debug > and testfilesplitranges5.debug. Pushed to master (without the regeneration of the testfiles since that was already done in an earlier commit).
[PATCH] Prepare for 0.171.
Set version to 0.171. Update po/*.po files. Mention DWARF5, split dwarf and GNU DebugFission support in NEWS. Signed-off-by: Mark Wielaard I think we are ready for a release now. For people who like to try out a tar ball, there is now an rc1 (0.170.99) at: https://sourceware.org/elfutils/ftp/rc/elfutils-0.170.90.tar.bz2 It includes all pending patches up to this one (with the version number changed). Please give feedback if you find some time to try it out. Thanks, Mark --- ChangeLog |5 + NEWS| 37 ++ config/ChangeLog|4 + config/elfutils.spec.in | 14 + configure.ac|2 +- po/ChangeLog|4 + po/de.po| 1280 +++-- po/es.po| 1313 -- po/ja.po| 1306 -- po/pl.po| 1320 -- po/uk.po| 1323 +-- 11 files changed, 4041 insertions(+), 2567 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8154241..04d86f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-05-29 Mark Wielaard + + * configure.ac: Set version to 0.171. + * NEWS: Mention DWARF5, split-dwarf and GNU DebugFission support. + 2018-03-17 Mark Wielaard * configure.ac (CHECK_FUNCS): Check for process_vm_readv. diff --git a/NEWS b/NEWS index 72e5118..a085d3e 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,40 @@ +Version 0.171 + +DWARF5 and split dwarf, including GNU DebugFission, are supported now. +Data can be read from the new DWARF sections .debug_addr, .debug_line_str, +.debug_loclists, .debug_str_offsets and .debug_rnglists. Plus the new +DWARF5 and GNU DebugFission encodings of the existing .debug sections. +Also in split DWARF .dwo (DWARF object) files. This support is mostly +handled by existing functions (dwarf_getlocation*, dwarf_getsrclines, +dwarf_ranges, dwarf_form*, etc.) now returning the data from the new +sections and data formats. But some new functions have been added +to more easily get information about skeleton and split compile units +(dwarf_get_units and dwarf_cu_info), handle new attribute data +(dwarf_getabbrevattr_data) and to keep references to Dwarf_Dies +that might come from different sections or files (dwarf_die_addr_die). + +Not yet supported are .dwp (Dwarf Package) and .sup (Dwarf Supplementary) +files, the .debug_names index, the .debug_cu_index and .debug_tu_index +sections. + +readelf: Handle all new DWARF5 sections. + --debug-dump=info+ will show split unit DIEs when found. + --dwarf-skeleton can be used when inspecting a .dwo file. +Recognizes GNU locviews with --debug-dump=loc. + +libdw: New functions dwarf_die_addr_die, dwarf_get_units, + dwarf_getabbrevattr_data and dwarf_cu_info. + libdw will now try to resolve the alt file on first use of + an alt attribute FORM when not set yet with dwarf_set_alt. + dwarf_aggregate_size() now works with multi-dimensional arrays. + +libdwfl: Use process_vm_readv when available instead of ptrace. + +backends: Add a RISC-V backend. + +There were various improvements to build on Windows. +The sha1 and md5 implementations have been removed, they weren't used. + Version 0.170 libdw: Added new DWARF5 attribute, tag, character encoding, language code, diff --git a/config/ChangeLog b/config/ChangeLog index 681def2..fe58df0 100644 --- a/config/ChangeLog +++ b/config/ChangeLog @@ -1,3 +1,7 @@ +2018-05-29 Mark Wielaard + + * elfutils.spec.in: Update for 0.171. + 2018-02-09 Joshua Watt * eu.am (IMPLICIT_FALLTHROUGH_WARNING): Set to 5. diff --git a/config/elfutils.spec.in b/config/elfutils.spec.in index 1d0a4f8..763e035 100644 --- a/config/elfutils.spec.in +++ b/config/elfutils.spec.in @@ -227,6 +227,20 @@ rm -rf ${RPM_BUILD_ROOT} %{_sysctldir}/10-default-yama-scope.conf %changelog +* Wed May 30 2018 Mark Wielaard 0.171-1 +- DWARF5 and split dwarf, including GNU DebugFission, support. +- readelf: Handle all new DWARF5 sections. + --debug-dump=info+ will show split unit DIEs when found. + --dwarf-skeleton can be used when inspecting a .dwo file. + Recognizes GNU locviews with --debug-dump=loc. +- libdw: New functions dwarf_die_addr_die, dwarf_get_units, + dwarf_getabbrevattr_data and dwarf_cu_info. + libdw will now try to resolve the alt file on first use + when not set yet with dwarf_set_alt. + dwarf_aggregate_size() now works with multi-dimensional arrays. +- libdwfl: Use process_vm_readv when available instead of ptrace. +- backends: Add a RISC-V backend. + * Wed Aug 2 2017 Mark Wielaard 0.170-1 - libdw: Added new DWARF5 attribute, tag, character encoding, language code, calling convention, defaulted member function diff --git a/configure.ac b/configure.ac index ab32cbc..183ffb5 1