dwarflint_SOURCES = \
addr-record.cc addr-record.hh \
all-dies-it.hh \
+ check_registrar.cc check_registrar.hh check_registrar.ii \
checkdescriptor.cc checkdescriptor.hh checkdescriptor.ii \
checked_read.cc checked_read.hh \
checkrule.cc checkrule.hh \
- checks.cc checks.hh checks.ii \
+ checks.hh checks.ii \
coverage.cc coverage.hh \
cu_coverage.cc cu_coverage.hh cu_coverage.ii \
dwarf_2.cc dwarf_2.hh \
check_debug_line.cc check_debug_line.hh check_debug_line.ii \
check_debug_loc_range.cc check_debug_loc_range.hh check_debug_loc_range.ii \
check_debug_pub.cc check_debug_pub.hh \
+ check_die_tree.cc check_die_tree.hh check_die_tree.ii \
check_duplicate_DW_tag_variable.cc \
check_dups_abstract_origin.cc \
check_expected_trees.cc \
Network licensing program, please visit www.openinventionnetwork.com
<http://www.openinventionnetwork.com>. */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
#include <vector>
#include <stdexcept>
--- /dev/null
+/* Pedantic checking of DWARF files
+ 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 "messages.hh"
+#include "highlevel_check.hh"
+#include "check_die_tree.hh"
+
+using namespace elfutils;
+
+namespace
+{
+ reg<check_die_tree> reg;
+}
+
+class die_check_context
+ : protected std::vector<die_check *>
+{
+ typedef std::vector<die_check *> _super_t;
+
+public:
+ die_check_context (checkdescriptor const *cd, dwarflint &lint,
+ die_check_registrar const ®istrar)
+ {
+ // For per-DIE runs, we are only interested in limited context:
+ // the main iteration check, and the per-DIE check. This should
+ // be enough to decide whether to run the per-DIE check or not.
+ // We cannot use the original stack as a criterion, because the
+ // original check that tricked us into running is here, and the
+ // logic in should_check would then assume that we need to run
+ // everything.
+ checkstack stack;
+ stack.push_back (cd);
+
+ for (die_check_registrar::const_iterator it = registrar.begin ();
+ it != registrar.end (); ++it)
+ {
+ stack.push_back ((*it)->descriptor ());
+ popper p (stack);
+ if (lint.rules ().should_check (stack))
+ push_back ((*it)->create (stack, lint));
+ }
+ }
+
+ void
+ die (all_dies_iterator<dwarf> const &a_d_it)
+ {
+ for (iterator it = begin (); it != end (); ++it)
+ (*it)->die (a_d_it);
+ }
+
+ ~die_check_context ()
+ {
+ for (iterator it = begin (); it != end (); ++it)
+ delete *it;
+ }
+};
+
+check_die_tree::check_die_tree (checkstack &stack, dwarflint &lint)
+ : highlevel_check<check_die_tree> (stack, lint)
+{
+ //std::cout << "check_die_tree" << std::endl;
+ die_check_context ctx (descriptor (), lint, *dwarflint::die_registrar ());
+
+ for (all_dies_iterator<dwarf> it = all_dies_iterator<dwarf> (dw);
+ it != all_dies_iterator<dwarf> (); ++it)
+ ctx.die (it);
+}
--- /dev/null
+/* Pedantic checking of DWARF files
+ 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>. */
+
+#ifndef _CHECK_DIE_TREE_H_
+#define _CHECK_DIE_TREE_H_
+
+#include "all-dies-it.hh"
+#include "highlevel_check.hh"
+#include "check_die_tree.ii"
+
+#include <c++/dwarf>
+
+/// Top-level check that iterates over all DIEs in a file and
+/// dispatches per-DIE checks on each one. Per-DIE checks are written
+/// as subclasses of die_check (see below) and registered using
+/// reg_die_check (see further below).
+class check_die_tree
+ : public highlevel_check<check_die_tree>
+{
+public:
+ static checkdescriptor const *descriptor ()
+ {
+ static checkdescriptor cd
+ (checkdescriptor::create ("check_die_tree")
+ .inherit<highlevel_check<check_die_tree> > ()
+ .hidden ()
+ .description ("A pass over the DIE tree that dispatches to various per-DIE checks.\n"));
+ return &cd;
+ }
+
+ check_die_tree (checkstack &stack, dwarflint &lint);
+};
+
+class die_check
+{
+public:
+ virtual ~die_check () {}
+ virtual void die (all_dies_iterator<elfutils::dwarf> const &it) = 0;
+};
+
+template <class T>
+struct reg_die_check
+ : public die_check_item
+{
+ reg_die_check ()
+ {
+ dwarflint::die_registrar ()->push_back (this);
+ }
+
+ virtual die_check *create (checkstack &stack, dwarflint &lint)
+ {
+ return new T (stack, lint);
+ }
+
+ virtual checkdescriptor const *descriptor () const
+ {
+ return T::descriptor ();
+ }
+
+private:
+ /// The top-level scheduler needs to see per-DIE checks as real
+ /// checks, which they are not. So the per-DIE registrar creates
+ /// this check stub that's here only to trick the check_die_tree to
+ /// run. check_die_tree then does the per-DIE check scheduling
+ /// itself, down in die_check_context.
+ class check_stub
+ : public highlevel_check<check_stub>
+ {
+ check_die_tree *_m_die_tree_check;
+ public:
+ static checkdescriptor const *descriptor ()
+ {
+ static checkdescriptor cd
+ (checkdescriptor::create (*T::descriptor ())
+ .prereq<typeof (*_m_die_tree_check)> ()
+ .inherit<highlevel_check<check_stub> > ());
+ return &cd;
+ }
+
+ check_stub (checkstack &stack, dwarflint &lint)
+ : highlevel_check<check_stub> (stack, lint)
+ , _m_die_tree_check (lint.check (stack, _m_die_tree_check))
+ {}
+ };
+
+ ::reg<check_stub> _m_reg_stub;
+};
+
+#endif /* _CHECK_DIE_TREE_H_ */
--- /dev/null
+class check_die_tree;
--- /dev/null
+/* Pedantic checking of DWARF files
+ 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_registrar.hh"
+#include "checkdescriptor.hh"
+#include "dwarflint.hh"
+#include "main.hh"
+#include "wrap.hh"
+
+void
+check_registrar_aux::add_deps (std::set<checkdescriptor const *> &to,
+ checkdescriptor const *cd)
+{
+ for (std::set<checkdescriptor const *>::const_iterator it
+ = cd->prereq ().begin (); it != cd->prereq ().end (); ++it)
+ include (to, *it);
+}
+
+void
+check_registrar_aux::include (std::set<checkdescriptor const *> &to,
+ checkdescriptor const *cd)
+{
+ if (cd->hidden ())
+ add_deps (to, cd);
+ else
+ to.insert (cd);
+}
+
+bool
+check_registrar_aux::be_verbose ()
+{
+ // We can hopefully assume that the option doesn't change during
+ // execution, so we can simply cache it this was.
+ static bool be_verbose = opt_list_checks.value () == "full";
+ return be_verbose;
+}
+
+void
+check_registrar_aux::list_one_check (checkdescriptor const &cd)
+{
+ const size_t columns = 70;
+
+ if (be_verbose ())
+ std::cout << "=== " << cd.name () << " ===";
+ else
+ std::cout << cd.name ();
+
+ checkgroups const &groups = cd.groups ();
+ if (!groups.empty ())
+ {
+ if (be_verbose ())
+ std::cout << std::endl << "groups: ";
+ else
+ std::cout << ' ';
+ std::cout << groups;
+ }
+ std::cout << std::endl;
+
+ if (be_verbose ())
+ {
+ prereqs const &prereq = cd.prereq ();
+ if (!prereq.empty ())
+ std::cout << "prerequisites: " << prereq << std::endl;
+
+ char const *desc = cd.description ();
+ if (desc != NULL)
+ std::cout << wrap_str (desc, columns).join ();
+
+ options const &opts = cd.opts ();
+ if (!opts.empty ())
+ {
+ std::cout << "recognized options:" << std::endl;
+ argp a = opts.build_argp ();
+ argp_help (&a, stdout, ARGP_HELP_LONG, NULL);
+ }
+
+ std::cout << std::endl;
+ }
+}
-/*
- Copyright (C) 2010 Red Hat, Inc.
+/* Pedantic checking of DWARF files
+ 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
Network licensing program, please visit www.openinventionnetwork.com
<http://www.openinventionnetwork.com>. */
-#include "checks.hh"
-#include "option.hh"
+#ifndef _CHECK_REGISTRAR_H_
+#define _CHECK_REGISTRAR_H_
-static global_opt<void_option> show_progress
- ("Print out checks as they are performed, their context and result.",
- "show-progress");
+#include "dwarflint.ii"
+#include "checkdescriptor.ii"
-reporter::reporter (checkstack const &s, checkdescriptor const &a_cd)
- : stack (s)
- , cd (a_cd)
+#include <vector>
+#include <set>
+#include <iostream>
+
+namespace check_registrar_aux
{
- (*this) ("...", true);
+ bool be_verbose ();
+ void list_one_check (checkdescriptor const &cd);
+
+ void include (std::set<checkdescriptor const *> &to,
+ checkdescriptor const *cd);
+ void add_deps (std::set<checkdescriptor const *> &to,
+ checkdescriptor const *cd);
}
-void
-reporter::operator () (char const *what, bool ext)
+template <class Item>
+class check_registrar_T
+ : protected std::vector<Item *>
{
- if (!show_progress)
- return;
+ typedef std::vector<Item *> _super_t;
+public:
- if (false)
- for (size_t i = 0; i < stack.size (); ++i)
- std::cout << ' ';
+ using _super_t::push_back;
+ using _super_t::const_iterator;
+ using _super_t::begin;
+ using _super_t::end;
- std::cout << cd.name () << ' ' << what;
- if (ext)
- std::cout << ' ' << cd.groups () << ' ' << stack;
- std::cout << std::endl;
-}
+ typedef std::vector<checkdescriptor const *> checkdescriptors_t;
+
+ checkdescriptors_t
+ get_descriptors () const
+ {
+ std::set<checkdescriptor const *> descriptors;
+ for (typename _super_t::const_iterator it = begin (); it != end (); ++it)
+ check_registrar_aux::include (descriptors, (*it)->descriptor ());
+ return checkdescriptors_t (descriptors.begin (), descriptors.end ());
+ }
+};
+
+#endif /* _CHECK_REGISTRAR_H_ */
--- /dev/null
+//-*-c++-*-
+struct check_registrar;
/*
- Copyright (C) 2010 Red Hat, Inc.
+ Copyright (C) 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
, _m_hidden (false)
{}
+checkdescriptor::create::create (checkdescriptor const &base)
+ : _m_groups (base.groups ())
+ , _m_prereq (base.prereq ())
+ , _m_name (base.name ())
+ , _m_description (base.description ())
+ , _m_hidden (base.hidden ())
+ , _m_opts (base.opts ())
+{}
+
checkdescriptor::create &
checkdescriptor::create::groups (char const *a_groups)
{
/*
- Copyright (C) 2010 Red Hat, Inc.
+ Copyright (C) 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
public:
create (char const *name = NULL);
+ create (checkdescriptor const &base); ///< For construction of overrides.
create &groups (char const *name);
create &description (char const *d)
#include "dwarflint.hh"
#include "checkdescriptor.hh"
#include "messages.hh"
+#include "check_registrar.hh"
+
#include <string>
#include <cassert>
}
};
-struct reporter
+class popper
{
- checkstack const &stack;
- checkdescriptor const &cd;
-
- reporter (checkstack const &s, checkdescriptor const &a_cd);
- void operator () (char const *what, bool ext = false);
-};
+ checkstack &_m_guard_stack;
-template <class T>
-T *
-dwarflint::check (checkstack &stack)
-{
- void const *key = T::key ();
- T *c = static_cast <T *> (find_check (key));
+public:
+ popper (checkstack &guard_stack)
+ : _m_guard_stack (guard_stack)
+ {}
- if (c == NULL)
- {
- checkdescriptor const &cd = *T::descriptor ();
-
- struct popper {
- checkstack &guard_stack;
- popper (checkstack &a_guard_stack) : guard_stack (a_guard_stack) {}
- ~popper () { guard_stack.pop_back (); }
- };
-
- // Put a marker there indicating that we are trying to satisfy
- // that dependency.
- bool inserted
- = _m_checks.insert (std::make_pair (key, (T *)marker)).second;
- assert (inserted || !"duplicate key");
-
-#define FAIL \
- /* Put the anchor in the table. */ \
- _m_checks[key] = NULL; \
- report ("FAIL")
-
- reporter report (stack, cd);
- try
- {
- stack.push_back (&cd);
- popper p (stack);
-
- if (!_m_rules.should_check (stack))
- throw check_base::unscheduled ();
-
- // Now do the check.
- c = new T (stack, *this);
- }
- catch (check_base::unscheduled &e)
- {
- report ("skipped");
- _m_checks.erase (key);
- throw;
- }
- catch (check_base::failed &e)
- {
- // We can assume that the check emitted error message.
- FAIL;
- throw;
- }
- catch (std::exception &e)
- {
- wr_error () << "A check failed: " << (cd.name () ?: "(nil)") << ": "
- << e.what () << std::endl;
- FAIL;
- throw check_base::failed ();
- }
- catch (...)
- {
- wr_error () << "A check failed: " << (cd.name () ?: "(nil)") << "."
- << std::endl;
- FAIL;
- throw check_base::failed ();
- }
-
-#undef FAIL
-
- report ("done");
-
- // On success, put the actual check object there instead of the
- // marker.
- _m_checks[key] = c;
- }
- return c;
-}
+ ~popper ()
+ {
+ _m_guard_stack.pop_back ();
+ }
+};
template <class T>
inline T *
-dwarflint::toplev_check (checkstack &stack,
- __attribute__ ((unused)) T *tag)
+dwarflint::toplev_check (checkstack &stack, T *)
{
try
{
template <class T>
struct reg
- : public dwarflint::check_registrar::item
+ : public main_check_item
{
- reg ()
- {
- dwarflint::check_registrar::inst ()->add (this);
+ reg () {
+ dwarflint::main_registrar ()->push_back (this);
}
virtual void run (checkstack &stack, dwarflint &lint)
struct check_base;
+class die_check;
-/* Dwarflint check scheduler.
+/* Pedantic checking of DWARF files
Copyright (C) 2008,2009,2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
#include "dwarflint.hh"
#include "messages.hh"
#include "checks.hh"
-#include "main.hh"
-#include "wrap.hh"
+#include "check_registrar.hh"
#include <fcntl.h>
#include <cstring>
}
}
-dwarflint::dwarflint (char const *a_fname, checkrules const &rules)
+void
+main_check_registrar::run (dwarflint &lint)
+{
+ for (const_iterator it = begin (); it != end (); ++it)
+ {
+ checkstack stack;
+ (*it)->run (stack, lint);
+ }
+}
+
+dwarflint::dwarflint (char const *a_fname, checkrules const &a_rules)
: _m_fname (a_fname)
, _m_fd (get_fd (_m_fname))
- , _m_rules (rules)
+ , _m_rules (a_rules)
{
- check_registrar::inst ()->enroll (*this);
+ main_registrar ()->run (*this);
}
dwarflint::~dwarflint ()
delete it->second;
}
-void
-dwarflint::check_registrar::enroll (dwarflint &lint)
+void *const dwarflint::marker = (void *)-1;
+
+void *
+dwarflint::find_check (void const *key)
{
- for (std::vector <item *>::iterator it = _m_items.begin ();
- it != _m_items.end (); ++it)
+ check_map::const_iterator it = _m_checks.find (key);
+
+ if (it != _m_checks.end ())
{
- checkstack stack;
- (*it)->run (stack, lint);
+ void *c = it->second;
+
+ // We already tried to do the check, but failed.
+ if (c == NULL)
+ throw check_base::failed ();
+ else
+ // Recursive dependency!
+ assert (c != marker);
+
+ return c;
}
+
+ return NULL;
}
-namespace
+main_check_registrar *
+dwarflint::main_registrar ()
{
- template <class T> void include (T &to, checkdescriptor const *cd);
+ static main_check_registrar inst;
+ return &inst;
+}
- template <class T>
- void add_deps (T &to, checkdescriptor const *cd)
- {
- for (typename T::const_iterator it = cd->prereq ().begin ();
- it != cd->prereq ().end (); ++it)
- include (to, *it);
- }
+die_check_registrar *
+dwarflint::die_registrar ()
+{
+ static die_check_registrar inst;
+ return &inst;
+}
+namespace
+{
template <class T>
- void include (T &to, checkdescriptor const *cd)
+ void
+ list_part_checks (T const &descriptors)
{
- if (cd->hidden ())
- add_deps (to, cd);
- else
- to.insert (cd);
+ for (typename T::const_iterator it = descriptors.begin ();
+ it != descriptors.end (); ++it)
+ check_registrar_aux::list_one_check (**it);
}
}
-dwarflint::check_registrar::checkdescriptors_t
-dwarflint::check_registrar::get_descriptors () const
-{
- std::set<checkdescriptor const *> descriptors;
- for (std::vector <item *>::const_iterator it = _m_items.begin ();
- it != _m_items.end (); ++it)
- include (descriptors, (*it)->descriptor ());
- return checkdescriptors_t (descriptors.begin (), descriptors.end ());
-}
-
void
-dwarflint::check_registrar::list_checks () const
+dwarflint::list_checks ()
{
- bool be_verbose = opt_list_checks.value () == "full";
- checkdescriptors_t descriptors = get_descriptors ();
- const size_t columns = 70;
+ list_part_checks (dwarflint::main_registrar ()->get_descriptors ());
- for (checkdescriptors_t::const_iterator it = descriptors.begin ();
- it != descriptors.end (); ++it)
- {
- checkdescriptor const &cd = **it;
- if (be_verbose)
- std::cout << "=== " << cd.name () << " ===";
- else
- std::cout << cd.name ();
-
- checkgroups const &groups = cd.groups ();
- if (!groups.empty ())
- {
- if (be_verbose)
- std::cout << std::endl << "groups: ";
- else
- std::cout << ' ';
- std::cout << groups;
- }
- std::cout << std::endl;
-
- if (be_verbose)
- {
- prereqs const &prereq = cd.prereq ();
- if (!prereq.empty ())
- std::cout << "prerequisites: " << prereq << std::endl;
-
- char const *desc = cd.description ();
- if (desc != NULL)
- std::cout << wrap_str (desc, columns).join ();
-
- options const &opts = cd.opts ();
- if (!opts.empty ())
- {
- std::cout << "recognized options:" << std::endl;
- argp a = opts.build_argp ();
- argp_help (&a, stdout, ARGP_HELP_LONG, NULL);
- }
-
- std::cout << std::endl;
- }
- }
- if (!be_verbose)
+ if (!check_registrar_aux::be_verbose ())
std::cout
<< "Use --list-checks=full to get more detailed description."
<< std::endl;
}
-void *const dwarflint::marker = (void *)-1;
+static global_opt<void_option> show_progress
+ ("Print out checks as they are performed, their context and result.",
+ "show-progress");
+
+namespace
+{
+ struct reporter
+ {
+ checkstack const &stack;
+ checkdescriptor const &cd;
+
+ reporter (checkstack const &s, checkdescriptor const &a_cd);
+ void operator () (char const *what, bool ext = false);
+ };
+
+ reporter::reporter (checkstack const &s, checkdescriptor const &a_cd)
+ : stack (s)
+ , cd (a_cd)
+ {
+ (*this) ("...", true);
+ }
+
+ void
+ reporter::operator () (char const *what, bool ext)
+ {
+ if (!show_progress)
+ return;
+
+ if (false)
+ for (size_t i = 0; i < stack.size (); ++i)
+ std::cout << ' ';
+
+ std::cout << cd.name () << ' ' << what;
+ if (ext)
+ std::cout << ' ' << cd.groups () << ' ' << stack;
+ std::cout << std::endl;
+ }
+}
void *
-dwarflint::find_check (void const *key)
+dwarflint::dispatch_check (checkstack &stack,
+ checkdescriptor const &cd,
+ void const *key,
+ check_base *(* create) (checkstack &, dwarflint &))
{
- check_map::const_iterator it = _m_checks.find (key);
+ // Put a marker there indicating that we are trying to satisfy
+ // that dependency.
+ bool inserted
+ = _m_checks.insert (std::make_pair (key, (check_base *)marker)).second;
+ assert (inserted || !"duplicate key");
- if (it != _m_checks.end ())
+#define FAIL \
+ /* Put the anchor in the table. */ \
+ _m_checks[key] = NULL; \
+ report ("FAIL")
+
+ reporter report (stack, cd);
+ try
{
- void *c = it->second;
+ stack.push_back (&cd);
+ popper p (stack);
- // We already tried to do the check, but failed.
- if (c == NULL)
- throw check_base::failed ();
- else
- // Recursive dependency!
- assert (c != marker);
+ if (!_m_rules.should_check (stack))
+ throw check_base::unscheduled ();
+ // Now do the check.
+ check_base *c = create (stack, *this);
+
+ // On success, put the actual check object there instead of the
+ // marker.
+ _m_checks[key] = c;
+ report ("done");
return c;
}
+ catch (check_base::unscheduled &e)
+ {
+ report ("skipped");
+ _m_checks.erase (key);
+ throw;
+ }
+ catch (check_base::failed &e)
+ {
+ // We can assume that the check emitted error message.
+ FAIL;
+ throw;
+ }
+ catch (std::exception &e)
+ {
+ wr_error () << "A check failed: " << (cd.name () ?: "(nil)") << ": "
+ << e.what () << std::endl;
+ FAIL;
+ throw check_base::failed ();
+ }
+ catch (...)
+ {
+ wr_error () << "A check failed: " << (cd.name () ?: "(nil)") << "."
+ << std::endl;
+ FAIL;
+ throw check_base::failed ();
+ }
- return NULL;
+#undef FAIL
}
/* 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
#include "checks.ii"
#include "checkdescriptor.ii"
#include "checkrule.hh"
+#include "check_registrar.hh"
+#include "dwarflint.ii"
+
+// Classes for full-blown check passes.
+struct main_check_item
+{
+ virtual checkdescriptor const *descriptor () const = 0;
+ virtual ~main_check_item () {}
+ virtual void run (checkstack &stack, dwarflint &lint) = 0;
+};
+
+class main_check_registrar
+ : public check_registrar_T<main_check_item>
+{
+public:
+ friend class dwarflint;
+ void run (dwarflint &lint);
+};
+
+// Classes for simplified single-die passes.
+struct die_check_item
+{
+ virtual checkdescriptor const *descriptor () const = 0;
+ virtual ~die_check_item () {}
+ virtual die_check *create (checkstack &stack, dwarflint &lint) = 0;
+};
+
+class die_check_registrar
+ : public check_registrar_T<die_check_item>
+{
+public:
+ friend class dwarflint;
+ void run (checkstack &stack, dwarflint &lint);
+};
+
class checkstack
: public std::vector <checkdescriptor const *>
{};
std::ostream &operator << (std::ostream &o, checkstack const &stack);
+
class dwarflint
{
typedef std::map <void const *, class check_base *> check_map;
// was detected.
void *find_check (void const *key);
-public:
- struct check_registrar
+ template <class T>
+ static check_base *
+ create_check_object (checkstack &stack, dwarflint &lint)
{
- struct item
- {
- virtual void run (checkstack &stack, dwarflint &lint) = 0;
- virtual checkdescriptor const *descriptor () const = 0;
- };
-
- static check_registrar *inst ()
- {
- static check_registrar inst;
- return &inst;
- }
-
- void add (item *i)
- {
- _m_items.push_back (i);
- }
-
- void list_checks () const;
-
- typedef std::vector<checkdescriptor const *> checkdescriptors_t;
- checkdescriptors_t get_descriptors () const;
-
- private:
- friend class dwarflint;
- void enroll (dwarflint &lint);
+ return new T (stack, lint);
+ }
- std::vector <item *> _m_items;
- };
+ void *dispatch_check (checkstack &stack,
+ checkdescriptor const &cd,
+ void const *key,
+ check_base *(* create) (checkstack &, dwarflint &));
+public:
dwarflint (char const *fname, checkrules const &rules);
~dwarflint ();
int fd () { return _m_fd; }
char const *fname () { return _m_fname; }
- template <class T> T *check (checkstack &stack);
+ template <class T>
+ T *
+ check (checkstack &stack)
+ {
+ void const *key = T::key ();
+ T *c = static_cast <T *> (find_check (key));
+ checkdescriptor const &cd = *T::descriptor ();
+
+ if (c == NULL)
+ c = (T *)dispatch_check (stack, cd, key, &create_check_object<T>);
+
+ return c;
+ }
template <class T>
T *
- check (checkstack &stack,
- __attribute__ ((unused)) T *fake)
+ check (checkstack &stack, T *)
{
return check<T> (stack);
}
template <class T>
- T *toplev_check (checkstack &stack,
- __attribute__ ((unused)) T *fake = NULL);
+ T *toplev_check (checkstack &stack, T *fake = NULL);
template <class T>
T *
else
return NULL;
}
+
+ checkrules const &
+ rules () const
+ {
+ return _m_rules;
+ }
+
+ static main_check_registrar *main_registrar ();
+ static die_check_registrar *die_registrar ();
+
+ static void list_checks ();
};
#endif//DWARFLINT_HH
class checkstack;
class dwarflint;
+class main_check_registrar;
/* 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
Dwfl *const _m_dwfl;
public:
static checkdescriptor const *descriptor () {
- static checkdescriptor cd ("open_highlevel_dwarf");
+ static checkdescriptor cd
+ (checkdescriptor::create ("open_highlevel_dwarf")
+ .hidden ());
return &cd;
}
if (opt_list_checks.seen ())
{
- dwarflint::check_registrar::inst ()->list_checks ();
+ dwarflint::list_checks ();
std::exit (0);
}
else if (remaining == argc)
try
{
char const *fname = argv[remaining];
- /* Create an `Elf' descriptor. */
unsigned int prev_error_count = error_count;
if (!only_one)
std::cout << std::endl << fname << ":" << std::endl;
/* 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
#include "option.hh"
#include "dwarflint.hh"
#include "checkdescriptor.hh"
+#include "check_registrar.hh"
#include <cassert>
#include <cstring>
#include <iostream>
argppp::inst ()
{
static argppp my
- (global_opts,
- dwarflint::check_registrar::inst ()->get_descriptors ());
+ (global_opts, dwarflint::main_registrar ()->get_descriptors ());
return my;
}
{
argp main = global.build_argp (true);
- typedef dwarflint::check_registrar::checkdescriptors_t checkdescriptors_t;
+ typedef main_check_registrar::checkdescriptors_t checkdescriptors_t;
for (checkdescriptors_t::const_iterator it = checkdescriptors.begin ();
it != checkdescriptors.end (); ++it)
if (!(*it)->opts ().empty ())