From 581c3f60e2b1fc7ddaf4260bb5a9cb59f8e3f0d0 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 21 Mar 2012 08:54:32 -0600 Subject: [PATCH] Fix bug using dwarf_next_unit to iterate over .debug_types * libdw_findcu.c (findcu_cb): Move earlier. (__libdw_intern_next_unit): Add new CU to search tree here... (__libdw_findcu): ... not here. * typeiter.c: New file. * run-typeiter.sh: New file. * testfile59.bz2: New file. * Makefile.am (noinst_PROGRAMS): Add typeiter. (TESTS): Add run-typeiter.sh. (EXTRA_DIST): Add run-typeiter.sh, testfile59.bz2. (typeiter_LDADD): New variable. If you call dwarf_next_unit to iterate over .debug_types, then call dwarf_offdie_types, you can see a failure if some earlier call happened to call __libdw_intern_next_unit via dwarf_formref_die. What happens is that __libdw_intern_next_unit updates the Dwarf's next_tu_offset, but does not add the TU to the TU search tree. So, the call to dwarf_offdie_types does not find the TU in the tree, and will not search any more, causing a failure. This fix changes __libdw_intern_next_unit to add the TU to the search tree, rather than relying on __libdw_findcu to do it. --- libdw/ChangeLog | 6 +++ libdw/libdw_findcu.c | 68 ++++++++++++++--------------- tests/ChangeLog | 10 +++++ tests/Makefile.am | 8 ++-- tests/run-typeiter.sh | 58 +++++++++++++++++++++++++ tests/testfile59.bz2 | Bin 0 -> 3097 bytes tests/typeiter.c | 98 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 210 insertions(+), 38 deletions(-) create mode 100755 tests/run-typeiter.sh create mode 100755 tests/testfile59.bz2 create mode 100644 tests/typeiter.c diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 98b67f4a7..f96c0d1ba 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,9 @@ +2012-03-19 Tom Tromey + + * libdw_findcu.c (findcu_cb): Move earlier. + (__libdw_intern_next_unit): Add new CU to search tree here... + (__libdw_findcu): ... not here. + 2012-01-31 Mark Wielaard * dwarf_formudata.c (dwarf_formudata): Handle DW_FORM_sec_offset. diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c index 8e5f9e9b1..83c96bafd 100644 --- a/libdw/libdw_findcu.c +++ b/libdw/libdw_findcu.c @@ -56,6 +56,31 @@ #include #include "libdwP.h" +static int +findcu_cb (const void *arg1, const void *arg2) +{ + struct Dwarf_CU *cu1 = (struct Dwarf_CU *) arg1; + struct Dwarf_CU *cu2 = (struct Dwarf_CU *) arg2; + + /* Find out which of the two arguments is the search value. It has + end offset 0. */ + if (cu1->end == 0) + { + if (cu1->start < cu2->start) + return -1; + if (cu1->start >= cu2->end) + return 1; + } + else + { + if (cu2->start < cu1->start) + return 1; + if (cu2->start >= cu1->end) + return -1; + } + + return 0; +} struct Dwarf_CU * internal_function @@ -65,6 +90,7 @@ __libdw_intern_next_unit (dbg, debug_types) { Dwarf_Off *const offsetp = debug_types ? &dbg->next_tu_offset : &dbg->next_cu_offset; + void **tree = debug_types ? &dbg->tu_tree : &dbg->cu_tree; Dwarf_Off oldoff = *offsetp; uint16_t version; @@ -105,34 +131,16 @@ __libdw_intern_next_unit (dbg, debug_types) newp->lines = NULL; newp->locs = NULL; - return newp; -} - - -static int -findcu_cb (const void *arg1, const void *arg2) -{ - struct Dwarf_CU *cu1 = (struct Dwarf_CU *) arg1; - struct Dwarf_CU *cu2 = (struct Dwarf_CU *) arg2; - - /* Find out which of the two arguments is the search value. It has - end offset 0. */ - if (cu1->end == 0) + /* Add the new entry to the search tree. */ + if (tsearch (newp, tree, findcu_cb) == NULL) { - if (cu1->start < cu2->start) - return -1; - if (cu1->start >= cu2->end) - return 1; - } - else - { - if (cu2->start < cu1->start) - return 1; - if (cu2->start >= cu1->end) - return -1; + /* Something went wrong. Undo the operation. */ + *offsetp = oldoff; + __libdw_seterrno (DWARF_E_NOMEM); + return NULL; } - return 0; + return newp; } struct Dwarf_CU * @@ -160,20 +168,10 @@ __libdw_findcu (dbg, start, debug_types) /* No. Then read more CUs. */ while (1) { - Dwarf_Off oldoff = *next_offset; struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, debug_types); if (newp == NULL) return NULL; - /* Add the new entry to the search tree. */ - if (tsearch (newp, tree, findcu_cb) == NULL) - { - /* Something went wrong. Undo the operation. */ - *next_offset = oldoff; - __libdw_seterrno (DWARF_E_NOMEM); - return NULL; - } - /* Is this the one we are looking for? */ if (start < *next_offset) // XXX Match exact offset. diff --git a/tests/ChangeLog b/tests/ChangeLog index a7825911e..8d2b83f18 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,13 @@ +2012-03-21 Tom Tromey + + * typeiter.c: New file. + * run-typeiter.sh: New file. + * testfile59.bz2: New file. + * Makefile.am (noinst_PROGRAMS): Add typeiter. + (TESTS): Add run-typeiter.sh. + (EXTRA_DIST): Add run-typeiter.sh, testfile59.bz2. + (typeiter_LDADD): New variable. + 2012-02-21 Kurt Roeckx * run-alldts.sh: testrun ./alldts. diff --git a/tests/Makefile.am b/tests/Makefile.am index 3074c8934..f2c211b56 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -58,7 +58,7 @@ noinst_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ dwfl-addr-sect dwfl-bug-report early-offscn \ dwfl-bug-getmodules dwarf-getmacros addrcfi \ test-flag-nobits dwarf-getstring rerequest_tag \ - alldts md5-sha1-test + alldts md5-sha1-test typeiter asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \ asm-tst6 asm-tst7 asm-tst8 asm-tst9 @@ -86,7 +86,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-disasm-x86.sh run-disasm-x86-64.sh \ run-early-offscn.sh run-dwarf-getmacros.sh \ run-test-flag-nobits.sh run-prelink-addr-test.sh \ - run-dwarf-getstring.sh run-rerequest_tag.sh + run-dwarf-getstring.sh run-rerequest_tag.sh run-typeiter.sh # run-show-ciefde.sh if !STANDALONE @@ -161,7 +161,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ testfile55-32.bz2 testfile55-32.debug.bz2 \ testfile55-32.prelink.bz2 testfile55-64.bz2 \ testfile55-64.debug.bz2 testfile55-64.prelink.bz2 \ - testfile56.bz2 testfile57.bz2 testfile58.bz2 + testfile56.bz2 testfile57.bz2 testfile58.bz2 \ + run-typeiter.sh testfile59.bz2 installed_TESTS_ENVIRONMENT = libdir=$(DESTDIR)$(libdir) \ bindir=$(DESTDIR)$(bindir) \ @@ -258,6 +259,7 @@ test_flag_nobits_LDADD = $(libelf) $(libmudflap) rerequest_tag_LDADD = $(libdw) $(libmudflap) alldts_LDADD = $(libebl) $(libelf) $(libmudflap) md5_sha1_test_LDADD = $(libeu) +typeiter_LDADD = $(libdw) $(libelf) $(libmudflap) if GCOV check: check-am coverage diff --git a/tests/run-typeiter.sh b/tests/run-typeiter.sh new file mode 100755 index 000000000..4f650ca68 --- /dev/null +++ b/tests/run-typeiter.sh @@ -0,0 +1,58 @@ +#! /bin/sh +# Copyright (C) 2012 Red Hat, Inc. +# This file is part of Red Hat elfutils. +# +# Red Hat elfutils is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the +# Free Software Foundation; version 2 of the License. +# +# Red Hat elfutils is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Red Hat elfutils; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. +# +# Red Hat elfutils is an included package of the Open Invention Network. +# An included package of the Open Invention Network is a package for which +# Open Invention Network licensees cross-license their patents. No patent +# license is granted, either expressly or impliedly, by designation as an +# included package. Should you wish to participate in the Open Invention +# Network licensing program, please visit www.openinventionnetwork.com +# . + +. $srcdir/test-subr.sh + +# struct s1 +# { +# char c; +# short s; +# int i; +# long l; +# float f; +# double d; +# }; +# +# s1 S1; +# +# int func (s1 *p) +# { +# return p->i; +# } +# +# int main() +# { +# return func (&S1); +# } +# +# g++ -gdwarf-4 -g -fdebug-types-section + +testfiles testfile59 + +testrun_compare ./typeiter testfile59 <<\EOF +ok +EOF + +exit 0 diff --git a/tests/testfile59.bz2 b/tests/testfile59.bz2 new file mode 100755 index 0000000000000000000000000000000000000000..bcee648cfcfd204b8c793937bb87393c67b1b754 GIT binary patch literal 3097 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 literal 0 Hc-jL100001 diff --git a/tests/typeiter.c b/tests/typeiter.c new file mode 100644 index 000000000..184b00be4 --- /dev/null +++ b/tests/typeiter.c @@ -0,0 +1,98 @@ +/* Copyright (C) 2012 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include ELFUTILS_HEADER(dw) +#include +#include +#include + +int +main (int argc, char *argv[]) +{ + for (int i = 1; i < argc; ++i) + { + int fd = open (argv[i], O_RDONLY); + + Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ); + if (dbg != NULL) + { + Dwarf_Off off = 0; + size_t cuhl; + Dwarf_Off noff; + + while (dwarf_nextcu (dbg, off, &noff, &cuhl, NULL, NULL, NULL) == 0) + { + Dwarf_Die die_mem; + Dwarf_Die *die = dwarf_offdie (dbg, off + cuhl, &die_mem); + + Dwarf_Die iter_mem; + Dwarf_Die *iter = &iter_mem; + dwarf_child (die, &iter_mem); + + while (1) + { + if (dwarf_tag (iter) == DW_TAG_variable) + { + Dwarf_Attribute attr_mem; + Dwarf_Die form_mem; + dwarf_formref_die (dwarf_attr (iter, DW_AT_type, + &attr_mem), + &form_mem); + } + + if (dwarf_siblingof (iter, &iter_mem) != 0) + break; + } + + off = noff; + } + + off = 0; + uint64_t type_sig; + + while (dwarf_next_unit (dbg, off, &noff, &cuhl, NULL, NULL, NULL, + NULL, &type_sig, NULL) == 0) + { + Dwarf_Die die_mem; + Dwarf_Die *die = dwarf_offdie_types (dbg, off + cuhl, &die_mem); + + if (die == NULL) + printf ("fail\n"); + else + printf ("ok\n"); + + off = noff; + } + + dwarf_end (dbg); + } + + close (fd); + } +} -- 2.47.2