]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarflint: new check_die_line_info die check.
authorMark Wielaard <mjw@redhat.com>
Wed, 13 Apr 2011 10:33:29 +0000 (12:33 +0200)
committerMark Wielaard <mjw@redhat.com>
Wed, 13 Apr 2011 10:38:04 +0000 (12:38 +0200)
Check that each code block start address is also mentioned in the
line table.

dwarflint/Makefile.am
dwarflint/check_die_line_info.cc [new file with mode: 0644]
dwarflint/tests/run-DW_AT-later-version.sh

index d948a0d85d4e8a305663cce0b840bb34bd390710..2a964603c8a3ee0efbb77d0541f38d7749d903ef 100644 (file)
@@ -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 (file)
index 0000000..d304532
--- /dev/null
@@ -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
+   <http://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<dwarf> 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<check_die_line_info> reg;
+}
index b2f0265805a599069e252be799103f129cb4e8c1..3565dc88c03e126024d4df8921c6ae60498bc941 100755 (executable)
@@ -32,4 +32,5 @@ testfiles DW_AT-later-version
 testrun_compare ./dwarflint --nognu DW_AT-later-version <<EOF
 warning: .debug_abbrev: abbr. attribute 0x15: attribute DW_AT_endianity from later DWARF version.
 warning: .debug_info: DIE 0xb: DW_AT_low_pc value not below DW_AT_high_pc.
+warning: .debug_info: DIE 0x29: variable has decl_file, but NOT decl_line
 EOF