From f89036d24e0207170244be611daa3f7a6b4e659c Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 21 Oct 2009 21:28:49 +0200 Subject: [PATCH] dwarflint: Move .debug_line checks to new infrastructure --- src/dwarflint/checks-low.cc | 81 ++++++++++++++++++++++++++++++++++--- src/dwarflint/checks-low.hh | 3 +- src/dwarflint/checks.hh | 8 ++-- src/dwarflint/low.c | 21 ++-------- src/dwarflint/low.h | 20 +-------- src/dwarflint/main.cc | 28 ------------- 6 files changed, 86 insertions(+), 75 deletions(-) diff --git a/src/dwarflint/checks-low.cc b/src/dwarflint/checks-low.cc index 6e870ff2d..1f6ac8fb1 100644 --- a/src/dwarflint/checks-low.cc +++ b/src/dwarflint/checks-low.cc @@ -32,6 +32,7 @@ #include #include #include +#include struct secentry { @@ -256,6 +257,13 @@ load_sections::load_sections (dwarflint &lint) elf_file_init (&file, lint.elf ()); } +load_sections::~load_sections () +{ + if (file.ebl != NULL) + ebl_closebackend (file.ebl); + free (file.sec); +} + sec & section_base::get_sec_or_throw (section_id secid) { @@ -310,8 +318,26 @@ check_debug_info::check_debug_info (dwarflint &lint) for (cu *cu = chain; cu != NULL; cu = cu->next) cus.push_back (*cu); - // cu_free (chain); xxx - cu_chain = chain; + + // re-link CUs so that they form a chain again. This is to + // interface with C-level code. The last CU's next is null, so we + // don't have to re-link it. + cu *last = NULL; + for (std::vector::iterator it = cus.begin (); + it != cus.end (); ++it) + { + cu *cur = &*it; + if (last != NULL) + last->next = cur; + last = cur; + } + if (cus.size () > 0) + assert (cus.back ().next == NULL); +} + +check_debug_info::~check_debug_info () +{ + cu_free (&cus.back ()); } check_debug_ranges::check_debug_ranges (dwarflint &lint) @@ -320,7 +346,7 @@ check_debug_ranges::check_debug_ranges (dwarflint &lint) { if (!check_loc_or_range_structural (&_m_sec_ranges->file, &_m_sec_ranges->sect, - _m_cus->cu_chain, + &_m_cus->cus.front (), &_m_cus->cu_cov)) throw check_base::failed (""); //xxx } @@ -333,7 +359,8 @@ check_debug_aranges::check_debug_aranges (dwarflint &lint) = _m_cus->cu_cov.need_ranges ? NULL : &_m_cus->cu_cov.cov; if (!check_aranges_structural (&_m_sec_aranges->file, &_m_sec_aranges->sect, - _m_cus->cu_chain, cov)) + &_m_cus->cus.front (), + cov)) throw check_base::failed (""); //xxx } @@ -343,7 +370,8 @@ check_debug_loc::check_debug_loc (dwarflint &lint) { if (!check_loc_or_range_structural (&_m_sec_loc->file, &_m_sec_loc->sect, - _m_cus->cu_chain, NULL)) + &_m_cus->cus.front (), + NULL)) throw check_base::failed (""); //xxx } @@ -363,7 +391,7 @@ namespace { if (!check_pub_structural (&_m_sec->file, &_m_sec->sect, - _m_cus->cu_chain)) + &_m_cus->cus.front ())) throw check_base::failed (""); //xxx } }; @@ -371,3 +399,44 @@ namespace reg > reg_debug_pubnames; reg > reg_debug_pubtypes; } + +namespace +{ + class check_debug_line + : public check + { + section *_m_sec; + + public: + explicit check_debug_line (dwarflint &lint) + : _m_sec (lint.check (_m_sec)) + { + addr_record line_tables; + WIPE (line_tables); + if (!check_line_structural (&_m_sec->file, + &_m_sec->sect, + &line_tables)) + throw check_base::failed (""); //xxx + + check_debug_info *info = NULL; + info = toplev_check (lint, info); + if (info != NULL) + for (std::vector::iterator it = info->cus.begin (); + it != info->cus.end (); ++it) + for (size_t i = 0; i < it->line_refs.size; ++i) + { + struct ref *ref = it->line_refs.refs + i; + if (!addr_record_has_addr (&line_tables, ref->addr)) + { + std::stringstream ss; + ss << ": unresolved reference to .debug_line table " + << "0x" << std::hex << ref->addr << "."; + wr_error (&ref->who, "%s\n", ss.str ().c_str ()); + } + } + addr_record_free (&line_tables); + } + }; + + reg reg_debug_line; +} diff --git a/src/dwarflint/checks-low.hh b/src/dwarflint/checks-low.hh index 0e5bddc4a..60b52bcb1 100644 --- a/src/dwarflint/checks-low.hh +++ b/src/dwarflint/checks-low.hh @@ -7,6 +7,7 @@ class load_sections public: elf_file file; explicit load_sections (dwarflint &lint); + ~load_sections (); }; class section_base @@ -55,9 +56,9 @@ class check_debug_info public: cu_coverage cu_cov; std::vector cus; - cu *cu_chain; // xxx explicit check_debug_info (dwarflint &lint); + ~check_debug_info (); }; static reg reg_debug_info; diff --git a/src/dwarflint/checks.hh b/src/dwarflint/checks.hh index ba09504b9..e906e9fb2 100644 --- a/src/dwarflint/checks.hh +++ b/src/dwarflint/checks.hh @@ -32,16 +32,18 @@ public: }; template -void -toplev_check (dwarflint &lint) +T * +toplev_check (dwarflint &lint, + __attribute__ ((unused)) T *tag = NULL) { try { - lint.check (); + return lint.check (); } catch (check_base::failed const &f) { std::cout << f.what () << std::endl; + return NULL; } } diff --git a/src/dwarflint/low.c b/src/dwarflint/low.c index e85e03540..02a2ee111 100644 --- a/src/dwarflint/low.c +++ b/src/dwarflint/low.c @@ -3446,21 +3446,18 @@ read_rel (struct elf_file *file, bool check_line_structural (struct elf_file *file, struct sec *sec, - struct cu *cu_chain) + struct addr_record *line_tables) { struct read_ctx ctx; read_ctx_init (&ctx, sec->data, file->other_byte_order); bool retval = true; - struct addr_record line_tables; - WIPE (line_tables); - while (!read_ctx_eof (&ctx)) { struct where where = WHERE (sec->id, NULL); uint64_t set_offset = read_ctx_get_offset (&ctx); where_reset_1 (&where, set_offset); - addr_record_add (&line_tables, set_offset); + addr_record_add (line_tables, set_offset); const unsigned char *set_begin = ctx.ptr; /* Size. */ @@ -3932,19 +3929,7 @@ check_line_structural (struct elf_file *file, } if (retval) - { - relocation_skip_rest (sec); - - for (struct cu *cu = cu_chain; cu != NULL; cu = cu->next) - for (size_t i = 0; i < cu->line_refs.size; ++i) - { - struct ref *ref = cu->line_refs.refs + i; - if (!addr_record_has_addr (&line_tables, ref->addr)) - wr_error (&ref->who, - ": unresolved reference to .debug_line table %#" PRIx64 ".\n", - ref->addr); - } - } + relocation_skip_rest (sec); return retval; } diff --git a/src/dwarflint/low.h b/src/dwarflint/low.h index a8b7539e0..5a0f2836e 100644 --- a/src/dwarflint/low.h +++ b/src/dwarflint/low.h @@ -34,7 +34,6 @@ #include "addr-record.h" #ifdef __cplusplus -# include extern "C" { #else @@ -161,27 +160,10 @@ extern "C" struct cu *cu_chain); extern bool check_line_structural (struct elf_file *file, struct sec *sec, - struct cu *cu_chain); + struct addr_record *line_tables); extern void cu_free (struct cu *cu_chain); - void section_coverage_init (struct section_coverage *sco, - struct sec *sec, bool warn); - bool coverage_map_init (struct coverage_map *coverage_map, - struct elf_file *elf, - Elf64_Xword mask, - Elf64_Xword warn_mask, - bool allow_overlap); - void coverage_map_add (struct coverage_map *coverage_map, - uint64_t address, uint64_t length, - struct where *where, enum message_category cat); - bool coverage_map_find_holes (struct coverage_map *coverage_map, - bool (*cb) (uint64_t, uint64_t, - struct section_coverage *, void *), - void *user); - void coverage_map_free (struct coverage_map *coverage_map); - - struct hole_info { enum section_id section; diff --git a/src/dwarflint/main.cc b/src/dwarflint/main.cc index 4dfdaa157..bc064916e 100644 --- a/src/dwarflint/main.cc +++ b/src/dwarflint/main.cc @@ -262,34 +262,6 @@ dwarflint::dwarflint (Elf *a_elf) : _m_elf (a_elf) { check_registrar::inst ()->enroll (*this); - - struct elf_file file; - if (!elf_file_init (&file, a_elf)) - return; - - check_debug_info *check_info = check (check_info); - // xxx check_expected_trees - cu *cu_chain = check_info->cu_chain; - -#define SEC(sec) (file.debugsec[sec_##sec]) -#define HAS_SEC(sec) (SEC(sec) != NULL && SEC(sec)->data != NULL) - - if (HAS_SEC(line)) - check_line_structural (&file, SEC(line), cu_chain); - else if (!tolerate_nodebug) - { - where wh = WHERE (sec_line, NULL); - wr_message (mc_impact_4 | mc_acc_suboptimal | mc_elf | mc_loc, - &wh, ": data not found.\n"); - } - - cu_free (cu_chain); - if (file.ebl != NULL) - ebl_closebackend (file.ebl); - free (file.sec); - -#undef SEC -#undef HAS_SEC } int -- 2.47.3