From: Petr Machata Date: Thu, 17 Mar 2011 16:06:53 +0000 (+0100) Subject: dwarflint: Fix message filtering X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0e9ce477310be7ff193338a67ddf76023326ee0d;p=thirdparty%2Felfutils.git dwarflint: Fix message filtering --- diff --git a/dwarflint/main.cc b/dwarflint/main.cc index 818d30f69..eb0252e0a 100644 --- a/dwarflint/main.cc +++ b/dwarflint/main.cc @@ -183,8 +183,7 @@ main (int argc, char *argv[]) if (!be_strict) { warning_criteria &= message_term (mc_none, mc_strings); - warning_criteria - &= message_term (cat (mc_line, mc_header, mc_acc_bloat), mc_none); + warning_criteria.and_not (mc_line | mc_acc_bloat); warning_criteria &= message_term (mc_none, mc_pubtypes); } @@ -196,8 +195,8 @@ main (int argc, char *argv[]) if (false) // for debugging { - std::cout << "warning criteria: " << warning_criteria.str () << std::endl; - std::cout << "error criteria: " << error_criteria.str () << std::endl; + std::cout << "warning criteria: " << warning_criteria << std::endl; + std::cout << "error criteria: " << error_criteria << std::endl; } /* Before we start tell the ELF library which version we are using. */ diff --git a/dwarflint/messages.cc b/dwarflint/messages.cc index 1c2f974bc..28b8d20c5 100644 --- a/dwarflint/messages.cc +++ b/dwarflint/messages.cc @@ -1,5 +1,5 @@ /* Pedantic checking of DWARF files - Copyright (C) 2009, 2010 Red Hat, Inc. + Copyright (C) 2009-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 @@ -39,13 +39,14 @@ bool message_accept (struct message_criteria const *cri, unsigned long cat) { - for (size_t i = 0; i < cri->size; ++i) + for (size_t i = 0; i < cri->size (); ++i) { - struct message_term *t = cri->terms + i; - if ((t->positive & cat) == t->positive - && (t->negative & cat) == 0) + message_term const &t = cri->at (i); + if ((t.positive & cat) == t.positive + && (t.negative & cat) == 0) return true; } + return false; } @@ -66,20 +67,32 @@ namespace MESSAGE_CATEGORIES #undef MC } - }; + } cat_names; + size_t cat_max = cat_names.size (); +} + + +message_category +operator | (message_category a, message_category b) +{ + return static_cast ((unsigned long)a | b); +} + +message_category & +operator |= (message_category &a, message_category b) +{ + a = a | b; + return a; } std::string message_term::str () const { - static cat_to_str names; - static size_t max = names.size (); - std::ostringstream os; os << '('; bool got = false; - for (size_t i = 0; i <= max; ++i) + for (size_t i = 0; i <= cat_max; ++i) { size_t mask = 1u << i; if ((positive & mask) != 0 @@ -89,7 +102,7 @@ message_term::str () const os << " & "; if ((negative & (1u << i)) != 0) os << '~'; - os << names[i]; + os << cat_names[i]; got = true; } } @@ -106,9 +119,9 @@ message_criteria::str () const { std::ostringstream os; - for (size_t i = 0; i < size; ++i) + for (size_t i = 0; i < size (); ++i) { - message_term const &t = terms[i]; + message_term const &t = at (i); if (i > 0) os << " | "; os << t.str (); @@ -121,14 +134,14 @@ void message_criteria::operator &= (message_term const &term) { assert ((term.positive & term.negative) == 0); - for (size_t i = 0; i < size; ) + for (size_t i = 0; i < size (); ) { - message_term &t = terms[i]; - t.positive |= term.positive; - t.negative |= term.negative; + message_term &t = at (i); + t.positive = cat (t.positive, term.positive); + t.negative = cat (t.negative, term.negative); if ((t.positive & t.negative) != 0) /* A ^ ~A -> drop the term. */ - terms[i] = terms[--size]; + erase (begin () + i); else ++i; } @@ -138,8 +151,7 @@ void message_criteria::operator |= (message_term const &term) { assert ((term.positive & term.negative) == 0); - REALLOC (this, terms); - terms[size++] = term; + push_back (term); } // xxx this one is inaccessible from the outside. Make it like &=, |= @@ -150,57 +162,86 @@ operator ! (message_term const &term) { assert ((term.positive & term.negative) == 0); - unsigned max = 0; -#define MC(CAT, ID) max = ID; - MESSAGE_CATEGORIES -#undef MC - message_criteria ret; - for (size_t i = 0; i < max; ++i) + for (size_t i = 0; i < cat_max; ++i) { unsigned mask = 1u << i; if ((term.positive & mask) != 0) - ret |= message_term (1u << i, mc_none); + ret |= message_term ((message_category)(1u << i), mc_none); else if ((term.negative & mask) != 0) - ret |= message_term (mc_none, 1u << i); + ret |= message_term (mc_none, (message_category)(1u << i)); } return ret; } -// xxx this one is inaccessible from the outside. Make it like &=, |= -// above +std::ostream & +operator<< (std::ostream &o, message_category cat) +{ + o << '('; + + bool got = false; + for (size_t i = 0; i <= cat_max; ++i) + { + size_t mask = 1u << i; + if ((cat & mask) != 0) + { + if (got) + o << ","; + o << cat_names[i]; + got = true; + } + } + + if (!got) + o << "none"; + + return o << ')'; +} + +std::ostream & +operator<< (std::ostream &o, message_term const &term) +{ + return o << term.str (); +} + +std::ostream & +operator<< (std::ostream &o, __attribute__ ((unused)) message_criteria const &criteria) +{ + return o << criteria.str (); +} + /* MUL((a&b + c&d), (e&f + g&h)) -> (a&b&e&f + a&b&g&h + c&d&e&f + c&d&g&h) */ void -message_cri_mul (struct message_criteria *cri, struct message_criteria *rhs) +message_criteria::operator *= (message_criteria const &rhs) { struct message_criteria ret; WIPE (ret); - for (size_t i = 0; i < cri->size; ++i) - for (size_t j = 0; j < rhs->size; ++j) + for (size_t i = 0; i < size (); ++i) + for (size_t j = 0; j < rhs.size (); ++j) { - struct message_term t1 = cri->terms[i]; - struct message_term *t2 = rhs->terms + j; - t1.positive |= t2->positive; - t1.negative |= t2->negative; + message_term t1 = at (i); + message_term const &t2 = rhs.at (j); + t1.positive |= t2.positive; + t1.negative |= t2.negative; if (t1.positive & t1.negative) /* A ^ ~A -> drop the term. */ continue; ret |= t1; } - free (cri->terms); - *cri = ret; + *this = ret; } // xxx this one is inaccessible from the outside. Bind it properly /* Reject message if TERM passes. */ void -message_cri_and_not (message_criteria &cri, message_term const &term) +message_criteria::and_not (message_term const &term) { + // xxxxx really?? "!"?? message_criteria tmp = !message_term (term.negative, term.positive); - message_cri_mul (&cri, &tmp); + *this *= tmp; } static void diff --git a/dwarflint/messages.hh b/dwarflint/messages.hh index d14230b0a..7809fb9cb 100644 --- a/dwarflint/messages.hh +++ b/dwarflint/messages.hh @@ -1,5 +1,5 @@ /* 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 @@ -29,6 +29,8 @@ #include "where.h" #include "libdw.h" #include +#include +#include #define MESSAGE_CATEGORIES \ /* Severity: */ \ @@ -60,7 +62,7 @@ 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 (mac, 22) /* messages related to .debug_mac */ \ MC (other, 31) /* messages unrelated to any of the above */ enum message_category @@ -73,38 +75,41 @@ enum message_category #undef MC }; +message_category operator | (message_category a, message_category b); +message_category &operator |= (message_category &a, message_category b); +std::ostream &operator<< (std::ostream &o, message_category cat); + struct message_term { /* Given a term like A && !B && C && !D, we decompose it thus: */ - unsigned long positive; /* non-zero bits for plain predicates */ - unsigned long negative; /* non-zero bits for negated predicates */ + message_category positive; /* non-zero bits for plain predicates */ + message_category negative; /* non-zero bits for negated predicates */ - message_term (unsigned long pos, unsigned long neg) + message_term (message_category pos, message_category neg = mc_none) : positive (pos), negative (neg) {} + std::string str () const; }; +std::ostream &operator<< (std::ostream &o, message_term const &term); + struct message_criteria + : protected std::vector { - struct message_term *terms; - size_t size; - size_t alloc; - - message_criteria () - : terms (NULL), size (0), alloc (0) - {} - - ~message_criteria () - { - free (terms); - } + using std::vector::at; + using std::vector::size; void operator |= (message_term const &term); void operator &= (message_term const &term); + void operator *= (message_criteria const &term); + void and_not (message_term const &term); + std::string str () const; }; +std::ostream &operator<< (std::ostream &o, message_criteria const &criteria); + message_criteria operator ! (message_term const &); extern void wr_error (const struct where *wh, const char *format, ...) @@ -154,7 +159,7 @@ cat (message_category c1, message_category c3 = mc_none, message_category c4 = mc_none) { - return static_cast (c1 | c2 | c3 | c4); + return c1 | c2 | c3 | c4; } std::ostream &wr_warning (where const &wh); diff --git a/dwarflint/sections.cc b/dwarflint/sections.cc index d5736c4be..4a8f6401e 100644 --- a/dwarflint/sections.cc +++ b/dwarflint/sections.cc @@ -250,12 +250,7 @@ namespace REALLOC (file, sec); file->sec[file->size++].id = sec_invalid; - bool check_rel = true; - - /* Try to obtain .shstrtab, which we will need in following. If - we fail, elf is broken. */ - Elf_Scn *shstrscn = elf_getscn (elf, file->ehdr.e_shstrndx); - if (shstrscn == NULL || elf_rawdata (shstrscn, NULL) == NULL) + if (false) { invalid_elf: wr_error () << "Broken ELF: " << elf_errmsg (-1) << "." @@ -263,6 +258,11 @@ namespace goto close_and_out; } + /* Check that the ELF file is sound. */ + for (Elf_Scn *scn = NULL; (scn = elf_nextscn (elf, scn)); ) + if (elf_rawdata (scn, NULL) == NULL) + goto invalid_elf; + for (Elf_Scn *scn = NULL; (scn = elf_nextscn (elf, scn)); ) { REALLOC (file, sec); @@ -366,7 +366,7 @@ namespace if (it->second.secndx != 0) file->debugsec[it->second.id] = file->sec + it->second.secndx; - if (check_rel) + if (true) { Elf_Data *reloc_symdata = NULL; if (reloc_symtab != NULL) diff --git a/dwarflint/tests/run-bad.sh b/dwarflint/tests/run-bad.sh index 41c56a5f1..fc14f8030 100755 --- a/dwarflint/tests/run-bad.sh +++ b/dwarflint/tests/run-bad.sh @@ -36,7 +36,9 @@ testrun_compare ./dwarflint hello.bad-1 <) error: .rela.debug_info: offset 0x1d00: invalid relocation 256 (). error: .rela.debug_info: offset 0x2500: invalid relocation 2560 (). error: .rela.debug_info: offset 0x3600: invalid relocation 256 (). +warning: .debug_info: CU 0: abbrev table offset seems to lack a relocation +warning: .debug_info: DIE 0xb (abbr. attribute 0): strp seems to lack a relocation +warning: .debug_info: DIE 0xb (abbr. attribute 0x4): strp seems to lack a relocation +warning: .debug_info: DIE 0xb (abbr. attribute 0xa): data4 seems to lack a relocation error: .debug_line: table 0: header claims that it has a size of 542, but in fact it has a size of 30. error: .debug_info: DIE 0xb (abbr. attribute 0xa): unresolved reference to .debug_line table 0x0. EOF diff --git a/dwarflint/tests/run-check_debug_info_refs.sh b/dwarflint/tests/run-check_debug_info_refs.sh index 7b36243fa..74288261c 100755 --- a/dwarflint/tests/run-check_debug_info_refs.sh +++ b/dwarflint/tests/run-check_debug_info_refs.sh @@ -31,13 +31,14 @@ testfiles check_debug_info_refs-{1,2} testrun_compare ./dwarflint --check=check_debug_info_refs check_debug_info_refs-1 <