From 044ae72d833db95085407564c3fb2ec175320930 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Mon, 18 Apr 2011 13:29:58 +0200 Subject: [PATCH] dwarflint: Add cu_locus, die_locus, use throughout, drop to_where --- dwarflint/Makefile.am | 2 + dwarflint/check_debug_abbrev.cc | 3 +- dwarflint/check_debug_aranges.cc | 4 +- dwarflint/check_debug_info.cc | 52 ++++++-------- dwarflint/check_debug_info.hh | 14 ++-- dwarflint/check_debug_line.cc | 6 +- dwarflint/check_debug_loc_range.cc | 16 ++--- dwarflint/check_debug_loc_range.hh | 6 +- dwarflint/check_debug_pub.cc | 6 +- dwarflint/check_die_decl_call.cc | 12 ++-- dwarflint/check_die_line_info.cc | 2 +- dwarflint/check_die_tree.cc | 2 +- dwarflint/check_duplicate_DW_tag_variable.cc | 4 +- dwarflint/check_dups_abstract_origin.cc | 2 +- dwarflint/check_expected_trees.cc | 6 +- dwarflint/check_linkage_external_die.cc | 6 +- dwarflint/check_matching_ranges.cc | 10 ++- dwarflint/check_range_out_of_scope.cc | 12 ++-- dwarflint/check_self_referential_die.cc | 2 +- dwarflint/checked_read.cc | 22 +++--- dwarflint/checked_read.hh | 8 +-- dwarflint/cu_coverage.cc | 4 ++ dwarflint/die_locus.cc | 57 ++++++++++++++++ dwarflint/die_locus.hh | 71 ++++++++++++++++++++ dwarflint/highlevel_check.hh | 12 +--- dwarflint/locstats.cc | 5 +- dwarflint/lowlevel_checks.cc | 4 ++ dwarflint/pri.cc | 7 ++ dwarflint/pri.hh | 2 + dwarflint/reloc.cc | 2 +- dwarflint/tests/run-bad.sh | 30 ++++----- dwarflint/where.cc | 3 +- 32 files changed, 259 insertions(+), 135 deletions(-) create mode 100644 dwarflint/die_locus.cc create mode 100644 dwarflint/die_locus.hh diff --git a/dwarflint/Makefile.am b/dwarflint/Makefile.am index 1fc154afe..c8e5c833f 100644 --- a/dwarflint/Makefile.am +++ b/dwarflint/Makefile.am @@ -48,6 +48,7 @@ dwarflint_SOURCES = \ checks.hh checks_i.hh \ coverage.cc coverage.hh \ cu_coverage.cc cu_coverage.hh cu_coverage_i.hh \ + die_locus.cc die_locus.hh \ dwarf_2.cc dwarf_2.hh \ dwarf_3.cc dwarf_3.hh \ dwarf_4.cc dwarf_4.hh \ @@ -95,6 +96,7 @@ dwarflint_SOURCES = \ locstats_SOURCES = \ locstats.cc \ + die_locus.cc die_locus.hh \ files.cc files.hh \ option.cc option.hh option_i.hh \ section_id.cc section_id.hh \ diff --git a/dwarflint/check_debug_abbrev.cc b/dwarflint/check_debug_abbrev.cc index 5e0311608..c818462fc 100644 --- a/dwarflint/check_debug_abbrev.cc +++ b/dwarflint/check_debug_abbrev.cc @@ -79,8 +79,7 @@ abbrev_attrib_locus::abbrev_attrib_locus (abbrev_attrib_locus const ©) std::string abbrev_attrib_locus::name () const { - assert (_m_name != -1); - return elfutils::dwarf::attributes::name (_m_name); + return pri::attr_name (_m_name); } void diff --git a/dwarflint/check_debug_aranges.cc b/dwarflint/check_debug_aranges.cc index d775608be..032a295fd 100644 --- a/dwarflint/check_debug_aranges.cc +++ b/dwarflint/check_debug_aranges.cc @@ -210,7 +210,7 @@ check_aranges_structural (struct elf_file *file, wr_error (&where, ": can't read table length.\n"); return false; } - if (!read_size_extra (&ctx, size32, &size, &offset_size, &where)) + if (!read_size_extra (&ctx, size32, &size, &offset_size, where)) return false; struct read_ctx sub_ctx; @@ -306,7 +306,7 @@ check_aranges_structural (struct elf_file *file, /* Address size. */ int address_size; error_code err = read_address_size (&sub_ctx, file->addr_64, - &address_size, &where); + &address_size, where); if (err != err_ok) retval = false; if (err == err_fatal) diff --git a/dwarflint/check_debug_info.cc b/dwarflint/check_debug_info.cc index 42227e5d1..5aff2b996 100644 --- a/dwarflint/check_debug_info.cc +++ b/dwarflint/check_debug_info.cc @@ -175,13 +175,8 @@ namespace while (!read_ctx_eof (&ctx)) { const unsigned char *cu_begin = ctx.ptr; - struct where where = WHERE (sec_info, NULL); uint64_t offset = read_ctx_get_offset (&ctx); - where_reset_1 (&where, offset); - - cu_head head; - head.offset = offset; - head.where = where; + cu_head head (offset); /* Reading CU head is a bit tricky, because we don't know if we have run into (superfluous but allowed) zero padding @@ -190,7 +185,7 @@ namespace if (!read_ctx_need_data (&ctx, 4) && read_check_zero_padding (&ctx, &off_start, &off_end)) { - wr_message_padding_0 (mc_info | mc_header, where, + wr_message_padding_0 (mc_info | mc_header, head.where, off_start, off_end); break; } @@ -203,25 +198,25 @@ namespace uint32_t size32; if (!read_ctx_read_4ubyte (&ctx, &size32)) { - wr_error (where) << "can't read CU length." << std::endl; + wr_error (head.where) << "can't read CU length." << std::endl; throw check_base::failed (); } if (size32 == 0 && read_check_zero_padding (&ctx, &off_start, &off_end)) { - wr_message_padding_0 (mc_info | mc_header, where, + wr_message_padding_0 (mc_info | mc_header, head.where, off_start, off_end); break; } Dwarf_Off cu_size; if (!read_size_extra (&ctx, size32, &cu_size, - &head.offset_size, &where)) + &head.offset_size, head.where)) throw check_base::failed (); if (!read_ctx_need_data (&ctx, cu_size)) { - wr_error (where) + wr_error (head.where) << "section doesn't have enough data to read CU of size " << cu_size << '.' << std::endl; throw check_base::failed (); @@ -241,7 +236,7 @@ namespace if (dwarf_version::get (version) == NULL) { wr_error (head.where) << "unsupported CU version " - << version << '.' << std::endl; + << version << '.' << std::endl; throw check_base::failed (); } if (version == 2 && head.offset_size == 8) // xxx? @@ -276,7 +271,7 @@ namespace /* Address size. */ error_code err = read_address_size (&ctx, file->addr_64, - &head.address_size, &head.where); + &head.address_size, head.where); if (err == err_fatal) throw check_base::failed (); else if (err == err_nohl) @@ -288,7 +283,7 @@ namespace if (!read_ctx_skip (&ctx, head.size)) { - wr_error (where) << pri::not_enough ("next CU") << std::endl; + wr_error (head.where) << pri::not_enough ("next CU") << std::endl; throw check_base::failed (); } @@ -395,7 +390,7 @@ namespace struct value_check_cb_ctx { struct read_ctx *const ctx; - struct where *const where; + locus const *where; struct cu *const cu; struct ref_record *local_die_refs; Elf_Data *strings; @@ -545,12 +540,11 @@ namespace uint64_t sibling_addr = 0; uint64_t die_off, prev_die_off = 0; struct abbrev *abbrev = NULL; - struct where where = WHERE (sec_info, NULL); unsigned long die_count = 0; int retval = 0; struct value_check_cb_ctx cb_ctx = { - ctx, &where, cu, + ctx, NULL, cu, local_die_refs, strings, strings_coverage, pc_coverage, @@ -560,20 +554,18 @@ namespace while (!read_ctx_eof (ctx)) { - where = cu->head->where; die_off = read_ctx_get_offset (ctx); /* Shift reported DIE offset by CU offset, to match the way readelf reports DIEs. */ - where_reset_2 (&where, die_off + cu->head->offset); + die_locus where (cu->head->offset + die_off); + cb_ctx.where = &where; uint64_t abbr_code; if (!checked_read_uleb128 (ctx, &abbr_code, where, "abbrev code")) return -1; -#define DEF_PREV_WHERE \ - struct where prev_where = where; \ - where_reset_2 (&prev_where, prev_die_off + cu->head->offset) +#define DEF_PREV_WHERE die_locus prev_where (cu->head->offset + prev_die_off) /* Check sibling value advertised last time through the loop. */ if (sibling_addr != 0) @@ -671,7 +663,7 @@ namespace for (struct abbrev_attrib *it = abbrev->attribs; it->name != 0 || it->form != 0; ++it) { - where.ref = &it->where; + where.set_attrib_name (it->name); int form_name = it->form; // In following, attribute may be NULL, but form never @@ -863,7 +855,7 @@ namespace // field? See check_debug_loc_range::op_read_form if (!check_location_expression (ver, file, &block, cu, - expr_start, reloc, value, &where)) + expr_start, reloc, value, where)) return -1; } else @@ -928,7 +920,7 @@ namespace if (valuep != NULL) *valuep = value; } - where.ref = NULL; + where.set_attrib_name (-1); if (high_pc != (uint64_t)-1 && low_pc != (uint64_t)-1 && high_pc_relative) @@ -960,7 +952,7 @@ namespace else { if (!high_pc_relative) - check_range_relocations (mc_die_other, &where, + check_range_relocations (where, mc_die_other, &file, low_pc_symbol, high_pc_symbol, "DW_AT_low_pc and DW_AT_high_pc"); @@ -973,8 +965,6 @@ namespace } } - where.ref = &abbrev->where; - if (abbrev->has_children) { int st = read_die_chain (ver, file, ctx, cu, abbrevs, strings, @@ -1004,7 +994,7 @@ namespace } if (sibling_addr != 0) - wr_error (where) + wr_error (die_locus (cu->head->offset + prev_die_off)) << "this DIE should have had its sibling at " << pri::hex (sibling_addr) << ", but the DIE chain ended." << std::endl; @@ -1103,7 +1093,7 @@ check_debug_info::check_debug_info (checkstack &stack, dwarflint &lint) it != cu_headers.end (); ++it) { cu_head const &head = *it; - where const &where = head.where; + cu_locus where = head.where; { cu cur; memset (&cur, 0, sizeof (cur)); @@ -1150,7 +1140,7 @@ check_debug_info::check_debug_info (checkstack &stack, dwarflint &lint) if (success) { - where wh = WHERE (sec_info, NULL); + section_locus wh (sec_info); if (ctx.ptr != ctx.end) /* Did we read up everything? */ wr_message (mc_die_other | mc_impact_4, &wh, diff --git a/dwarflint/check_debug_info.hh b/dwarflint/check_debug_info.hh index b82b18f6c..ad139c3af 100644 --- a/dwarflint/check_debug_info.hh +++ b/dwarflint/check_debug_info.hh @@ -35,30 +35,32 @@ #include "check_debug_line_i.hh" #include "check_debug_aranges_i.hh" #include "sections_i.hh" +#include "die_locus.hh" struct cu_head { - uint64_t offset; + Dwarf_Off offset; Dwarf_Off size; // Size of this CU. Dwarf_Off head_size; // Size from begin to 1st byte of CU. Dwarf_Off total_size; // size + head_size - int offset_size; // Offset size in this CU. - ::where where; // Where this section was defined. + int offset_size; // Offset size in this CU. Dwarf_Off abbrev_offset; // Abbreviation section that this CU uses. int version; // CU version int address_size; // Address size in bytes on the target machine. - cu_head () - : offset (0) + cu_locus where; + + explicit cu_head (Dwarf_Off a_offset) + : offset (a_offset) , size (0) , head_size (0) , total_size (0) , offset_size (0) - , where () , abbrev_offset (0) , version (0) , address_size (0) + , where (a_offset) {} }; diff --git a/dwarflint/check_debug_line.cc b/dwarflint/check_debug_line.cc index cc0599915..b6b8309f1 100644 --- a/dwarflint/check_debug_line.cc +++ b/dwarflint/check_debug_line.cc @@ -23,6 +23,10 @@ Network licensing program, please visit www.openinventionnetwork.com . */ +#ifdef HAVE_CONFIG_H +# include +#endif + #include "check_debug_line.hh" #include "check_debug_info.hh" #include "sections.hh" @@ -171,7 +175,7 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint) wr_error (where) << "can't read table length." << std::endl; throw check_base::failed (); } - if (!read_size_extra (&ctx, size32, &size, &offset_size, &where)) + if (!read_size_extra (&ctx, size32, &size, &offset_size, where)) throw check_base::failed (); struct read_ctx sub_ctx; diff --git a/dwarflint/check_debug_loc_range.cc b/dwarflint/check_debug_loc_range.cc index 611f1aec1..1c09bd839 100644 --- a/dwarflint/check_debug_loc_range.cc +++ b/dwarflint/check_debug_loc_range.cc @@ -455,7 +455,7 @@ namespace wr_message (cat | mc_impact_2 | mc_reloc, &where, ": end of address range is relocated, but the beginning wasn't.\n"); else - check_range_relocations (cat, &where, file, + check_range_relocations (where, cat, file, begin_symbol, end_symbol, "begin and end address"); } @@ -518,7 +518,7 @@ namespace /* location expression itself */ uint64_t expr_start = read_ctx_get_offset (&ctx); if (!check_location_expression - (ver, *file, &ctx, cu, expr_start, &sec->rel, len, &where)) + (ver, *file, &ctx, cu, expr_start, &sec->rel, len, where)) return false; uint64_t expr_end = read_ctx_get_offset (&ctx); if (!overlap @@ -865,13 +865,13 @@ check_location_expression (dwarf_version const *ver, uint64_t init_off, struct relocation_data *reloc, size_t length, - struct where *wh) + locus const &loc) { struct read_ctx ctx; if (!read_ctx_init_sub (&ctx, parent_ctx, parent_ctx->ptr, parent_ctx->ptr + length)) { - wr_error (wh, PRI_NOT_ENOUGH, "location expression"); + wr_error (&loc, PRI_NOT_ENOUGH, "location expression"); return false; } @@ -881,7 +881,7 @@ check_location_expression (dwarf_version const *ver, while (!read_ctx_eof (&ctx)) { uint64_t opcode_off = read_ctx_get_offset (&ctx) + init_off; - locexpr_locus where (opcode_off, wh); + locexpr_locus where (opcode_off, &loc); opaddrs.add (opcode_off); uint8_t opcode; @@ -1004,8 +1004,8 @@ found_hole (uint64_t start, uint64_t length, void *data) } void -check_range_relocations (enum message_category cat, - struct where *where, +check_range_relocations (locus const &loc, + enum message_category cat, struct elf_file const *file, GElf_Sym *begin_symbol, GElf_Sym *end_symbol, @@ -1014,7 +1014,7 @@ check_range_relocations (enum message_category cat, if (begin_symbol != NULL && end_symbol != NULL && begin_symbol->st_shndx != end_symbol->st_shndx) - wr_message (cat | mc_impact_2 | mc_reloc, where, + wr_message (cat | mc_impact_2 | mc_reloc, &loc, ": %s relocated against different sections (%s and %s).\n", description, file->sec[begin_symbol->st_shndx].name, diff --git a/dwarflint/check_debug_loc_range.hh b/dwarflint/check_debug_loc_range.hh index 442191e63..9e552a5af 100644 --- a/dwarflint/check_debug_loc_range.hh +++ b/dwarflint/check_debug_loc_range.hh @@ -93,10 +93,10 @@ bool check_location_expression (dwarf_version const *ver, uint64_t init_off, struct relocation_data *reloc, size_t length, - struct where *wh); + locus const &loc); -void check_range_relocations (enum message_category cat, - struct where *where, +void check_range_relocations (locus const &loc, + enum message_category cat, struct elf_file const *file, GElf_Sym *begin_symbol, GElf_Sym *end_symbol, diff --git a/dwarflint/check_debug_pub.cc b/dwarflint/check_debug_pub.cc index 4890a7cb5..4ce6999d4 100644 --- a/dwarflint/check_debug_pub.cc +++ b/dwarflint/check_debug_pub.cc @@ -23,6 +23,10 @@ Network licensing program, please visit www.openinventionnetwork.com . */ +#ifdef HAVE_CONFIG_H +# include +#endif + #include "check_debug_pub.hh" #include "check_debug_info.hh" #include "sections.hh" @@ -108,7 +112,7 @@ check_debug_pub::check_pub_structural () wr_error (&where, ": can't read table length.\n"); return false; } - if (!read_size_extra (&ctx, size32, &size, &offset_size, &where)) + if (!read_size_extra (&ctx, size32, &size, &offset_size, where)) return false; { diff --git a/dwarflint/check_die_decl_call.cc b/dwarflint/check_die_decl_call.cc index 7bddad0d7..05f4b726f 100644 --- a/dwarflint/check_die_decl_call.cc +++ b/dwarflint/check_die_decl_call.cc @@ -64,19 +64,19 @@ namespace decl_file = attrs.find (DW_AT_decl_file); if (decl_column != attrs.end () && decl_line == attrs.end ()) - wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal) + wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal) .id (descriptor ()) << elfutils::dwarf::tags::name (entry.tag ()) << " has decl_column, but NOT decl_line" << std::endl; if (decl_line != attrs.end () && decl_file == attrs.end ()) - wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal) + wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal) .id (descriptor ()) << elfutils::dwarf::tags::name (entry.tag ()) << " has decl_line, but NOT decl_file" << std::endl; if (decl_file != attrs.end () && decl_line == attrs.end ()) - wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal) + wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal) .id (descriptor ()) << elfutils::dwarf::tags::name (entry.tag ()) << " has decl_file, but NOT decl_line" << std::endl; @@ -90,19 +90,19 @@ namespace call_file = attrs.find (DW_AT_call_file); if (call_column != attrs.end () && call_line == attrs.end ()) - wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal) + wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal) .id (descriptor ()) << elfutils::dwarf::tags::name (entry.tag ()) << " has call_column, but NOT call_line" << std::endl; if (call_line != attrs.end () && call_file == attrs.end ()) - wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal) + wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal) .id (descriptor ()) << elfutils::dwarf::tags::name (entry.tag ()) << " has call_line, but NOT call_file" << std::endl; if (call_file != attrs.end () && call_line == attrs.end ()) - wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal) + wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal) .id (descriptor ()) << elfutils::dwarf::tags::name (entry.tag ()) << " has call_file, but NOT call_line" << std::endl; diff --git a/dwarflint/check_die_line_info.cc b/dwarflint/check_die_line_info.cc index d30453216..4f19113a7 100644 --- a/dwarflint/check_die_line_info.cc +++ b/dwarflint/check_die_line_info.cc @@ -98,7 +98,7 @@ namespace } if (! found) - wr_message (to_where (entry), mc_impact_3 | mc_acc_suboptimal) + wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal) .id (descriptor ()) << elfutils::dwarf::tags::name (entry.tag ()) << " " << dwarf::attributes::name (pc.first) << "=0x" diff --git a/dwarflint/check_die_tree.cc b/dwarflint/check_die_tree.cc index 0e0b38d49..5aeea9eb5 100644 --- a/dwarflint/check_die_tree.cc +++ b/dwarflint/check_die_tree.cc @@ -97,7 +97,7 @@ public: r += reason; } - wr_error (to_where (*a_d_it)) + wr_error (die_locus (*a_d_it)) << "A check failed: " << (_m_cd->name () ?: "(nil)") << r << std::endl; } diff --git a/dwarflint/check_duplicate_DW_tag_variable.cc b/dwarflint/check_duplicate_DW_tag_variable.cc index 838e3f693..f916ac037 100644 --- a/dwarflint/check_duplicate_DW_tag_variable.cc +++ b/dwarflint/check_duplicate_DW_tag_variable.cc @@ -108,14 +108,14 @@ namespace varinfo &i = old->second; if ((declaration && i.decl != children.end ()) || (!declaration && i.def != children.end ())) - wr_message (to_where (*jt), mc_impact_3 | mc_die_other) + wr_message (die_locus (*jt), mc_impact_3 | mc_die_other) .id (descriptor ()) << "Re" << (declaration ? "declaration" : "definition") << " of variable '" << name << "', originally seen at " << pri::ref (declaration ? *i.decl : *i.def) << '.' << std::endl; else - wr_message (to_where (*jt), mc_impact_3 | mc_die_other) + wr_message (die_locus (*jt), mc_impact_3 | mc_die_other) .id (descriptor ()) << "Found " << (declaration ? "declaration" : "definition") diff --git a/dwarflint/check_dups_abstract_origin.cc b/dwarflint/check_dups_abstract_origin.cc index acb4274f8..47297ea7a 100644 --- a/dwarflint/check_dups_abstract_origin.cc +++ b/dwarflint/check_dups_abstract_origin.cc @@ -122,7 +122,7 @@ namespace if ((at2 = m.find ((*at).first)) != m.end () && ! duplicate_ok (entry.tag (), at2->first, attr.first, referree.tag (), at2->second == (*at).second)) - wr_message (to_where (entry), mc_impact_3 | mc_acc_bloat | mc_die_rel) + wr_message (die_locus (entry), mc_impact_3 | mc_acc_bloat | mc_die_rel) .id (descriptor ()) << dwarf::tags::name (entry.tag ()) << " attribute " << dwarf::attributes::name (at2->first) diff --git a/dwarflint/check_expected_trees.cc b/dwarflint/check_expected_trees.cc index a758c7c3f..1b8cb4e97 100644 --- a/dwarflint/check_expected_trees.cc +++ b/dwarflint/check_expected_trees.cc @@ -104,9 +104,7 @@ check_expected_trees::check_expected_trees (checkstack &stack, dwarflint &lint) void operator () (dwarf::compile_unit const &cu, dwarf::debug_info_entry const &parent) { - struct where where = WHERE (sec_info, NULL); - where_reset_1 (&where, cu.offset ()); - where_reset_2 (&where, parent.offset ()); + die_locus where (parent); int parent_tag = parent.tag (); @@ -204,7 +202,7 @@ check_expected_trees::check_expected_trees (checkstack &stack, dwarflint &lint) // XXX more specific class when has it catch (std::runtime_error &exc) { - wr_error (WHERE (sec_info, NULL)) + wr_error (section_locus (sec_info)) << "Exception while checking expected trees: " << exc.what () << std::endl; throw check_base::failed (); diff --git a/dwarflint/check_linkage_external_die.cc b/dwarflint/check_linkage_external_die.cc index d615afaef..74d2ad4be 100644 --- a/dwarflint/check_linkage_external_die.cc +++ b/dwarflint/check_linkage_external_die.cc @@ -133,7 +133,7 @@ namespace && entry.tag () != DW_TAG_union_type) || attrs.find (DW_AT_name) != attrs.end ())) { - wr_message (to_where (entry), + wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal | mc_die_other) .id (descriptor ()) << elfutils::dwarf::tags::name (entry.tag ()) @@ -152,7 +152,7 @@ namespace if (attrs.find (DW_AT_declaration) == attrs.end () && is_external (it)) { - wr_message (to_where (entry), + wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal | mc_die_other) .id (descriptor ()) << elfutils::dwarf::tags::name (entry.tag ()) @@ -165,7 +165,7 @@ namespace { // Global symbol in symbol table, not marked external. // Always bad. - wr_message (to_where (entry), + wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal | mc_die_other) .id (descriptor ()) << elfutils::dwarf::tags::name (entry.tag ()) diff --git a/dwarflint/check_matching_ranges.cc b/dwarflint/check_matching_ranges.cc index 6f2f4eb67..9a006342e 100644 --- a/dwarflint/check_matching_ranges.cc +++ b/dwarflint/check_matching_ranges.cc @@ -63,11 +63,8 @@ check_matching_ranges::check_matching_ranges (checkstack &stack, try { - struct where where_ref = WHERE (sec_info, NULL); struct where where_ar = WHERE (sec_aranges, NULL); - where_ar.ref = &where_ref; struct where where_r = WHERE (sec_ranges, NULL); - where_r.ref = &where_ref; char buf[128]; const dwarf::aranges_map &aranges = dw.aranges (); @@ -75,8 +72,9 @@ check_matching_ranges::check_matching_ranges (checkstack &stack, i != aranges.end (); ++i) { const dwarf::compile_unit &cu = i->first; - where_reset_1 (&where_ref, 0); - where_reset_2 (&where_ref, cu.offset ()); + die_locus where_ref (cu); + where_ar.ref = &where_ref; + where_r.ref = &where_ref; std::set cu_aranges = i->second, @@ -114,7 +112,7 @@ check_matching_ranges::check_matching_ranges (checkstack &stack, // XXX more specific class when has it catch (std::runtime_error &exc) { - wr_error (WHERE (sec_info, NULL)) + wr_error (section_locus (sec_info)) << "Exception while checking matching ranges: " << exc.what () << std::endl; throw check_base::failed (); diff --git a/dwarflint/check_range_out_of_scope.cc b/dwarflint/check_range_out_of_scope.cc index 57b96baf5..cae7c8443 100644 --- a/dwarflint/check_range_out_of_scope.cc +++ b/dwarflint/check_range_out_of_scope.cc @@ -45,7 +45,7 @@ namespace static void recursively_validate (dwarf::compile_unit const &cu, dwarf::debug_info_entry const &die, ranges_t const &ranges, - where const &wh_parent); + locus const &wh_parent); public: static checkdescriptor const *descriptor () { @@ -72,7 +72,7 @@ check_range_out_of_scope::check_range_out_of_scope (checkstack &stack, dwarflint class dwarf::compile_units_type const &cus = dw.compile_units (); ranges_t r; r.push_back (std::make_pair (0, -1)); - where wh = WHERE (sec_info, NULL); + section_locus wh (sec_info); for (dwarf::compile_units_type::const_iterator it = cus.begin (); it != cus.end (); ++it) recursively_validate (*it, *it, r, wh); @@ -80,7 +80,7 @@ check_range_out_of_scope::check_range_out_of_scope (checkstack &stack, dwarflint // XXX more specific class when has it catch (std::runtime_error &exc) { - wr_error (WHERE (sec_info, NULL)) + wr_error (section_locus (sec_info)) << "Exception while checking ranges out of scope: " << exc.what () << std::endl; throw check_base::failed (); @@ -92,11 +92,9 @@ check_range_out_of_scope::recursively_validate (dwarf::compile_unit const &cu, dwarf::debug_info_entry const &die, ranges_t const &ranges, - where const &wh_parent) + locus const &wh_parent) { - where wh = WHERE (sec_info, NULL); - where_reset_1 (&wh, cu.offset ()); - where_reset_2 (&wh, die.offset ()); + die_locus wh (die); ::Dwarf_Addr low_pc = 0; ::Dwarf_Addr high_pc = ::noaddr; diff --git a/dwarflint/check_self_referential_die.cc b/dwarflint/check_self_referential_die.cc index e81560aa6..752fdfbb2 100644 --- a/dwarflint/check_self_referential_die.cc +++ b/dwarflint/check_self_referential_die.cc @@ -65,7 +65,7 @@ namespace { dwarf::debug_info_entry ref = *val.reference (); if (ref.identity () == entry.identity ()) - wr_message (to_where (entry), + wr_message (die_locus (entry), mc_impact_3 | mc_acc_suboptimal | mc_die_rel) .id (descriptor ()) << dwarf::tags::name (entry.tag ()) diff --git a/dwarflint/checked_read.cc b/dwarflint/checked_read.cc index a4df0222a..b2b14682c 100644 --- a/dwarflint/checked_read.cc +++ b/dwarflint/checked_read.cc @@ -39,13 +39,13 @@ bool read_size_extra (struct read_ctx *ctx, uint32_t size32, uint64_t *sizep, - int *offset_sizep, struct where *where) + int *offset_sizep, locus const &loc) { if (size32 == DWARF3_LENGTH_64_BIT) { if (!read_ctx_read_8ubyte (ctx, sizep)) { - wr_error (*where) << "can't read 64bit CU length.\n"; + wr_error (loc) << "can't read 64bit CU length.\n"; return false; } @@ -53,7 +53,7 @@ read_size_extra (struct read_ctx *ctx, uint32_t size32, uint64_t *sizep, } else if (size32 >= DWARF3_LENGTH_MIN_ESCAPE_CODE) { - wr_error (*where) + wr_error (loc) << "unrecognized CU length escape value: " << size32 << ".\n"; return false; } @@ -67,15 +67,13 @@ read_size_extra (struct read_ctx *ctx, uint32_t size32, uint64_t *sizep, } error_code -read_address_size (struct read_ctx *ctx, - bool addr_64, - int *address_sizep, - struct where const *where) +read_address_size (struct read_ctx *ctx, bool addr_64, + int *address_sizep, locus const &loc) { uint8_t address_size; if (!read_ctx_read_ubyte (ctx, &address_size)) { - wr_error (*where) << "can't read address size.\n"; + wr_error (loc) << "can't read address size.\n"; return err_fatal; } @@ -84,16 +82,16 @@ read_address_size (struct read_ctx *ctx, { /* Keep going. Deduce the address size from ELF header, and try to parse it anyway. */ - wr_error (*where) << "invalid address size: " << (int)address_size - << " (only 4 or 8 allowed).\n"; + wr_error (loc) << "invalid address size: " << (int)address_size + << " (only 4 or 8 allowed).\n"; address_size = addr_64 ? 8 : 4; ret = err_nohl; } else if ((address_size == 8) != addr_64) { /* Keep going, we may still be able to parse it. */ - wr_error (*where) << "CU reports address size of " << address_size - << " in " << (addr_64 ? 64 : 32) << "-bit ELF.\n"; + wr_error (loc) << "CU reports address size of " << address_size + << " in " << (addr_64 ? 64 : 32) << "-bit ELF.\n"; ret = err_nohl; } diff --git a/dwarflint/checked_read.hh b/dwarflint/checked_read.hh index 3f4f5984b..8cdecfeaf 100644 --- a/dwarflint/checked_read.hh +++ b/dwarflint/checked_read.hh @@ -38,15 +38,13 @@ enum error_code }; bool read_size_extra (read_ctx *ctx, uint32_t size32, uint64_t *sizep, - int *offset_sizep, where *where); + int *offset_sizep, locus const &loc); /// Read address size and return it via address_sizep and return 0. /// Address size may be 4 or 8; for other values it's set depending or /// addr_64, and err_nohl is returned. -error_code read_address_size (read_ctx *ctx, - bool addr_64, - int *address_sizep, - where const *where); +error_code read_address_size (read_ctx *ctx, bool addr_64, + int *address_sizep, locus const &loc); bool checked_read_uleb128 (read_ctx *ctx, uint64_t *ret, locus const &loc, const char *what); diff --git a/dwarflint/cu_coverage.cc b/dwarflint/cu_coverage.cc index c09ecabda..4f87e0c4f 100644 --- a/dwarflint/cu_coverage.cc +++ b/dwarflint/cu_coverage.cc @@ -23,6 +23,10 @@ Network licensing program, please visit www.openinventionnetwork.com . */ +#ifdef HAVE_CONFIG_H +# include +#endif + #include "cu_coverage.hh" #include "check_debug_info.hh" #include "check_debug_loc_range.hh" diff --git a/dwarflint/die_locus.cc b/dwarflint/die_locus.cc new file mode 100644 index 000000000..1d225645f --- /dev/null +++ b/dwarflint/die_locus.cc @@ -0,0 +1,57 @@ +/* + 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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "die_locus.hh" +#include "pri.hh" + +std::string +cu_locus::format (bool brief) const +{ + std::stringstream ss; + if (!brief) + ss << section_name[sec_info] << ": "; + ss << "CU " << _m_offset; + return ss.str (); +} + +std::string +die_locus::format (bool brief) const +{ + std::stringstream ss; + if (!brief) + ss << section_name[sec_info] << ": "; + + ss << "DIE 0x" << std::hex << _m_offset; + + if (_m_attrib_name != -1) + ss << ", attr. " << pri::attr_name (_m_attrib_name); + + return ss.str (); +} + diff --git a/dwarflint/die_locus.hh b/dwarflint/die_locus.hh new file mode 100644 index 000000000..87f0a0b47 --- /dev/null +++ b/dwarflint/die_locus.hh @@ -0,0 +1,71 @@ +/* + 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 + . */ + +#ifndef _DWARFLINT_DIE_LOCUS_H_ +#define _DWARFLINT_DIE_LOCUS_H_ + +#include "where.h" +#include "../libdw/c++/dwarf" + +class cu_locus + : public clonable_locus +{ + Dwarf_Off _m_offset; +public: + explicit cu_locus (Dwarf_Off offset) + : _m_offset (offset) + {} + + std::string format (bool brief = false) const; +}; + +class die_locus + : public clonable_locus +{ + Dwarf_Off _m_offset; + int _m_attrib_name; + +public: + explicit die_locus (Dwarf_Off offset, int attrib_name = -1) + : _m_offset (offset) + , _m_attrib_name (attrib_name) + {} + + template + explicit die_locus (T const &die, int attrib_name = -1) + : _m_offset (die.offset ()) + , _m_attrib_name (attrib_name) + {} + + void + set_attrib_name (int attrib_name) + { + _m_attrib_name = attrib_name; + } + + std::string format (bool brief = false) const; +}; + +#endif /* _DWARFLINT_DIE_LOCUS_H_ */ diff --git a/dwarflint/highlevel_check.hh b/dwarflint/highlevel_check.hh index 007756a41..66d6e38c2 100644 --- a/dwarflint/highlevel_check.hh +++ b/dwarflint/highlevel_check.hh @@ -31,6 +31,8 @@ #endif #include "checks.hh" +#include "check_debug_info.hh" + #include "../libdw/c++/dwarf" #include "../libdwfl/libdwfl.h" @@ -82,14 +84,4 @@ public: {} }; -template -inline where -to_where (T const &die) -{ - where ret = WHERE (sec_info, NULL); - where_reset_1 (&ret, 0); - where_reset_2 (&ret, die.offset ()); - return ret; -} - #endif//DWARFLINT_CHECKS_HIGH_HH diff --git a/dwarflint/locstats.cc b/dwarflint/locstats.cc index 614563eb4..8a8a05284 100644 --- a/dwarflint/locstats.cc +++ b/dwarflint/locstats.cc @@ -513,10 +513,7 @@ process(Dwarf *c_dw, dwarf const &dw) } catch (::error const &e) { - struct where where = WHERE (sec_info, NULL); - where_reset_1 (&where, it.cu ().offset ()); - where_reset_2 (&where, die.offset ()); - std::cerr << "error: " << where << ": " + std::cerr << "error: " << die_locus (die) << ": " << e.what () << '.' << std::endl; continue; } diff --git a/dwarflint/lowlevel_checks.cc b/dwarflint/lowlevel_checks.cc index 987c56dfb..bbfe6764a 100644 --- a/dwarflint/lowlevel_checks.cc +++ b/dwarflint/lowlevel_checks.cc @@ -23,6 +23,10 @@ Network licensing program, please visit www.openinventionnetwork.com . */ +#ifdef HAVE_CONFIG_H +# include +#endif + #include "lowlevel_checks.hh" #include "sections.hh" #include "check_debug_info.hh" diff --git a/dwarflint/pri.cc b/dwarflint/pri.cc index de01463f9..6f289ab8d 100644 --- a/dwarflint/pri.cc +++ b/dwarflint/pri.cc @@ -64,3 +64,10 @@ pri::operator << (std::ostream &os, pri::range const &obj) return os << "[" << pri::addr (obj.start) << ", " << pri::addr (obj.end) << ")"; } + +std::string +pri::attr_name (int name) +{ + assert (name != -1); + return elfutils::dwarf::attributes::name (name); +} diff --git a/dwarflint/pri.hh b/dwarflint/pri.hh index 67705f40c..cef1ba9a6 100644 --- a/dwarflint/pri.hh +++ b/dwarflint/pri.hh @@ -114,6 +114,8 @@ namespace pri friend std::ostream &operator << (std::ostream &os, range const &obj); }; std::ostream &operator << (std::ostream &os, range const &obj); + + std::string attr_name (int name); } #endif//DWARFLINT_PRI_H diff --git a/dwarflint/reloc.cc b/dwarflint/reloc.cc index f89cd6711..8cf23998b 100644 --- a/dwarflint/reloc.cc +++ b/dwarflint/reloc.cc @@ -414,7 +414,7 @@ read_rel (struct elf_file *file, : (is_rela ? sizeof (Elf32_Rela) : sizeof (Elf32_Rel)); size_t count = reldata->d_size / entrysize; - struct where parent = WHERE (sec->id, NULL); + section_locus parent (sec->id); for (unsigned i = 0; i < count; ++i) { diff --git a/dwarflint/tests/run-bad.sh b/dwarflint/tests/run-bad.sh index 54b10f6a9..fa06499da 100755 --- a/dwarflint/tests/run-bad.sh +++ b/dwarflint/tests/run-bad.sh @@ -49,7 +49,7 @@ EOF testrun_compare ./dwarflint empty-1 <). error: .rela 0x2500 of .debug_info: invalid relocation 2560 (). error: .rela 0x3600 of .debug_info: invalid relocation 256 (). warning: .debug_info: CU 0: abbrev table offset seems to lack a relocation -warning: .debug_info: DIE 0xb (abbr. 0x0, attr. producer): strp seems to lack a relocation -warning: .debug_info: DIE 0xb (abbr. 0x0, attr. comp_dir): strp seems to lack a relocation -warning: .debug_info: DIE 0xb (abbr. 0x0, attr. stmt_list): data4 seems to lack a relocation +warning: .debug_info: DIE 0xb, attr. producer: strp seems to lack a relocation +warning: .debug_info: DIE 0xb, attr. comp_dir: strp seems to lack a relocation +warning: .debug_info: DIE 0xb, attr. stmt_list: data4 seems to lack a relocation warning: .debug_info: DIE 0xb: DW_AT_low_pc value not below DW_AT_high_pc. 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. 0x0, attr. stmt_list): unresolved reference to .debug_line table 0x0. +error: .debug_info: DIE 0xb, attr. stmt_list: unresolved reference to .debug_line table 0x0. EOF testrun_compare ./dwarflint garbage-12 <