From c6c1318e274c1494ac361997ee424d1ad5c7adc7 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Mon, 30 Nov 2009 18:06:53 +0100 Subject: [PATCH] dwarflint: Extract .debug_pub checks into check_debug_pub.cc --- src/Makefile.am | 1 + src/dwarflint/check_debug_info.cc | 11 ++ src/dwarflint/check_debug_info.hh | 2 + src/dwarflint/check_debug_pub.cc | 201 ++++++++++++++++++++++++++++++ src/dwarflint/checks-low.cc | 25 ---- src/dwarflint/low.c | 162 ------------------------ src/dwarflint/low.h | 3 - src/dwarflint/pri.hh | 4 + 8 files changed, 219 insertions(+), 190 deletions(-) create mode 100644 src/dwarflint/check_debug_pub.cc diff --git a/src/Makefile.am b/src/Makefile.am index 2a9aef337..086e5c0e8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -99,6 +99,7 @@ dwarflint_SOURCES = dwarfstrings.c \ dwarflint/check_debug_abbrev.cc dwarflint/check_debug_abbrev.hh dwarflint/check_debug_abbrev.ii \ dwarflint/check_debug_info.cc dwarflint/check_debug_info.hh dwarflint/check_debug_info.ii \ dwarflint/check_debug_line.cc \ + dwarflint/check_debug_pub.cc \ dwarflint/check_debug_loc_range.cc dwarflint/check_debug_loc_range.hh \ dwarflint/check_matching_ranges.cc \ dwarflint/check_range_out_of_scope.cc \ diff --git a/src/dwarflint/check_debug_info.cc b/src/dwarflint/check_debug_info.cc index d4642b2d2..2f1ff8f35 100644 --- a/src/dwarflint/check_debug_info.cc +++ b/src/dwarflint/check_debug_info.cc @@ -1180,3 +1180,14 @@ check_debug_info::~check_debug_info () } coverage_free (&cu_cov.cov); } + +cu * +check_debug_info::find_cu (::Dwarf_Off offset) +{ + for (std::vector::iterator it = cus.begin (); + it != cus.end (); ++it) + if (it->head->offset == offset) + return &*it; + + return NULL; +} diff --git a/src/dwarflint/check_debug_info.hh b/src/dwarflint/check_debug_info.hh index 844bc5381..1f8b7bf86 100644 --- a/src/dwarflint/check_debug_info.hh +++ b/src/dwarflint/check_debug_info.hh @@ -72,6 +72,8 @@ public: explicit check_debug_info (dwarflint &lint); ~check_debug_info (); + + cu *find_cu (::Dwarf_Off offset); }; static reg reg_debug_info; diff --git a/src/dwarflint/check_debug_pub.cc b/src/dwarflint/check_debug_pub.cc new file mode 100644 index 000000000..29d2b95e0 --- /dev/null +++ b/src/dwarflint/check_debug_pub.cc @@ -0,0 +1,201 @@ +#include "checks-low.hh" +#include "check_debug_info.hh" +#include "pri.hh" + +namespace +{ + template + class check_debug_pub + : public check > + { + section *_m_sec; + elf_file const &_m_file; + + bool check_pub_structural (check_debug_info *cus); + + public: + explicit check_debug_pub (dwarflint &lint) + : _m_sec (lint.check (_m_sec)) + , _m_file (_m_sec->file) + { + check_pub_structural (lint.toplev_check ()); + } + }; + + template + struct where xwhere (A a, B b) + { + return WHERE (a, b); + } +} + +template +bool +check_debug_pub::check_pub_structural (check_debug_info *cus) +{ + struct read_ctx ctx; + read_ctx_init (&ctx, _m_sec->sect.data, _m_file.other_byte_order); + bool retval = true; + + while (!read_ctx_eof (&ctx)) + { + struct where where = WHERE (_m_sec->sect.id, NULL); + where_reset_1 (&where, read_ctx_get_offset (&ctx)); + const unsigned char *set_begin = ctx.ptr; + + /* Size. */ + uint32_t size32; + uint64_t size; + int offset_size; + if (!read_ctx_read_4ubyte (&ctx, &size32)) + { + wr_error (&where, ": can't read table length.\n"); + return false; + } + if (!read_size_extra (&ctx, size32, &size, &offset_size, &where)) + return false; + + { + struct read_ctx sub_ctx; + const unsigned char *set_end = ctx.ptr + size; + if (!read_ctx_init_sub (&sub_ctx, &ctx, set_begin, set_end)) + goto not_enough; + sub_ctx.ptr = ctx.ptr; + + /* Version. */ + uint16_t version; + if (!read_ctx_read_2ubyte (&sub_ctx, &version)) + { + wr_error (&where, ": can't read set version.\n"); + retval = false; + goto next; + } + if (!supported_version (version, 1, &where, 2)) + { + retval = false; + goto next; + } + + /* CU offset. */ + uint64_t cu_offset; /* Offset of related CU. */ + uint64_t ctx_offset = sub_ctx.ptr - ctx.begin; + if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &cu_offset)) + { + wr_error (&where, ": can't read debug info offset.\n"); + retval = false; + goto next; + } + + struct relocation *rel; + if ((rel = relocation_next (&_m_sec->sect.rel, ctx_offset, + &where, skip_mismatched))) + relocate_one (&_m_file, &_m_sec->sect.rel, rel, offset_size, + &cu_offset, &where, sec_info, NULL); + else if (_m_file.ehdr.e_type == ET_REL) + wr_message (mc_impact_2 | mc_pubtables | mc_reloc | mc_header, &where, + PRI_LACK_RELOCATION, "debug info offset"); + + struct cu *cu = NULL; + if (cus != NULL && (cu = cus->find_cu (cu_offset)) == NULL) + wr_error (where) + << "unresolved reference to " << pri::CU (cu_offset) + << '.' << std::endl; + if (cu != NULL) + { + where.ref = &cu->head->where; + bool *has = _m_sec->sect.id == sec_pubnames + ? &cu->has_pubnames : &cu->has_pubtypes; + if (*has) + wr_message (mc_impact_2 | mc_pubtables | mc_header, &where, + ": there has already been section for this CU.\n"); + else + *has = true; + } + + /* Covered length. */ + uint64_t cu_len; + if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &cu_len)) + { + wr_error (&where, ": can't read covered length.\n"); + retval = false; + goto next; + } + if (cu != NULL && cu_len != cu->head->total_size) + { + wr_error (where) + << "the table covers length " << cu_len << " but CU has length " + << cu->head->total_size << '.' << std::endl; + retval = false; + goto next; + } + + /* Records... */ + while (!read_ctx_eof (&sub_ctx)) + { + ctx_offset = sub_ctx.ptr - ctx.begin; + where_reset_2 (&where, ctx_offset); + + uint64_t offset; + if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &offset)) + { + wr_error (&where, ": can't read offset field.\n"); + retval = false; + goto next; + } + if (offset == 0) + break; + + if (cu != NULL + && !addr_record_has_addr (&cu->die_addrs, + offset + cu->head->offset)) + { + wr_error (where) + << "unresolved reference to " << pri::DIE (offset) + << '.' << std::endl; + retval = false; + goto next; + } + + uint8_t c; + do + if (!read_ctx_read_ubyte (&sub_ctx, &c)) + { + wr_error (&where, ": can't read symbol name.\n"); + retval = false; + goto next; + } + while (c); + } + + struct where wh = WHERE (_m_sec->sect.id, NULL); + if (sub_ctx.ptr != sub_ctx.end + && !check_zero_padding (&sub_ctx, mc_pubtables, &wh)) + { + wh = WHERE (_m_sec->sect.id, NULL); + wr_message_padding_n0 (mc_pubtables | mc_error, &wh, + read_ctx_get_offset (&sub_ctx), + read_ctx_get_offset (&sub_ctx) + size); + retval = false; + } + } + + next: + if (read_ctx_skip (&ctx, size)) + continue; + + not_enough: + wr_error (&where, PRI_NOT_ENOUGH, "next set"); + return false; + } + + if (retval) + relocation_skip_rest (&_m_sec->sect.rel, _m_sec->sect.id); + + return retval; +} + +namespace +{ + reg > reg_debug_pubnames; + reg > reg_debug_pubtypes; +} diff --git a/src/dwarflint/checks-low.cc b/src/dwarflint/checks-low.cc index 16f377bec..4e07beb7f 100644 --- a/src/dwarflint/checks-low.cc +++ b/src/dwarflint/checks-low.cc @@ -487,28 +487,3 @@ check_debug_aranges::check_debug_aranges (dwarflint &lint) cov)) throw check_base::failed (); } - -namespace -{ - template - class check_debug_pub - : public check > - { - section *_m_sec; - check_debug_info *_m_cus; - - public: - explicit check_debug_pub (dwarflint &lint) - : _m_sec (lint.check (_m_sec)) - , _m_cus (lint.check (_m_cus)) - { - if (!check_pub_structural (&_m_sec->file, - &_m_sec->sect, - &_m_cus->cus.front ())) - throw check_base::failed (); - } - }; - - reg > reg_debug_pubnames; - reg > reg_debug_pubtypes; -} diff --git a/src/dwarflint/low.c b/src/dwarflint/low.c index a4b0fc59c..51ba46859 100644 --- a/src/dwarflint/low.c +++ b/src/dwarflint/low.c @@ -556,168 +556,6 @@ check_aranges_structural (struct elf_file *file, return retval; } -bool -check_pub_structural (struct elf_file *file, - struct sec *sec, - struct cu *cu_chain) -{ - struct read_ctx ctx; - read_ctx_init (&ctx, sec->data, file->other_byte_order); - bool retval = true; - - while (!read_ctx_eof (&ctx)) - { - struct where where = WHERE (sec->id, NULL); - where_reset_1 (&where, read_ctx_get_offset (&ctx)); - const unsigned char *set_begin = ctx.ptr; - - /* Size. */ - uint32_t size32; - uint64_t size; - int offset_size; - if (!read_ctx_read_4ubyte (&ctx, &size32)) - { - wr_error (&where, ": can't read table length.\n"); - return false; - } - if (!read_size_extra (&ctx, size32, &size, &offset_size, &where)) - return false; - - struct read_ctx sub_ctx; - const unsigned char *set_end = ctx.ptr + size; - if (!read_ctx_init_sub (&sub_ctx, &ctx, set_begin, set_end)) - { - not_enough: - wr_error (&where, PRI_NOT_ENOUGH, "next set"); - return false; - } - sub_ctx.ptr = ctx.ptr; - - /* Version. */ - uint16_t version; - if (!read_ctx_read_2ubyte (&sub_ctx, &version)) - { - wr_error (&where, ": can't read set version.\n"); - retval = false; - goto next; - } - if (!supported_version (version, 1, &where, 2)) - { - retval = false; - goto next; - } - - /* CU offset. */ - uint64_t cu_offset; /* Offset of related CU. */ - uint64_t ctx_offset = sub_ctx.ptr - ctx.begin; - if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &cu_offset)) - { - wr_error (&where, ": can't read debug info offset.\n"); - retval = false; - goto next; - } - - struct relocation *rel; - if ((rel = relocation_next (&sec->rel, ctx_offset, - &where, skip_mismatched))) - relocate_one (file, &sec->rel, rel, offset_size, - &cu_offset, &where, sec_info, NULL); - else if (file->ehdr.e_type == ET_REL) - wr_message (mc_impact_2 | mc_pubtables | mc_reloc | mc_header, &where, - PRI_LACK_RELOCATION, "debug info offset"); - - struct cu *cu = NULL; - if (cu_chain != NULL && (cu = cu_find_cu (cu_chain, cu_offset)) == NULL) - wr_error (&where, ": unresolved reference to " PRI_CU ".\n", cu_offset); - if (cu != NULL) - { - where.ref = &cu->head->where; - bool *has = sec->id == sec_pubnames - ? &cu->has_pubnames : &cu->has_pubtypes; - if (*has) - wr_message (mc_impact_2 | mc_pubtables | mc_header, &where, - ": there has already been section for this CU.\n"); - else - *has = true; - } - - /* Covered length. */ - uint64_t cu_len; - if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &cu_len)) - { - wr_error (&where, ": can't read covered length.\n"); - retval = false; - goto next; - } - if (cu != NULL && cu_len != cu->head->total_size) - { - wr_error (&where, - ": the table covers length %" PRId64 - " but CU has length %" PRId64 ".\n", - cu_len, cu->head->total_size); - retval = false; - goto next; - } - - /* Records... */ - while (!read_ctx_eof (&sub_ctx)) - { - ctx_offset = sub_ctx.ptr - ctx.begin; - where_reset_2 (&where, ctx_offset); - - uint64_t offset; - if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &offset)) - { - wr_error (&where, ": can't read offset field.\n"); - retval = false; - goto next; - } - if (offset == 0) - break; - - if (cu != NULL - && !addr_record_has_addr (&cu->die_addrs, - offset + cu->head->offset)) - { - wr_error (&where, - ": unresolved reference to " PRI_DIE ".\n", offset); - retval = false; - goto next; - } - - uint8_t c; - do - if (!read_ctx_read_ubyte (&sub_ctx, &c)) - { - wr_error (&where, ": can't read symbol name.\n"); - retval = false; - goto next; - } - while (c); - } - - if (sub_ctx.ptr != sub_ctx.end - && !check_zero_padding (&sub_ctx, mc_pubtables, - &WHERE (sec->id, NULL))) - { - wr_message_padding_n0 (mc_pubtables | mc_error, - &WHERE (sec->id, NULL), - read_ctx_get_offset (&sub_ctx), - read_ctx_get_offset (&sub_ctx) + size); - retval = false; - } - - next: - if (!read_ctx_skip (&ctx, size)) - goto not_enough; - } - - if (retval) - relocation_skip_rest (&sec->rel, sec->id); - - return retval; -} - static GElf_Rela * get_rel_or_rela (Elf_Data *data, int ndx, GElf_Rela *dst, size_t type) diff --git a/src/dwarflint/low.h b/src/dwarflint/low.h index db46b98b8..c415310f4 100644 --- a/src/dwarflint/low.h +++ b/src/dwarflint/low.h @@ -146,9 +146,6 @@ extern "C" struct sec *sec, struct cu *cu_chain, struct coverage *coverage); - extern bool check_pub_structural (struct elf_file *file, - struct sec *sec, - struct cu *cu_chain); extern bool check_line_structural (struct elf_file *file, struct sec *sec, struct addr_record *line_tables); diff --git a/src/dwarflint/pri.hh b/src/dwarflint/pri.hh index 5ce28870d..eb4d65015 100644 --- a/src/dwarflint/pri.hh +++ b/src/dwarflint/pri.hh @@ -96,6 +96,10 @@ namespace pri DIE (Dwarf_Off off) : hex (off, "DIE ") {} }; + struct CU: public hex { + CU (Dwarf_Off off) : hex (off, "CU ") {} + }; + class range { Dwarf_Off start; -- 2.47.3