From: Petr Machata Date: Tue, 7 Sep 2010 21:08:05 +0000 (+0200) Subject: dwarflint: Add a lowlevel_checks pass X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a5411525fce00015f6911094b1013f50b16426ae;p=thirdparty%2Felfutils.git dwarflint: Add a lowlevel_checks pass - which is where low-level checks are explicitly requested - and what highlevel checks, also explicitly, depend on --- diff --git a/dwarflint/Makefile.am b/dwarflint/Makefile.am index c8cb062dc..1f6c84e20 100644 --- a/dwarflint/Makefile.am +++ b/dwarflint/Makefile.am @@ -64,6 +64,7 @@ dwarflint_SOURCES = \ check_debug_pub.cc check_debug_pub.hh \ check_debug_loc_range.cc check_debug_loc_range.hh check_debug_loc_range.ii \ check_debug_aranges.cc check_debug_aranges.hh \ + lowlevel_checks.cc lowlevel_checks.hh \ check_matching_ranges.cc \ check_range_out_of_scope.cc \ check_expected_trees.cc \ diff --git a/dwarflint/TODO b/dwarflint/TODO index 2a2060a10..0f374ca24 100644 --- a/dwarflint/TODO +++ b/dwarflint/TODO @@ -1,14 +1,4 @@ -*-org-*- -* resolver -** ordering - High-level checks implicitly depend on low-level checks of the - sections that they use, but since there is no explicit need to - access any of the low-level variables, these dependencies are not - visible in the source. So right now high-level checks will happily - run even when no low-level checks passed, and can ever run before - any of the low-level checks, since the dependency resolver has no - idea that there is a dependency in the first place. - * DWARF 4 support This TODO item is actually to go through the DWARF 4 standard and add TODO items for individual tasks. @@ -18,6 +8,13 @@ can be either constant or *ptr in DWARF<=3 but only sec_offset is *ptr in DWARF>=4. +* low-level checks +** error out on incomplete debuginfo + Right now, without --strict, running dwarflint on a binary compiled + without debuginfo gives no errors. On the other hand, with + --strict, dwarflint errors out on any debug section that's not + there, which is also wrong. Fix it. + * high-level checks ** DW_OP_GNU_implicit_pointer diff --git a/dwarflint/check_debug_abbrev.cc b/dwarflint/check_debug_abbrev.cc index 8ee63dfb5..ad4c28432 100644 --- a/dwarflint/check_debug_abbrev.cc +++ b/dwarflint/check_debug_abbrev.cc @@ -38,9 +38,7 @@ #include #include -static reg reg_debug_abbrev; - -checkdescriptor & +checkdescriptor const * check_debug_abbrev::descriptor () { static checkdescriptor cd @@ -73,7 +71,7 @@ check_debug_abbrev::descriptor () "many checks will still be done, operating under assumption that what\n" "we see is the latest DWARF format. This may render some checks\n" "inaccurate.\n")); - return cd; + return &cd; } struct abbrev * diff --git a/dwarflint/check_debug_abbrev.hh b/dwarflint/check_debug_abbrev.hh index f1aef31ea..11cd1dec8 100644 --- a/dwarflint/check_debug_abbrev.hh +++ b/dwarflint/check_debug_abbrev.hh @@ -38,7 +38,7 @@ class check_debug_abbrev read_cu_headers *_m_cu_headers; public: - static checkdescriptor &descriptor (); + static checkdescriptor const *descriptor (); // offset -> abbreviations typedef std::map< ::Dwarf_Off, abbrev_table> abbrev_map; diff --git a/dwarflint/check_debug_aranges.cc b/dwarflint/check_debug_aranges.cc index 4d87b4022..9918030f8 100644 --- a/dwarflint/check_debug_aranges.cc +++ b/dwarflint/check_debug_aranges.cc @@ -34,9 +34,7 @@ #include "check_debug_loc_range.hh" #include "cu_coverage.hh" -static reg reg_debug_aranges; - -checkdescriptor +checkdescriptor const * check_debug_aranges::descriptor () { static checkdescriptor cd @@ -55,7 +53,7 @@ check_debug_aranges::descriptor () " - for zero-length ranges\n" " - that the ranges cover all the address range covered by CUs\n" )); - return cd; + return &cd; } check_debug_aranges::check_debug_aranges (checkstack &stack, dwarflint &lint) diff --git a/dwarflint/check_debug_aranges.hh b/dwarflint/check_debug_aranges.hh index 993a221ad..dbd0726eb 100644 --- a/dwarflint/check_debug_aranges.hh +++ b/dwarflint/check_debug_aranges.hh @@ -40,7 +40,7 @@ class check_debug_aranges cu_coverage *_m_cu_coverage; public: - static checkdescriptor descriptor (); + static checkdescriptor const *descriptor (); check_debug_aranges (checkstack &stack, dwarflint &lint); }; diff --git a/dwarflint/check_debug_info.cc b/dwarflint/check_debug_info.cc index 631083e0b..8e8a36f0d 100644 --- a/dwarflint/check_debug_info.cc +++ b/dwarflint/check_debug_info.cc @@ -41,25 +41,22 @@ #include "check_debug_info.hh" #include "check_debug_line.hh" -checkdescriptor const & +checkdescriptor const * read_cu_headers::descriptor () { static checkdescriptor cd (checkdescriptor::create ("read_cu_headers") .prereq ()); - return cd; + return &cd; } -static reg reg_debug_info; - -checkdescriptor const & +checkdescriptor const * check_debug_info::descriptor () { static checkdescriptor cd (checkdescriptor::create ("check_debug_info") .groups ("@low") .prereq () - .prereq () .prereq () .prereq () .prereq () @@ -93,7 +90,7 @@ check_debug_info::descriptor () " - that relocations are valid. In ET_REL files that certain fields\n" " are relocated\n" )); - return cd; + return &cd; } namespace @@ -1223,7 +1220,6 @@ check_debug_info::check_info_structural () check_debug_info::check_debug_info (checkstack &stack, dwarflint &lint) : _m_sec_info (lint.check (stack, _m_sec_info)) - , _m_sec_abbrev (lint.check (stack, _m_sec_abbrev)) , _m_sec_str (lint.check (stack, _m_sec_str)) , _m_file (_m_sec_info->file) , _m_abbrevs (lint.check (stack, _m_abbrevs)) @@ -1274,7 +1270,7 @@ check_debug_info::find_cu (::Dwarf_Off offset) return NULL; } -checkdescriptor const & +checkdescriptor const * check_debug_info_refs::descriptor () { static checkdescriptor cd @@ -1286,7 +1282,7 @@ check_debug_info_refs::descriptor () "This pass checks for outstanding unresolved references from\n" ".debug_info to .debug_line (and perhaps others as they are\n" "identified).\n")); - return cd; + return &cd; } check_debug_info_refs::check_debug_info_refs (checkstack &stack, @@ -1303,4 +1299,3 @@ check_debug_info_refs::check_debug_info_refs (checkstack &stack, << "unresolved reference to .debug_line table " << pri::hex (it->stmt_list.addr) << '.' << std::endl; } -static reg reg_debug_info_refs; diff --git a/dwarflint/check_debug_info.hh b/dwarflint/check_debug_info.hh index 81827126f..df80baa0c 100644 --- a/dwarflint/check_debug_info.hh +++ b/dwarflint/check_debug_info.hh @@ -40,7 +40,7 @@ class read_cu_headers section *_m_sec_info; public: - static checkdescriptor const &descriptor (); + static checkdescriptor const *descriptor (); std::vector const cu_headers; read_cu_headers (checkstack &stack, dwarflint &lint); }; @@ -50,7 +50,6 @@ class check_debug_info : public check { section *_m_sec_info; - section *_m_sec_abbrev; section *_m_sec_str; elf_file const &_m_file; check_debug_abbrev *_m_abbrevs; @@ -78,7 +77,7 @@ class check_debug_info void check_info_structural (); public: - static checkdescriptor const &descriptor (); + static checkdescriptor const *descriptor (); coverage const &cov () const { return _m_cov; } bool need_ranges () const { return _m_need_ranges; } @@ -101,7 +100,7 @@ class check_debug_info_refs check_debug_line *_m_line; public: - static checkdescriptor const &descriptor (); + static checkdescriptor const *descriptor (); check_debug_info_refs (checkstack &stack, dwarflint &lint); }; diff --git a/dwarflint/check_debug_line.cc b/dwarflint/check_debug_line.cc index 7445fe74d..a383e953f 100644 --- a/dwarflint/check_debug_line.cc +++ b/dwarflint/check_debug_line.cc @@ -34,7 +34,7 @@ #include -checkdescriptor const & +checkdescriptor const * check_debug_line::descriptor () { static checkdescriptor cd @@ -68,9 +68,8 @@ check_debug_line::descriptor () " should be consistent in that case, namely is_stmt, basic_block,\n" " end_sequence, prologue_end, epilogue_begin, isa.\n" )); - return cd; + return &cd; } -static reg reg_debug_line; namespace { diff --git a/dwarflint/check_debug_line.hh b/dwarflint/check_debug_line.hh index fc7aa4dfd..a70982d17 100644 --- a/dwarflint/check_debug_line.hh +++ b/dwarflint/check_debug_line.hh @@ -40,7 +40,7 @@ class check_debug_line std::set _m_line_tables; public: - static checkdescriptor const &descriptor (); + static checkdescriptor const *descriptor (); check_debug_line (checkstack &stack, dwarflint &lint); std::set const &line_tables () const { return _m_line_tables; } diff --git a/dwarflint/check_debug_loc_range.cc b/dwarflint/check_debug_loc_range.cc index e1b397183..d664122e6 100644 --- a/dwarflint/check_debug_loc_range.cc +++ b/dwarflint/check_debug_loc_range.cc @@ -45,9 +45,7 @@ #include "../src/dwarf-opcodes.h" #include "pri.hh" -static reg reg_debug_ranges; - -checkdescriptor const & +checkdescriptor const * check_debug_ranges::descriptor () { static checkdescriptor cd @@ -67,12 +65,10 @@ check_debug_ranges::descriptor () " - neither or both of range start and range end are expected to be\n" " relocated. It's expected that they are both relocated against the\n" " same section.\n")); - return cd; + return &cd; } -static reg reg_debug_loc; - -checkdescriptor const & +checkdescriptor const * check_debug_loc::descriptor () { static checkdescriptor cd @@ -92,7 +88,7 @@ check_debug_loc::descriptor () " - on 32-bit machines it rejects DW_OP_const8u and DW_OP_const8s\n" " - on 32-bit machines it checks that ULEB128-encoded arguments aren't\n" " quantities that don't fit into 32 bits\n")); - return cd; + return &cd; } namespace diff --git a/dwarflint/check_debug_loc_range.hh b/dwarflint/check_debug_loc_range.hh index c3737e1ce..2f8138f97 100644 --- a/dwarflint/check_debug_loc_range.hh +++ b/dwarflint/check_debug_loc_range.hh @@ -38,7 +38,7 @@ class check_debug_ranges coverage _m_cov; public: - static checkdescriptor const &descriptor (); + static checkdescriptor const *descriptor (); coverage const &cov () const { return _m_cov; } check_debug_ranges (checkstack &stack, dwarflint &lint); @@ -52,7 +52,7 @@ class check_debug_loc check_debug_info *_m_info; public: - static checkdescriptor const &descriptor (); + static checkdescriptor const *descriptor (); check_debug_loc (checkstack &stack, dwarflint &lint); }; diff --git a/dwarflint/check_debug_pub.cc b/dwarflint/check_debug_pub.cc index 82eab1d27..0ce3ff60e 100644 --- a/dwarflint/check_debug_pub.cc +++ b/dwarflint/check_debug_pub.cc @@ -47,7 +47,7 @@ check_debug_pub::check_debug_pub (checkstack &stack, dwarflint &lint) } -checkdescriptor const & +checkdescriptor const * check_debug_pubnames::descriptor () { static checkdescriptor cd @@ -64,13 +64,12 @@ check_debug_pubnames::descriptor () "Furthermore, if .debug_info is valid, it is checked:\n" " - that references point to actual CUs and DIEs\n" " - that there's only one pub section per CU\n")); - return cd; + return &cd; } -static reg reg_debug_pubnames; template check_debug_pub::check_debug_pub (checkstack &stack, dwarflint &lint); -checkdescriptor const & +checkdescriptor const * check_debug_pubtypes::descriptor () { static checkdescriptor cd @@ -81,9 +80,8 @@ check_debug_pubtypes::descriptor () .description ( "Checks for low-level structure of .debug_pubtypes. In addition it\n" "makes the same checks as check_debug_pubnames.\n")); - return cd; + return &cd; } -static reg reg_debug_pubtypes; template check_debug_pub::check_debug_pub (checkstack &stack, dwarflint &lint); diff --git a/dwarflint/check_debug_pub.hh b/dwarflint/check_debug_pub.hh index 1f3e35cfd..97415f8c8 100644 --- a/dwarflint/check_debug_pub.hh +++ b/dwarflint/check_debug_pub.hh @@ -51,7 +51,7 @@ public: struct check_debug_pubnames : public check_debug_pub { - static checkdescriptor const &descriptor (); + static checkdescriptor const *descriptor (); check_debug_pubnames (checkstack &stack, dwarflint &lint) : check_debug_pub (stack, lint) @@ -61,7 +61,7 @@ struct check_debug_pubnames struct check_debug_pubtypes : public check_debug_pub { - static checkdescriptor const &descriptor (); + static checkdescriptor const *descriptor (); check_debug_pubtypes (checkstack &stack, dwarflint &lint) : check_debug_pub (stack, lint) diff --git a/dwarflint/check_duplicate_DW_tag_variable.cc b/dwarflint/check_duplicate_DW_tag_variable.cc index c8a937bd2..67f6a2942 100644 --- a/dwarflint/check_duplicate_DW_tag_variable.cc +++ b/dwarflint/check_duplicate_DW_tag_variable.cc @@ -57,7 +57,7 @@ namespace }; public: - static checkdescriptor descriptor () { + static checkdescriptor const *descriptor () { static checkdescriptor cd (checkdescriptor::create ("check_duplicate_DW_tag_variable") .inherit > () @@ -67,7 +67,7 @@ namespace "definition and declaration with definition.\n" " https://fedorahosted.org/pipermail/elfutils-devel/2010-July/001497.html\n" " http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39524\n")); - return cd; + return &cd; } check_duplicate_DW_tag_variable (checkstack &stack, dwarflint &lint); diff --git a/dwarflint/check_dups_abstract_origin.cc b/dwarflint/check_dups_abstract_origin.cc index 27745bf9b..a45cd6606 100644 --- a/dwarflint/check_dups_abstract_origin.cc +++ b/dwarflint/check_dups_abstract_origin.cc @@ -42,7 +42,8 @@ namespace : public highlevel_check { public: - static checkdescriptor descriptor () { + static checkdescriptor const *descriptor () + { static checkdescriptor cd (checkdescriptor::create ("check_dups_abstract_origin") .inherit > () @@ -51,7 +52,7 @@ namespace "suspicious if that attribute name appears on the DIE that's the\n" "first DIE's DW_AT_abstract_origin or DW_AT_specification.\n" " https://bugzilla.redhat.com/show_bug.cgi?id=527430\n")); - return cd; + return &cd; } explicit check_dups_abstract_origin (checkstack &stack, dwarflint &lint) diff --git a/dwarflint/check_expected_trees.cc b/dwarflint/check_expected_trees.cc index 0482919b2..c90a488dc 100644 --- a/dwarflint/check_expected_trees.cc +++ b/dwarflint/check_expected_trees.cc @@ -42,14 +42,14 @@ namespace : public highlevel_check { public: - static checkdescriptor descriptor () { + static checkdescriptor const *descriptor () { static checkdescriptor cd (checkdescriptor::create ("check_expected_trees") .inherit > () .description ( "Checks whether all DIEs have the right attributes and the right children.\n" "Currently this is very much a work in progress.\n")); - return cd; + return &cd; } check_expected_trees (checkstack &stack, dwarflint &lint); diff --git a/dwarflint/check_matching_ranges.cc b/dwarflint/check_matching_ranges.cc index 2361618db..0afdc0788 100644 --- a/dwarflint/check_matching_ranges.cc +++ b/dwarflint/check_matching_ranges.cc @@ -39,14 +39,14 @@ namespace : public highlevel_check { public: - static checkdescriptor descriptor () { + static checkdescriptor const *descriptor () { static checkdescriptor cd (checkdescriptor::create ("check_matching_ranges") .inherit > () .description ( "Check that the ranges in .debug_aranges and .debug_ranges match.\n" )); - return cd; + return &cd; } check_matching_ranges (checkstack &stack, dwarflint &lint); diff --git a/dwarflint/check_range_out_of_scope.cc b/dwarflint/check_range_out_of_scope.cc index 779fba88a..c930aa210 100644 --- a/dwarflint/check_range_out_of_scope.cc +++ b/dwarflint/check_range_out_of_scope.cc @@ -48,13 +48,13 @@ namespace where const &wh_parent); public: - static checkdescriptor descriptor () { + static checkdescriptor const *descriptor () { static checkdescriptor cd (checkdescriptor::create ("check_range_out_of_scope") .inherit > () .description ( "Check whether PC ranges reported at DIEs fall into the containing scope.\n")); - return cd; + return &cd; } check_range_out_of_scope (checkstack &stack, dwarflint &lint); diff --git a/dwarflint/checkdescriptor.cc b/dwarflint/checkdescriptor.cc index c0a4e364d..3ab7a14f4 100644 --- a/dwarflint/checkdescriptor.cc +++ b/dwarflint/checkdescriptor.cc @@ -42,9 +42,24 @@ operator << (std::ostream &o, checkgroups const &groups) return o; } -checkdescriptor::create::create (char const *a_name) - : name (a_name) - , desc (NULL) +std::ostream & +operator << (std::ostream &o, prereqs const &p) +{ + o << "("; + for (prereqs::const_iterator it = p.begin (); it != p.end (); ++it) + { + if (it != p.begin ()) + o << ','; + o << (*it)->name (); + } + o << ")"; + return o; +} + +checkdescriptor::create::create (char const *name) + : _m_name (name) + , _m_description (NULL) + , _m_hidden (false) {} checkdescriptor::create & @@ -53,15 +68,16 @@ checkdescriptor::create::groups (char const *a_groups) std::stringstream ss (a_groups); std::string group; while (ss >> group) - g.insert (group); + _m_groups.insert (group); return *this; } checkdescriptor::checkdescriptor (create const &c) - : _m_name (c.name) - , _m_description (c.desc) - , _m_groups (c.g) - , _m_prereq (c.p) + : _m_name (c._m_name) + , _m_description (c._m_description) + , _m_groups (c._m_groups) + , _m_prereq (c._m_prereq) + , _m_hidden (c._m_hidden) {} bool diff --git a/dwarflint/checkdescriptor.hh b/dwarflint/checkdescriptor.hh index 5e7d32450..f5131b2a1 100644 --- a/dwarflint/checkdescriptor.hh +++ b/dwarflint/checkdescriptor.hh @@ -35,46 +35,69 @@ struct checkgroups {}; std::ostream &operator << (std::ostream &o, checkgroups const &groups); +struct checkdescriptor; + +struct prereqs + : public std::set +{}; +std::ostream &operator << (std::ostream &o, prereqs const &p); + struct checkdescriptor { - struct create + class create { - checkgroups g; - checkgroups p; - char const *const name; - char const *desc; + friend class checkdescriptor; + checkgroups _m_groups; + prereqs _m_prereq; + char const *const _m_name; + char const *_m_description; + bool _m_hidden; + + public: create (char const *name = NULL); create &groups (char const *name); create &description (char const *d) - { desc = d; return *this; } + { + _m_description = d; + return *this; + } template create &prereq (); template create &inherit (); + + create hidden () + { + _m_hidden = true; + return *this; + } }; checkdescriptor (create const &c); char const *name () const { return _m_name; } char const *description () const { return _m_description; } - checkgroups const &prereq () const { return _m_prereq; } + prereqs const &prereq () const { return _m_prereq; } checkgroups const &groups () const { return _m_groups; } bool in_group (std::string const &group) const; + bool hidden () const { return _m_hidden; } + private: char const *const _m_name; char const *const _m_description; checkgroups const _m_groups; - checkgroups const _m_prereq; + prereqs const _m_prereq; + bool _m_hidden; }; template checkdescriptor::create & checkdescriptor::create::prereq () { - p.insert (T::descriptor ().name ()); + _m_prereq.insert (T::descriptor ()); return *this; } @@ -82,10 +105,10 @@ template checkdescriptor::create & checkdescriptor::create::inherit () { - checkdescriptor const &cd = T::descriptor (); - for (checkgroups::const_iterator it = cd.prereq ().begin (); + checkdescriptor const &cd = *T::descriptor (); + for (prereqs::const_iterator it = cd.prereq ().begin (); it != cd.prereq ().end (); ++it) - p.insert (*it); + _m_prereq.insert (*it); return *this; } diff --git a/dwarflint/checks.hh b/dwarflint/checks.hh index c819b46f0..cba9271dd 100644 --- a/dwarflint/checks.hh +++ b/dwarflint/checks.hh @@ -70,7 +70,7 @@ dwarflint::check (checkstack &stack) if (c == NULL) { - checkdescriptor const &cd = T::descriptor (); + checkdescriptor const &cd = *T::descriptor (); struct popper { checkstack &guard_stack; @@ -148,7 +148,7 @@ struct reg lint.toplev_check (stack); } - virtual checkdescriptor descriptor () const + virtual checkdescriptor const *descriptor () const { return T::descriptor (); } diff --git a/dwarflint/cu_coverage.cc b/dwarflint/cu_coverage.cc index 8fabcda81..7fb0d3d61 100644 --- a/dwarflint/cu_coverage.cc +++ b/dwarflint/cu_coverage.cc @@ -27,14 +27,14 @@ #include "check_debug_info.hh" #include "check_debug_loc_range.hh" -checkdescriptor const & +checkdescriptor const * cu_coverage::descriptor () { static checkdescriptor cd (checkdescriptor::create ("cu_coverage") .prereq () .prereq ()); - return cd; + return &cd; } cu_coverage::cu_coverage (checkstack &stack, dwarflint &lint) diff --git a/dwarflint/cu_coverage.hh b/dwarflint/cu_coverage.hh index 00767e922..273eb3362 100644 --- a/dwarflint/cu_coverage.hh +++ b/dwarflint/cu_coverage.hh @@ -39,7 +39,7 @@ class cu_coverage check_debug_ranges *_m_ranges; public: - static checkdescriptor const &descriptor (); + static checkdescriptor const *descriptor (); coverage cov; diff --git a/dwarflint/dwarflint.cc b/dwarflint/dwarflint.cc index cc11924e7..f2116a823 100644 --- a/dwarflint/dwarflint.cc +++ b/dwarflint/dwarflint.cc @@ -97,13 +97,41 @@ dwarflint::check_registrar::enroll (dwarflint &lint) } } +namespace +{ + template void include (T &to, checkdescriptor const *cd); + + template + 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); + } + + template + void include (T &to, checkdescriptor const *cd) + { + if (cd->hidden ()) + add_deps (to, cd); + else + to.insert (cd); + } +} + void dwarflint::check_registrar::list_checks () const { + typedef std::set descset; + descset descriptors; for (std::vector ::const_iterator it = _m_items.begin (); it != _m_items.end (); ++it) + include (descriptors, (*it)->descriptor ()); + + for (descset::const_iterator it = descriptors.begin (); + it != descriptors.end (); ++it) { - checkdescriptor const &cd = (*it)->descriptor (); + checkdescriptor const &cd = **it; if (be_verbose) std::cout << "=== " << cd.name () << " ==="; else @@ -122,7 +150,7 @@ dwarflint::check_registrar::list_checks () const if (be_verbose) { - checkgroups const &prereq = cd.prereq (); + prereqs const &prereq = cd.prereq (); if (!prereq.empty ()) std::cout << "prerequisites: " << prereq << std::endl; char const *desc = cd.description (); diff --git a/dwarflint/dwarflint.hh b/dwarflint/dwarflint.hh index 518c33bf0..69baff91c 100644 --- a/dwarflint/dwarflint.hh +++ b/dwarflint/dwarflint.hh @@ -86,7 +86,7 @@ public: struct item { virtual void run (checkstack &stack, dwarflint &lint) = 0; - virtual checkdescriptor descriptor () const = 0; + virtual checkdescriptor const *descriptor () const = 0; }; static check_registrar *inst () diff --git a/dwarflint/highlevel_check.cc b/dwarflint/highlevel_check.cc index ea8ce05d6..8e1db6d46 100644 --- a/dwarflint/highlevel_check.cc +++ b/dwarflint/highlevel_check.cc @@ -26,6 +26,9 @@ #include "highlevel_check.hh" #include "messages.h" +#include "sections.hh" +#include "lowlevel_checks.hh" + namespace { inline bool failed (void *ptr) { return ptr == NULL; } @@ -128,10 +131,9 @@ namespace } } -open_highlevel_dwarf::open_highlevel_dwarf (checkstack &stack - __attribute__ ((unused)), - dwarflint &lint) - : _m_dwfl (open_dwfl ()) +open_highlevel_dwarf::open_highlevel_dwarf (checkstack &stack, dwarflint &lint) + : _m_dwfl ((lint.check (stack), + open_dwfl ())) , _m_dw (open_dwarf (_m_dwfl, lint.fname (), lint.fd ())) , dw (open_hl_dwarf (_m_dw)) {} diff --git a/dwarflint/highlevel_check.hh b/dwarflint/highlevel_check.hh index 6d57d5fb1..5505ae152 100644 --- a/dwarflint/highlevel_check.hh +++ b/dwarflint/highlevel_check.hh @@ -41,9 +41,9 @@ class open_highlevel_dwarf Dwfl *const _m_dwfl; Dwarf *const _m_dw; public: - static checkdescriptor descriptor () { + static checkdescriptor const *descriptor () { static checkdescriptor cd ("open_highlevel_dwarf"); - return cd; + return &cd; } elfutils::dwarf const dw; @@ -57,11 +57,11 @@ class highlevel_check { open_highlevel_dwarf *_m_loader; public: - static checkdescriptor const &descriptor () { + static checkdescriptor const *descriptor () { static checkdescriptor cd (checkdescriptor::create ("open_highlevel_dwarf") .prereq ()); - return cd; + return &cd; } elfutils::dwarf const &dw; diff --git a/dwarflint/lowlevel_checks.cc b/dwarflint/lowlevel_checks.cc new file mode 100644 index 000000000..65349fadc --- /dev/null +++ b/dwarflint/lowlevel_checks.cc @@ -0,0 +1,89 @@ +/* Scheduler for low_level checks + Copyright (C) 2010 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 "lowlevel_checks.hh" +#include "sections.hh" +#include "check_debug_info.hh" +#include "check_debug_abbrev.hh" +#include "check_debug_aranges.hh" +#include "check_debug_pub.hh" +#include "check_debug_loc_range.hh" +#include "check_debug_line.hh" + +checkdescriptor const * +lowlevel_checks::descriptor () +{ + static checkdescriptor cd + (checkdescriptor::create ("lowlevel_checks") + .prereq () + .prereq () + .prereq () + .prereq () + .prereq () + .prereq () + .prereq () + .prereq () + .hidden () + ); + return &cd; +} +static reg reg_lowlevel_checks; + +namespace +{ + template struct do_check { + static void check (checkstack &stack, dwarflint &lint) { + lint.check (stack); + } + }; + + // There is no separate check_debug_str pass. Make a stub so that + // we can do it all in one macro-expanded sweep below. +#define STUBBED_CHECK(NAME) \ + struct check_debug_##NAME {}; \ + template<> struct do_check { \ + static void check (__attribute__ ((unused)) checkstack &stack, \ + __attribute__ ((unused)) dwarflint &lint) {} \ + } + STUBBED_CHECK(str); + STUBBED_CHECK(mac); +#undef STUBBED_CHECK +} + +lowlevel_checks::lowlevel_checks (checkstack &stack, dwarflint &lint) +{ + // Then check whatever else is there. For each existing section + // request that the check passes. Re-requesting already-passed + // checks is OK, the scheduler caches it. +#define SEC(NAME) \ + section *NAME = \ + lint.toplev_check > (stack); \ + if (NAME != NULL) \ + do_check::check (stack, lint); + DEBUGINFO_SECTIONS; +#undef SEC + + lint.check (stack); +} diff --git a/dwarflint/lowlevel_checks.hh b/dwarflint/lowlevel_checks.hh new file mode 100644 index 000000000..9892b9101 --- /dev/null +++ b/dwarflint/lowlevel_checks.hh @@ -0,0 +1,39 @@ +/* Scheduler for low_level checks + Copyright (C) 2010 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 + . */ + +#ifndef DWARFLINT_LOWLEVEL_CHECKS_HH +#define DWARFLINT_LOWLEVEL_CHECKS_HH + +#include "checks.hh" + +class lowlevel_checks + : public check +{ +public: + static checkdescriptor const *descriptor (); + lowlevel_checks (checkstack &stack, dwarflint &lint); +}; + +#endif//DWARFLINT_LOWLEVEL_CHECKS_HH diff --git a/dwarflint/messages.h b/dwarflint/messages.h index f5b337f92..af2048b75 100644 --- a/dwarflint/messages.h +++ b/dwarflint/messages.h @@ -66,6 +66,7 @@ extern "C" MC (line, 19) /* messages related to .debug_line */ \ MC (reloc, 20) /* messages related to relocation handling */ \ MC (header, 21) /* messages related to header portions in general */ \ + MC (mac, 22) /* messages related to .debug_mac */ \ MC (other, 31) /* messages unrelated to any of the above */ enum message_category diff --git a/dwarflint/sections.cc b/dwarflint/sections.cc index b1eb3d508..74685cecd 100644 --- a/dwarflint/sections.cc +++ b/dwarflint/sections.cc @@ -37,20 +37,20 @@ #include "pri.hh" #include "options.h" -checkdescriptor const & +checkdescriptor const * load_sections::descriptor () { static checkdescriptor cd ("load_sections"); - return cd; + return &cd; } -checkdescriptor const & +checkdescriptor const * section_base::descriptor () { static checkdescriptor cd (checkdescriptor::create () .prereq ()); - return cd; + return &cd; } namespace @@ -435,6 +435,7 @@ namespace case sec_line: return mc_line; case sec_loc: return mc_loc; case sec_ranges: return mc_ranges; + case sec_mac: return mc_mac; case sec_pubnames: case sec_pubtypes: @@ -445,7 +446,6 @@ namespace return mc_reloc; // xxx don't have one - case sec_mac: case sec_invalid: case sec_locexpr: case rel_value: diff --git a/dwarflint/sections.hh b/dwarflint/sections.hh index bb8c87206..48151ae84 100644 --- a/dwarflint/sections.hh +++ b/dwarflint/sections.hh @@ -33,7 +33,7 @@ class load_sections : public check { public: - static checkdescriptor const &descriptor (); + static checkdescriptor const *descriptor (); elf_file file; load_sections (checkstack &stack, dwarflint &lint); @@ -46,7 +46,7 @@ class section_base sec &get_sec_or_throw (section_id secid); public: - static checkdescriptor const &descriptor (); + static checkdescriptor const *descriptor (); sec § elf_file &file; @@ -65,11 +65,11 @@ class section , public check > { public: - static checkdescriptor const &descriptor () { + static checkdescriptor const *descriptor () { static checkdescriptor cd (checkdescriptor::create (section_name[sec_id]) .inherit ()); - return cd; + return &cd; } explicit section (checkstack &stack, dwarflint &lint)