From: Petr Machata Date: Thu, 3 Mar 2011 13:24:27 +0000 (+0100) Subject: dwarflint: Fix all-dies-it X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=61cdaa8098037898b62656a268b3c6d5985de4e3;p=thirdparty%2Felfutils.git dwarflint: Fix all-dies-it - Account for the case that die.has_children and at the same time die.children().begin() == die.children().end() - Change the algorithm to iterate DIEs acually in pre-order - Add a test case --- diff --git a/dwarflint/Makefile.am b/dwarflint/Makefile.am index 4b0f592ce..75c215a01 100644 --- a/dwarflint/Makefile.am +++ b/dwarflint/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to create Makefile.in ## -## Copyright (C) 1996-2010 Red Hat, Inc. +## Copyright (C) 1996-2011 Red Hat, Inc. ## This file is part of Red Hat elfutils. ## ## Red Hat elfutils is free software; you can redistribute it and/or modify @@ -36,7 +36,7 @@ AM_LDFLAGS = -Wl,-rpath-link,../libelf:../libdw no_mudflap.os = -fmudflap bin_PROGRAMS = dwarflint -noinst_PROGRAMS = tests/test-coverage tests/test-wrap +noinst_PROGRAMS = tests/test-coverage tests/test-wrap tests/test-all-dies-it dwarflint_SOURCES = \ addr-record.cc addr-record.hh \ @@ -91,6 +91,7 @@ tests_test_coverage_SOURCES = tests/test-coverage.cc coverage.cc pri.cc \ ../src/dwarfstrings.c tests_test_wrap_SOURCES = tests/test-wrap.cc wrap.cc +tests_test_all_dies_it_SOURCES = tests/test-all-dies-it.cc EXTRA_TESTS = tests/run-debug_abbrev-duplicate-attribute.sh \ tests/run-check_duplicate_DW_tag_variable.sh \ @@ -99,7 +100,8 @@ EXTRA_TESTS = tests/run-debug_abbrev-duplicate-attribute.sh \ tests/run-check_range_out_of_scope.sh \ tests/run-check_debug_info_refs.sh \ tests/run-aranges_terminate_early.sh \ - tests/run-libdl-2.12.so.debug.sh + tests/run-libdl-2.12.so.debug.sh \ + tests/run-test-all-dies-it.sh TESTS = $(EXTRA_TESTS) \ tests/test-coverage \ @@ -148,6 +150,7 @@ libdwpp = ../libdw/libdwpp.a $(libdw) dwarflint_LDADD = $(libebl) $(libelf) $(libdwpp) $(libeu) $(libmudflap) -ldl tests_test_coverage_LDADD = $(libebl) $(libelf) $(libdwpp) $(libeu) $(libmudflap) -ldl +tests_test_all_dies_it_LDADD = $(libdwpp) installcheck-binPROGRAMS: $(bin_PROGRAMS) bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \ diff --git a/dwarflint/all-dies-it.hh b/dwarflint/all-dies-it.hh index 57257e3ea..7bcc36f2b 100644 --- a/dwarflint/all-dies-it.hh +++ b/dwarflint/all-dies-it.hh @@ -1,5 +1,5 @@ /* Pedantic checking of DWARF files. - Copyright (C) 2009, 2010 Red Hat, Inc. + Copyright (C) 2009, 2010, 2011 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -41,23 +41,19 @@ class all_dies_iterator die_it_stack_t _m_die_it_stack; bool _m_atend; - void nest () + void start () { - while (_m_die_it->has_children ()) + if (_m_cu_it == _m_cu_it_end) + _m_atend = true; + else { - _m_die_it_stack.push_back (std::make_pair (_m_die_it, _m_die_it_end)); - _m_die_it_end = (*_m_die_it).children ().end (); - _m_die_it = (*_m_die_it).children ().begin (); + _m_die_it = die_it_t (*_m_cu_it); + _m_die_it_end = die_it_t (); + ++_m_cu_it; + assert (_m_die_it != _m_die_it_end); } } - void start () - { - _m_die_it = die_it_t (*_m_cu_it); - _m_die_it_end = die_it_t (); - nest (); - } - public: // An end iterator. all_dies_iterator () @@ -67,9 +63,10 @@ public: explicit all_dies_iterator (T const &dw) : _m_cu_it (dw.compile_units ().begin ()) , _m_cu_it_end (dw.compile_units ().end ()) - , _m_atend (false) + , _m_atend (_m_cu_it == _m_cu_it_end) { - start (); + if (!_m_atend) + start (); } bool operator== (all_dies_iterator const &other) @@ -89,21 +86,26 @@ public: { if (!_m_atend) { - if (++_m_die_it == _m_die_it_end) + if (_m_die_it->has_children () + && _m_die_it->children ().begin () != _m_die_it->children ().end ()) { - if (_m_die_it_stack.size () > 0) - { - _m_die_it = _m_die_it_stack.back ().first; - _m_die_it_end = _m_die_it_stack.back ().second; - _m_die_it_stack.pop_back (); - } - else if (++_m_cu_it == _m_cu_it_end) - _m_atend = true; - else - start (); + _m_die_it_stack.push_back (std::make_pair (_m_die_it, _m_die_it_end)); + _m_die_it_end = _m_die_it->children ().end (); + _m_die_it = _m_die_it->children ().begin (); } else - nest (); + while (++_m_die_it == _m_die_it_end) + + { + if (_m_die_it_stack.size () == 0) + { + start (); + break; + } + _m_die_it = _m_die_it_stack.back ().first; + _m_die_it_end = _m_die_it_stack.back ().second; + _m_die_it_stack.pop_back (); + } } return *this; } @@ -117,7 +119,7 @@ public: typename T::debug_info_entry const &operator* () const { - if (/*unlikely*/ (_m_atend)) + if (unlikely (_m_atend)) throw std::runtime_error ("dereferencing end iterator"); return *_m_die_it; } diff --git a/dwarflint/tests/hello.bad-2.bz2 b/dwarflint/tests/hello.bad-2.bz2 new file mode 100644 index 000000000..8ccbe37b2 Binary files /dev/null and b/dwarflint/tests/hello.bad-2.bz2 differ diff --git a/dwarflint/tests/run-test-all-dies-it.sh b/dwarflint/tests/run-test-all-dies-it.sh new file mode 100755 index 000000000..fb6f83ce9 --- /dev/null +++ b/dwarflint/tests/run-test-all-dies-it.sh @@ -0,0 +1,38 @@ +#! /bin/sh +# Copyright (C) 2011 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/../tests/test-subr.sh + +srcdir=$srcdir/tests + +testfiles hello.bad-2 + +../src/readelf -winfo ./tests/test-all-dies-it | grep '^ \[ *[0-9a-f]*\]' | + sed 's/ \[ *\([0-9a-f]\+\).*/0x\1/' | + testrun_compare ./tests/test-all-dies-it ./tests/test-all-dies-it + +../src/readelf -winfo hello.bad-2 | grep '^ \[ *[0-9a-f]*\]' | + sed 's/ \[ *\([0-9a-f]\+\).*/0x\1/' | + testrun_compare ./tests/test-all-dies-it hello.bad-2 diff --git a/dwarflint/tests/test-all-dies-it.cc b/dwarflint/tests/test-all-dies-it.cc new file mode 100644 index 000000000..e6296fa10 --- /dev/null +++ b/dwarflint/tests/test-all-dies-it.cc @@ -0,0 +1,54 @@ +/* + Copyright (C) 2011 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 + . */ + +#include +#include +#include +#include + +#include "config.h" +#include "../all-dies-it.hh" +#include "../../libdw/c++/dwarf" + +using namespace elfutils; + +int +main (int argc, char ** argv) +{ + assert (argc == 2); + char const *fn = argv[1]; + assert (fn != NULL); + + int fd = open (fn, O_RDONLY); + assert (fd >= 0); + + Dwarf *cdw = dwarf_begin (fd, DWARF_C_READ); + assert (cdw != NULL); + + dwarf dw = cdw; + for (all_dies_iterator it = all_dies_iterator (dw); + it != all_dies_iterator (); ++it) + std::cout << std::hex << "0x" << (*it).offset () << std::endl; +}