From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 46678 invoked by alias); 29 May 2018 21:57:55 -0000 Mailing-List: contact elfutils-devel-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Post: List-Help: List-Subscribe: Sender: elfutils-devel-owner@sourceware.org Received: (qmail 46660 invoked by uid 89); 29 May 2018 21:57:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Checked: by ClamAV 0.99.4 on sourceware.org X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.2 spammy=limitation, 12616 X-Spam-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.2 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on sourceware.org X-Spam-Level: X-HELO: gnu.wildebeest.org Received: from wildebeest.demon.nl (HELO gnu.wildebeest.org) (212.238.236.112) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 29 May 2018 21:57:50 +0000 Received: from tarox.wildebeest.org (tarox.wildebeest.org [172.31.17.39]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by gnu.wildebeest.org (Postfix) with ESMTPSA id 5CF5130008C1; Tue, 29 May 2018 23:57:48 +0200 (CEST) Received: by tarox.wildebeest.org (Postfix, from userid 1000) id 348704001140; Tue, 29 May 2018 23:57:48 +0200 (CEST) From: Mark Wielaard To: elfutils-devel@sourceware.org Cc: Mark Wielaard Subject: [PATCH] libdw: Handle split Dwarf Dies in dwarf_die_addr_die. Date: Tue, 29 May 2018 21:57:00 -0000 Message-Id: <1527631066-31956-1-git-send-email-mark@klomp.org> X-Mailer: git-send-email 1.8.3.1 X-Spam-Flag: NO X-IsSubscribed: yes X-SW-Source: 2018-q2/txt/msg00101.txt.bz2 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) { + if (tsearch (split->dbg, &cu->dbg->split_tree, + __libdw_finddbg_cb) == NULL) + { + /* Something went wrong. Don't link. */ + __libdw_seterrno (DWARF_E_NOMEM); + break; + } + /* Link skeleton and split compile units. */ __libdw_link_skel_split (cu, split); diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c index 9d23199..2f5c6c4 100644 --- a/libdw/libdw_findcu.c +++ b/libdw/libdw_findcu.c @@ -61,6 +61,40 @@ findcu_cb (const void *arg1, const void *arg2) return 0; } +int +__libdw_finddbg_cb (const void *arg1, const void *arg2) +{ + Dwarf *dbg1 = (Dwarf *) arg1; + Dwarf *dbg2 = (Dwarf *) arg2; + + Elf_Data *dbg1_data = dbg1->sectiondata[IDX_debug_info]; + unsigned char *dbg1_start = dbg1_data->d_buf; + size_t dbg1_size = dbg1_data->d_size; + + Elf_Data *dbg2_data = dbg2->sectiondata[IDX_debug_info]; + unsigned char *dbg2_start = dbg2_data->d_buf; + size_t dbg2_size = dbg2_data->d_size; + + /* Find out which of the two arguments is the search value. It has + a size of 0. */ + if (dbg1_size == 0) + { + if (dbg1_start < dbg2_start) + return -1; + if (dbg1_start >= dbg2_start + dbg2_size) + return 1; + } + else + { + if (dbg2_start < dbg1_start) + return 1; + if (dbg2_start >= dbg1_start + dbg1_size) + return -1; + } + + return 0; +} + struct Dwarf_CU * internal_function __libdw_intern_next_unit (Dwarf *dbg, bool debug_types) @@ -247,3 +281,18 @@ __libdw_findcu_addr (Dwarf *dbg, void *addr) return NULL; } + +Dwarf * +internal_function +__libdw_find_split_dbg_addr (Dwarf *dbg, void *addr) +{ + /* XXX Assumes split DWARF only has CUs in main IDX_debug_info. */ + Elf_Data fake_data = { .d_buf = addr, .d_size = 0 }; + Dwarf fake = { .sectiondata[IDX_debug_info] = &fake_data }; + Dwarf **found = tfind (&fake, &dbg->split_tree, __libdw_finddbg_cb); + + if (found != NULL) + return *found; + + return NULL; +} diff --git a/tests/ChangeLog b/tests/ChangeLog index 2b255c7..b656bee 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,5 +1,12 @@ 2018-05-29 Mark Wielaard + * dwarf-die-addr-die.c (check_dbg): Also check subdies, split or + type, gotten through dwarf_get_units. + * run-dwarf-die-addr-die.sh: Add tests for dwarf-4, dwarf-5, + split-dwarf-4, split-dwarf-5 and dwo files. + +2018-05-29 Mark Wielaard + * run-readelf-loc.sh: Add GNU DebugFission split-dwarf variant. * run-varlocs.sh: Likewise. diff --git a/tests/dwarf-die-addr-die.c b/tests/dwarf-die-addr-die.c index b4f6dbc..7899988 100644 --- a/tests/dwarf-die-addr-die.c +++ b/tests/dwarf-die-addr-die.c @@ -134,6 +134,20 @@ check_dbg (Dwarf *dbg) res |= check_dbg (alt); } + // Split or Type Dwarf_Dies gotten through dwarf_get_units. + Dwarf_CU *cu = NULL; + Dwarf_Die subdie; + uint8_t unit_type; + while (dwarf_get_units (dbg, cu, &cu, NULL, + &unit_type, NULL, &subdie) == 0) + { + if (dwarf_tag (&subdie) != DW_TAG_invalid) + { + printf ("checking %" PRIx8 " subdie\n", unit_type); + res |= check_die (&subdie); + } + } + return res; } diff --git a/tests/run-dwarf-die-addr-die.sh b/tests/run-dwarf-die-addr-die.sh index 16fe7b0..951d1c5 100755 --- a/tests/run-dwarf-die-addr-die.sh +++ b/tests/run-dwarf-die-addr-die.sh @@ -32,6 +32,20 @@ testfiles testfilebazdbgppc64.debug testrun ${abs_builddir}/dwarf-die-addr-die testfilebazdbgppc64.debug +# see tests/testfile-dwarf-45.source +testfiles testfile-dwarf-4 testfile-dwarf-5 +testfiles testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo +testfiles testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo + +testrun ${abs_builddir}/dwarf-die-addr-die testfile-dwarf-4 +testrun ${abs_builddir}/dwarf-die-addr-die testfile-dwarf-5 +testrun ${abs_builddir}/dwarf-die-addr-die testfile-splitdwarf-4 +testrun ${abs_builddir}/dwarf-die-addr-die testfile-splitdwarf-5 +testrun ${abs_builddir}/dwarf-die-addr-die testfile-hello4.dwo +testrun ${abs_builddir}/dwarf-die-addr-die testfile-world4.dwo +testrun ${abs_builddir}/dwarf-die-addr-die testfile-hello5.dwo +testrun ${abs_builddir}/dwarf-die-addr-die testfile-world5.dwo + # Self test testrun_on_self ${abs_builddir}/dwarf-die-addr-die -- 1.8.3.1