From 488d41b366fe064141fb7b82a705d9a04bee0fbc Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Tue, 27 Oct 2009 16:40:32 +0100 Subject: [PATCH] dwarflint: Check for dup attribs between DIE and its DW_AT_abstract_origin --- src/Makefile.am | 3 +- src/dwarflint/check_dups_abstract_origin.cc | 102 ++++++++++++++++++++ src/dwarflint/checks-high.hh | 35 +++++++ src/dwarflint/messages.cc | 8 ++ src/dwarflint/messages.h | 13 +++ 5 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 src/dwarflint/check_dups_abstract_origin.cc diff --git a/src/Makefile.am b/src/Makefile.am index 05c994eeb..1a7d10df2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -98,7 +98,8 @@ dwarflint_SOURCES = dwarfstrings.c \ dwarflint/check_debug_line.cc \ dwarflint/check_matching_ranges.cc \ dwarflint/check_range_out_of_scope.cc \ - dwarflint/check_expected_trees.cc + dwarflint/check_expected_trees.cc \ + dwarflint/check_dups_abstract_origin.cc readelf_SOURCES = readelf.c dwarfstrings.c diff --git a/src/dwarflint/check_dups_abstract_origin.cc b/src/dwarflint/check_dups_abstract_origin.cc new file mode 100644 index 000000000..867779ee2 --- /dev/null +++ b/src/dwarflint/check_dups_abstract_origin.cc @@ -0,0 +1,102 @@ +/* Pedantic checking of DWARF files. + Copyright (C) 2009 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 + . */ + +// Implements a check for +// https://bugzilla.redhat.com/show_bug.cgi?id=527430 +// +// Roland: If a given attribute name is present on a DIE, it is +// suspicious if that attribute name appears on the DIE that's the +// first DIE's DW_AT_abstract_origin or DW_AT_specification. + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "checks-high.hh" +#include "dwarfstrings.h" +#include "all-dies-it.hh" +#include + +using elfutils::dwarf; + +namespace +{ + class check_dups_abstract_origin + : public highlevel_check + { + public: + explicit check_dups_abstract_origin (dwarflint &lint) + : highlevel_check (lint) + { + struct { + void operator () (dwarf::debug_info_entry const &die, + dwarf::attribute const &attr) + { + std::map m; + for (dwarf::debug_info_entry::attributes_type::const_iterator + at = die.attributes ().begin (); + at != die.attributes ().end (); ++at) + m.insert (std::make_pair ((*at).first, (*at).second)); + + dwarf::attr_value const &val = attr.second; + // xxx Referree can't be const&, gives memory errors. + dwarf::debug_info_entry referree = *val.reference (); + + std::map::const_iterator at2; + for (dwarf::debug_info_entry::attributes_type::const_iterator + at = referree.attributes ().begin (); + at != referree.attributes ().end (); ++at) + if ((at2 = m.find ((*at).first)) != m.end ()) + wr_message (to_where (die), + cat (mc_impact_3, mc_acc_bloat, mc_die_rel)) + << "Attribute " << dwarf_attr_string (at2->first) + << " is duplicated at " << dwarf_attr_string (attr.first) + << " (" << pri::ref (referree) << ")" + << (at2->second == (*at).second + ? "." : " with different value.") + << std::endl; + } + } check; + + for (all_dies_iterator it = all_dies_iterator (dw); + it != all_dies_iterator (); ++it) + { + // Do we have DW_AT_abstract_origin or DW_AT_specification? + dwarf::debug_info_entry const &die = *it; + for (dwarf::debug_info_entry::attributes_type::const_iterator + at = die.attributes ().begin (); + at != die.attributes ().end (); ++at) + if ((*at).first == DW_AT_abstract_origin + || (*at).first == DW_AT_specification) + { + assert ((*at).second.what_space () == dwarf::VS_reference); + check (die, *at); + } + } + } + }; + + reg reg; +} diff --git a/src/dwarflint/checks-high.hh b/src/dwarflint/checks-high.hh index 1723aac99..6e1a63ec9 100644 --- a/src/dwarflint/checks-high.hh +++ b/src/dwarflint/checks-high.hh @@ -1,3 +1,28 @@ +/* Pedantic checking of DWARF files. + Copyright (C) 2009 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 "checks-low.hh" #include "config.h" #include "c++/dwarf" @@ -26,3 +51,13 @@ public: dwarf_end (_m_handle); } }; + +template +inline where +to_where (T const &die) +{ + where ret = WHERE (sec_info, NULL); + where_reset_1 (&ret, 0); + where_reset_2 (&ret, die.offset ()); + return ret; +} diff --git a/src/dwarflint/messages.cc b/src/dwarflint/messages.cc index 83e9c94fc..afed6b764 100644 --- a/src/dwarflint/messages.cc +++ b/src/dwarflint/messages.cc @@ -310,3 +310,11 @@ pri::operator << (std::ostream &os, pri::pribase const &obj) { return os << obj.m_a << obj.m_b << obj.m_c; } + +std::ostream & +pri::operator << (std::ostream &os, pri::ref const &obj) +{ + std::stringstream ss; + ss << std::hex << "DIE " << obj.off; + return os << ss.str (); +} diff --git a/src/dwarflint/messages.h b/src/dwarflint/messages.h index e920e4ffd..8b595f284 100644 --- a/src/dwarflint/messages.h +++ b/src/dwarflint/messages.h @@ -2,6 +2,7 @@ #define DWARFLINT_MESSAGES_H #include "where.h" +#include "libdw.h" #ifdef __cplusplus # define IF_CPLUSPLUS(X) X @@ -180,6 +181,18 @@ namespace pri : pribase (what, " seems to lack a relocation") {} }; + + class ref + { + Dwarf_Off off; + public: + template + ref (T const &die) + : off (die.offset ()) + {} + friend std::ostream &operator << (std::ostream &os, ref const &obj); + }; + std::ostream &operator << (std::ostream &os, ref const &obj); } #endif -- 2.47.3