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);
}
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. */
/* 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
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;
}
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<message_category> ((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
os << " & ";
if ((negative & (1u << i)) != 0)
os << '~';
- os << names[i];
+ os << cat_names[i];
got = true;
}
}
{
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 ();
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;
}
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 &=, |=
{
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
/* 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 "where.h"
#include "libdw.h"
#include <string>
+#include <iosfwd>
+#include <vector>
#define MESSAGE_CATEGORIES \
/* Severity: */ \
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
#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<message_term>
{
- 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<message_term>::at;
+ using std::vector<message_term>::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, ...)
message_category c3 = mc_none,
message_category c4 = mc_none)
{
- return static_cast<message_category> (c1 | c2 | c3 | c4);
+ return c1 | c2 | c3 | c4;
}
std::ostream &wr_warning (where const &wh);
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) << "."
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);
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)
error: .debug_info: DIE 0x83: abbrev section at 0x0 doesn't contain code 83.
EOF
-testrun_compare ./dwarflint hello.bad-3 <<EOF
+testrun_compare ./dwarflint --check=@low hello.bad-3 <<EOF
+error: .debug_info: DIE 0x2d: This DIE had children, but no DW_AT_sibling attribute.
+error: .debug_info: DIE 0xb: This DIE had children, but no DW_AT_sibling attribute.
error: .debug_info: DIE 0x91: toplevel DIE chain contains more than one DIE.
error: .debug_info: DIE 0x98: toplevel DIE chain contains more than one DIE.
error: .debug_info: DIE 0x9e: toplevel DIE chain contains more than one DIE.
EOF
testrun_compare ./dwarflint empty-1 <<EOF
-warning: .debug_line: table 0: the file #1 \`empty.c' is not used.
+warning: .debug_line: table 0: no CU uses this line table.
error: .debug_info: DIE 0x29 (abbr. attribute 0x13): references .debug_line table, but CU DIE lacks DW_AT_stmt_list.
EOF
testrun_compare ./dwarflint garbage-8 <<EOF
error: .debug_info: DIE 0x6c (abbr. attribute 0x43): DW_AT_sibling with a value of 0.
+error: .debug_info: DIE 0x6c: This DIE had children, but no DW_AT_sibling attribute.
error: .debug_info: DIE 0xab (abbreviation 113): DIE chain not terminated with null entry.
EOF
error: .rela.debug_info: offset 0x1d00: invalid relocation 256 (<INVALID RELOC>).
error: .rela.debug_info: offset 0x2500: invalid relocation 2560 (<INVALID RELOC>).
error: .rela.debug_info: offset 0x3600: invalid relocation 256 (<INVALID RELOC>).
+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
testrun_compare ./dwarflint --check=check_debug_info_refs check_debug_info_refs-1 <<EOF
error: .debug_aranges: table 48 (CU DIE 95): there has already been arange section for this CU.
+warning: .debug_info: CU 0: no aranges table is associated with this CU.
EOF
-testrun_compare ./dwarflint --strict --check=check_debug_info_refs check_debug_info_refs-1 <<EOF
+testrun_compare ./dwarflint --check=check_debug_info_refs check_debug_info_refs-1 <<EOF
error: .debug_aranges: table 48 (CU DIE 95): there has already been arange section for this CU.
warning: .debug_info: CU 0: no aranges table is associated with this CU.
EOF
-testrun_compare ./dwarflint --strict --check=check_debug_info_refs check_debug_info_refs-2 <<EOF
+testrun_compare ./dwarflint --check=check_debug_info_refs check_debug_info_refs-2 <<EOF
warning: .debug_info: CU 0: no aranges table is associated with this CU.
EOF
#! /bin/sh
-# 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
testfiles crc7.ko.debug
testrun_compare ./dwarflint --check check_duplicate_DW_tag_variable crc7.ko.debug <<EOF
-warning: .debug_line: offset 0x3c4: the include #6 \`XXXXXX' is not used.
-warning: .debug_line: table 967: the include #6 \`XXXXXX' is not used.
+warning: .debug_info: CU 16614: no aranges table is associated with this CU.
error: .debug_info: DIE 0x3d21: Redeclaration of variable 'console_printk', originally seen at DIE 37f3.
error: .debug_info: DIE 0x3d2e: Redeclaration of variable 'hex_asc', originally seen at DIE 380b.
error: .debug_info: DIE 0x3d41: Redeclaration of variable '__per_cpu_offset', originally seen at DIE 382e.
#! /bin/sh
-# 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
testfiles libdl-2.12.so.debug
# Here we test that dwarflint can tolerate invalid attribute name.
-testrun_compare ./dwarflint --check=@low --nognu libdl-2.12.so.debug <<EOF
+testrun_compare ./dwarflint --check=@low --nognu --ignore-bloat libdl-2.12.so.debug <<EOF
error: .debug_abbrev: abbr. attribute 0xbe: invalid or unknown name 0x2107.
error: .debug_abbrev: abbr. attribute 0x330: invalid or unknown name 0x2107.
error: .debug_abbrev: abbr. attribute 0xa28: invalid or unknown name 0x2107.
error: .debug_abbrev: abbr. attribute 0x108e: invalid or unknown name 0x2107.
error: .debug_abbrev: abbr. attribute 0x1300: invalid or unknown name 0x2107.
+warning: .debug_info: CU 55709: no aranges table is associated with this CU.
+warning: .debug_info: CU 56524: no aranges table is associated with this CU.
EOF
# Here we test proper support for DW_AT_GNU_vector
-testrun_compare ./dwarflint --check=@low libdl-2.12.so.debug <<EOF
-No errors
+testrun_compare ./dwarflint --check=@low --ignore-bloat libdl-2.12.so.debug <<EOF
+warning: .debug_info: CU 55709: no aranges table is associated with this CU.
+warning: .debug_info: CU 56524: no aranges table is associated with this CU.
EOF
#! /bin/sh
-# 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
testfiles location-leaks
testrun_compare ./dwarflint location-leaks <<EOF
+warning: .debug_loc: loclist 0x38: entry covers no range.
error: .debug_info: DIE 0x62: attribute \`location': PC range [0x400495, 0x40049a) outside containing scope.
error: .debug_info: DIE 0x51: in this context: [0x400498, 0x4004b2).
EOF
EOF
testrun_compare ./dwarflint null.o <<EOF
+warning: .debug_abbrev: [0x0, 0x1): unnecessary padding with zero bytes.
+warning: .debug_abbrev: no abbreviations.
error: .debug_info: data not found.
EOF
-testrun_compare ./dwarflint --nodebug:ignore null.o <<EOF
+testrun_compare ./dwarflint --ignore-bloat --nodebug:ignore null.o <<EOF
No errors
EOF