From: Petr Machata Date: Mon, 30 Nov 2009 07:19:48 +0000 (+0100) Subject: dwarflint: Avoid some use of C interfaces X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8eff356b98e9ae79f5efdcd119d4246bc6141d52;p=thirdparty%2Felfutils.git dwarflint: Avoid some use of C interfaces --- diff --git a/src/dwarflint/check_debug_info.cc b/src/dwarflint/check_debug_info.cc index 623dbc30a..dda8b5a13 100644 --- a/src/dwarflint/check_debug_info.cc +++ b/src/dwarflint/check_debug_info.cc @@ -954,11 +954,12 @@ namespace return got_die ? 1 : 0; } + bool check_cu_structural (struct elf_file *file, struct read_ctx *ctx, struct cu *const cu, - struct abbrev_table *abbrev_chain, + check_debug_abbrev::abbrev_map &abbrev_tables, Elf_Data *strings, struct coverage *strings_coverage, struct relocation_data *reloc, @@ -972,30 +973,28 @@ namespace assert (ver != NULL); /* Look up Abbrev table for this CU. */ - struct abbrev_table *abbrevs = abbrev_chain; - for (; abbrevs != NULL; abbrevs = abbrevs->next) - if (abbrevs->offset == cu->head->abbrev_offset) - break; - - if (abbrevs == NULL) + check_debug_abbrev::abbrev_map::iterator abbrev_it + = abbrev_tables.find (cu->head->abbrev_offset); + if (abbrev_it == abbrev_tables.end ()) { - wr_error (&cu->head->where, - ": couldn't find abbrev section with offset %" PRId64 ".\n", - cu->head->abbrev_offset); + wr_error (cu->head->where) + << "couldn't find abbrev section with offset " + << pri::addr (cu->head->abbrev_offset) << '.' << std::endl; return false; } + struct abbrev_table &abbrevs = abbrev_it->second; /* Read DIEs. */ struct ref_record local_die_refs; WIPE (local_die_refs); cu->cudie_offset = read_ctx_get_offset (ctx) + cu->head->offset; - if (read_die_chain (ver, file, ctx, cu, abbrevs, strings, + if (read_die_chain (ver, file, ctx, cu, &abbrevs, strings, &local_die_refs, strings_coverage, (reloc != NULL && reloc->size > 0) ? reloc : NULL, cu_coverage) < 0) { - abbrevs->skip_check = true; + abbrevs.skip_check = true; retval = false; } else if (!check_die_references (cu, &local_die_refs)) @@ -1004,149 +1003,148 @@ namespace ref_record_free (&local_die_refs); return retval; } +} - struct cu * - check_info_structural (struct elf_file *file, - struct sec *sec, - struct abbrev_table *abbrev_chain, - Elf_Data *strings, - struct cu_coverage *cu_coverage, - std::vector const &cu_headers) - { - struct ref_record die_refs; - WIPE (die_refs); +read_cu_headers::read_cu_headers (dwarflint &lint) + : _m_sec_info (lint.check (_m_sec_info)) + , cu_headers (read_info_headers (&_m_sec_info->file, + &_m_sec_info->sect, + _m_sec_info->reldata ())) +{ +} - struct cu *cu_chain = NULL; - bool success = true; +struct cu * +check_debug_info::check_info_structural (struct elf_file *file, + struct sec *sec, + Elf_Data *strings) +{ + std::vector const &cu_headers = _m_cu_headers->cu_headers; + struct ref_record die_refs; + WIPE (die_refs); - struct coverage strings_coverage_mem, *strings_coverage = NULL; - if (strings != NULL && check_category (mc_strings)) - { - WIPE (strings_coverage_mem); - strings_coverage = &strings_coverage_mem; - } + struct cu *cu_chain = NULL; + bool success = true; - struct relocation_data *reloc = sec->rel.size > 0 ? &sec->rel : NULL; - if (reloc != NULL) - relocation_reset (reloc); + struct coverage strings_coverage_mem, *strings_coverage = NULL; + if (strings != NULL && check_category (mc_strings)) + { + WIPE (strings_coverage_mem); + strings_coverage = &strings_coverage_mem; + } - struct read_ctx ctx; - read_ctx_init (&ctx, sec->data, file->other_byte_order); - for (std::vector ::const_iterator it = cu_headers.begin (); - it != cu_headers.end (); ++it) - { - cu_head const &head = *it; - where const &where = head.where; - struct cu *cur = (cu *)xcalloc (1, sizeof (*cur)); - cur->head = &head; - cur->low_pc = (uint64_t)-1; - cur->next = cu_chain; - cu_chain = cur; - - assert (read_ctx_need_data (&ctx, head.total_size)); - - // Make CU context begin just before the CU length, so that - // DIE offsets are computed correctly. - struct read_ctx cu_ctx; - const unsigned char *cu_end = ctx.ptr + head.total_size; - read_ctx_init_sub (&cu_ctx, &ctx, ctx.ptr, cu_end); - cu_ctx.ptr += head.head_size; - - if (!check_cu_structural (file, &cu_ctx, cur, abbrev_chain, - strings, strings_coverage, reloc, - cu_coverage)) - { - success = false; - break; - } + struct relocation_data *reloc = sec->rel.size > 0 ? &sec->rel : NULL; + if (reloc != NULL) + relocation_reset (reloc); - if (cu_ctx.ptr != cu_ctx.end - && !check_zero_padding (&cu_ctx, mc_info, &where)) - { - // Garbage coordinates: - uint64_t start - = read_ctx_get_offset (&ctx) + read_ctx_get_offset (&cu_ctx); - uint64_t end = read_ctx_get_offset (&ctx) + head.total_size; - wr_message_padding_n0 (mc_info, &where, start, end); - } + struct read_ctx ctx; + read_ctx_init (&ctx, sec->data, file->other_byte_order); + for (std::vector ::const_iterator it = cu_headers.begin (); + it != cu_headers.end (); ++it) + { + cu_head const &head = *it; + where const &where = head.where; + cu *cur = (cu *)xcalloc (1, sizeof (struct cu)); + cur->head = &head; + cur->low_pc = (uint64_t)-1; + cur->next = cu_chain; + cu_chain = cur; + + assert (read_ctx_need_data (&ctx, head.total_size)); + + // Make CU context begin just before the CU length, so that + // DIE offsets are computed correctly. + struct read_ctx cu_ctx; + const unsigned char *cu_end = ctx.ptr + head.total_size; + read_ctx_init_sub (&cu_ctx, &ctx, ctx.ptr, cu_end); + cu_ctx.ptr += head.head_size; + + if (!check_cu_structural (file, &cu_ctx, cur, _m_abbrevs->abbrevs, + strings, strings_coverage, reloc, + &cu_cov)) + { + success = false; + break; + } - int i = read_ctx_skip (&ctx, head.total_size); - assert (i); - } + if (cu_ctx.ptr != cu_ctx.end + && !check_zero_padding (&cu_ctx, mc_info, &where)) + { + // Garbage coordinates: + uint64_t start + = read_ctx_get_offset (&ctx) + read_ctx_get_offset (&cu_ctx); + uint64_t end = read_ctx_get_offset (&ctx) + head.total_size; + wr_message_padding_n0 (mc_info, &where, start, end); + } - if (success) - { - if (ctx.ptr != ctx.end) - /* Did we read up everything? */ - { - where wh = WHERE (sec_info, NULL); - wr_message (cat (mc_die_other, mc_impact_4), &wh, - ": CU lengths don't exactly match Elf_Data contents."); - } - else - /* Did we consume all the relocations? */ - relocation_skip_rest (&sec->rel, sec->id); - - /* If we managed to read up everything, now do abbrev usage - analysis. */ - for (struct abbrev_table *abbrevs = abbrev_chain; - abbrevs != NULL; abbrevs = abbrevs->next) - if (abbrevs->used && !abbrevs->skip_check) - for (size_t i = 0; i < abbrevs->size; ++i) - if (!abbrevs->abbr[i].used) - wr_message (mc_impact_3 | mc_acc_bloat | mc_abbrevs, - &abbrevs->abbr[i].where, - ": abbreviation is never used.\n"); - } + int i = read_ctx_skip (&ctx, head.total_size); + assert (i); + } + if (success) + { + if (ctx.ptr != ctx.end) + /* Did we read up everything? */ + { + where wh = WHERE (sec_info, NULL); + wr_message (cat (mc_die_other, mc_impact_4), &wh, + ": CU lengths don't exactly match Elf_Data contents."); + } + else + /* Did we consume all the relocations? */ + relocation_skip_rest (&sec->rel, sec->id); + + /* If we managed to read up everything, now do abbrev usage + analysis. */ + for (check_debug_abbrev::abbrev_map::const_iterator it + = _m_abbrevs->abbrevs.begin (); + it != _m_abbrevs->abbrevs.end (); ++it) + if (it->second.used && !it->second.skip_check) + for (size_t i = 0; i < it->second.size; ++i) + if (!it->second.abbr[i].used) + wr_message (it->second.abbr[i].where, + cat (mc_impact_3, mc_acc_bloat, mc_abbrevs)) + << ": abbreviation is never used." << std::endl; + } - /* We used to check that all CUs have the same address size. Now - that we validate address_size of each CU against the ELF header, - that's not necessary anymore. */ - bool references_sound = check_global_die_references (cu_chain); - ref_record_free (&die_refs); + /* We used to check that all CUs have the same address size. Now + that we validate address_size of each CU against the ELF header, + that's not necessary anymore. */ - if (strings_coverage != NULL) - { - if (success) - { - struct hole_info info = {sec_str, mc_strings, strings->d_buf, 0}; - coverage_find_holes (strings_coverage, 0, strings->d_size, - found_hole, &info); - } - coverage_free (strings_coverage); - } + bool references_sound = check_global_die_references (cu_chain); + ref_record_free (&die_refs); - if (!success || !references_sound) - { - cu_free (cu_chain); - cu_chain = NULL; - } + if (strings_coverage != NULL) + { + if (success) + { + struct hole_info info = {sec_str, mc_strings, strings->d_buf, 0}; + coverage_find_holes (strings_coverage, 0, strings->d_size, + found_hole, &info); + } + coverage_free (strings_coverage); + } - /* Reverse the chain, so that it's organized "naturally". Has - significant impact on performance when handling loc_ref and - range_ref fields in loc/range validation. */ - struct cu *last = NULL; - for (struct cu *it = cu_chain; it != NULL; ) - { - struct cu *next = it->next; - it->next = last; - last = it; - it = next; - } - cu_chain = last; + if (!success || !references_sound) + { + cu_free (cu_chain); + cu_chain = NULL; + } - return cu_chain; - } -} + /* Reverse the chain, so that it's organized "naturally". Has + significant impact on performance when handling loc_ref and + range_ref fields in loc/range validation. */ + struct cu *last = NULL; + for (struct cu *it = cu_chain; it != NULL; ) + { + struct cu *next = it->next; + it->next = last; + last = it; + it = next; + } + cu_chain = last; -read_cu_headers::read_cu_headers (dwarflint &lint) - : _m_sec_info (lint.check (_m_sec_info)) - , cu_headers (read_info_headers (&_m_sec_info->file, - &_m_sec_info->sect, - _m_sec_info->reldata ())) -{ + return cu_chain; } check_debug_info::check_debug_info (dwarflint &lint) @@ -1158,11 +1156,8 @@ check_debug_info::check_debug_info (dwarflint &lint) { memset (&cu_cov, 0, sizeof (cu_cov)); - cu *chain = check_info_structural - (&_m_sec_info->file, &_m_sec_info->sect, - &_m_abbrevs->abbrevs.begin ()->second, - _m_sec_str->sect.data, &cu_cov, - _m_cu_headers->cu_headers); + cu *chain = check_info_structural (&_m_sec_info->file, &_m_sec_info->sect, + _m_sec_str->sect.data); if (chain == NULL) throw check_base::failed (); diff --git a/src/dwarflint/checks-low.hh b/src/dwarflint/checks-low.hh index de6510765..b6905d14d 100644 --- a/src/dwarflint/checks-low.hh +++ b/src/dwarflint/checks-low.hh @@ -101,6 +101,10 @@ class check_debug_info check_debug_abbrev *_m_abbrevs; read_cu_headers *_m_cu_headers; + struct cu *check_info_structural (elf_file *file, + struct sec *sec, + Elf_Data *strings); + public: // The check pass adds all low_pc/high_pc ranges loaded from DIE // tree into this following cu_cov structure. If it finds any