From: Mark Wielaard Date: Wed, 13 Apr 2011 10:33:29 +0000 (+0200) Subject: dwarflint: new check_die_line_info die check. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=849c6da0eeb1b453c7bb7ffea25a16c78d7e0a1b;p=thirdparty%2Felfutils.git dwarflint: new check_die_line_info die check. Check that each code block start address is also mentioned in the line table. --- diff --git a/dwarflint/Makefile.am b/dwarflint/Makefile.am index d948a0d85..2a964603c 100644 --- a/dwarflint/Makefile.am +++ b/dwarflint/Makefile.am @@ -88,6 +88,7 @@ dwarflint_SOURCES = \ check_self_referential_die.cc \ check_linkage_external_die.cc \ check_die_decl_call.cc \ + check_die_line_info.cc \ lowlevel_checks.cc lowlevel_checks.hh \ \ ../src/dwarfstrings.c diff --git a/dwarflint/check_die_line_info.cc b/dwarflint/check_die_line_info.cc new file mode 100644 index 000000000..d30453216 --- /dev/null +++ b/dwarflint/check_die_line_info.cc @@ -0,0 +1,144 @@ +/* Check that every block that has an address is also in line info table. + 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 "check_die_tree.hh" +#include "pri.hh" +#include "messages.hh" + +using elfutils::dwarf; + +namespace +{ + class check_die_line_info + : public die_check + { + public: + static checkdescriptor const *descriptor () + { + static checkdescriptor cd + (checkdescriptor::create ("check_die_line_info") + .description ("Check that each code block start address " + "is also mentioned in the line table.\n")); + return &cd; + } + + check_die_line_info (highlevel_check_i *, checkstack &, dwarflint &) + { + // No state stored for this check. + } + + static bool is_code_block (dwarf::debug_info_entry const &entry) + { + int tag = entry.tag (); + switch (tag) + { + case DW_TAG_subprogram: + case DW_TAG_inlined_subroutine: + case DW_TAG_entry_point: + case DW_TAG_lexical_block: + case DW_TAG_label: + case DW_TAG_with_stmt: + case DW_TAG_try_block: + case DW_TAG_catch_block: + return true; + + default: + return false; + } + } + + static void check_die_pc (dwarf::debug_info_entry const &entry, + dwarf::attribute const &pc, + Dwarf_Addr addr) + { + dwarf::compile_unit cu = entry.compile_unit (); + dwarf::line_info_table line_info = cu.line_info (); + dwarf::line_table lines = line_info.lines (); + dwarf::line_table::const_iterator l = lines.find (addr); + + bool found = false; + while (l != lines.end ()) + { + dwarf::line_entry line = *l; + if (line.address () < addr) + { + l++; + continue; + } + else if (line.address () > addr) + { + // Ran past it... + break; + } + + found = true; + break; + } + + if (! found) + wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal) + .id (descriptor ()) + << elfutils::dwarf::tags::name (entry.tag ()) + << " " << dwarf::attributes::name (pc.first) << "=0x" + << std::hex << addr << std::dec + << ", NOT found in line table." << std::endl; + } + + virtual void + die (all_dies_iterator const &it) + { + dwarf::debug_info_entry const &entry = *it; + if (is_code_block (entry)) + { + dwarf::debug_info_entry::attributes_type attrs = entry.attributes (); + + dwarf::debug_info_entry::attributes_type::const_iterator + entry_pc = attrs.find (DW_AT_entry_pc); + if (entry_pc != attrs.end ()) + check_die_pc (entry, *entry_pc, (*entry_pc).second.address ()); + + dwarf::debug_info_entry::attributes_type::const_iterator + low_pc = attrs.find (DW_AT_low_pc); + if (low_pc != attrs.end ()) + check_die_pc (entry, *low_pc, (*low_pc).second.address ()); + + dwarf::debug_info_entry::attributes_type::const_iterator + at_ranges = attrs.find (DW_AT_ranges); + if (at_ranges != attrs.end ()) + { + dwarf::ranges ranges = entry.ranges (); + dwarf::ranges::const_iterator r = ranges.begin (); + while (r != ranges.end ()) + { + check_die_pc (entry, *at_ranges, (*r).first); + r++; + } + } + } + } + }; + + reg_die_check reg; +} diff --git a/dwarflint/tests/run-DW_AT-later-version.sh b/dwarflint/tests/run-DW_AT-later-version.sh index b2f026580..3565dc88c 100755 --- a/dwarflint/tests/run-DW_AT-later-version.sh +++ b/dwarflint/tests/run-DW_AT-later-version.sh @@ -32,4 +32,5 @@ testfiles DW_AT-later-version testrun_compare ./dwarflint --nognu DW_AT-later-version <