From: Petr Machata Date: Tue, 21 Sep 2010 18:30:40 +0000 (+0200) Subject: dwarflint: Move check_zero_padding to read_ctx module X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2453a6446dfa3151e750d5ce695a5d25912d5989;p=thirdparty%2Felfutils.git dwarflint: Move check_zero_padding to read_ctx module - and promote the reporting part back to callers --- diff --git a/dwarflint/check_debug_info.cc b/dwarflint/check_debug_info.cc index 77515328a..353f4a290 100644 --- a/dwarflint/check_debug_info.cc +++ b/dwarflint/check_debug_info.cc @@ -168,6 +168,7 @@ namespace { struct read_ctx ctx; read_ctx_init (&ctx, sec->data, file->other_byte_order); + uint64_t off_start, off_end; std::vector ret; while (!read_ctx_eof (&ctx)) @@ -183,9 +184,14 @@ namespace /* Reading CU head is a bit tricky, because we don't know if we have run into (superfluous but allowed) zero padding between CUs. */ + if (!read_ctx_need_data (&ctx, 4) - && check_zero_padding (&ctx, cat (mc_info, mc_header), &where)) - break; + && read_check_zero_padding (&ctx, &off_start, &off_end)) + { + wr_message_padding_0 (cat (mc_info, mc_header), &where, + off_start, off_end); + break; + } /* CU length. In DWARF 2, (uint32_t)-1 is simply a CU of that length. In DWARF 3+ that's an escape for 64bit length. @@ -199,8 +205,12 @@ namespace throw check_base::failed (); } if (size32 == 0 - && check_zero_padding (&ctx, cat (mc_info, mc_header), &where)) - break; + && read_check_zero_padding (&ctx, &off_start, &off_end)) + { + wr_message_padding_0 (cat (mc_info, mc_header), &where, + off_start, off_end); + break; + } Dwarf_Off cu_size; if (!read_size_extra (&ctx, size32, &cu_size, @@ -1146,14 +1156,18 @@ check_debug_info::check_info_structural () break; } - if (cu_ctx.ptr != cu_ctx.end - && !check_zero_padding (&cu_ctx, mc_info, &where)) + if (cu_ctx.ptr != cu_ctx.end) { - // 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); + uint64_t off_start, off_end; + if (read_check_zero_padding (&cu_ctx, &off_start, &off_end)) + wr_message_padding_0 (mc_info, &where, off_start, off_end); + else + { + // Garbage coordinates: + uint64_t start = read_ctx_get_offset (&ctx) + off_start; + uint64_t end = read_ctx_get_offset (&ctx) + head.total_size; + wr_message_padding_n0 (mc_info, &where, start, end); + } } int i = read_ctx_skip (&ctx, head.total_size); diff --git a/dwarflint/check_debug_line.cc b/dwarflint/check_debug_line.cc index a383e953f..e57fdb8d5 100644 --- a/dwarflint/check_debug_line.cc +++ b/dwarflint/check_debug_line.cc @@ -1,5 +1,5 @@ /* Low-level checking of .debug_line. - Copyright (C) 2009 Red Hat, Inc. + Copyright (C) 2009, 2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -362,10 +362,13 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint) else if (sub_ctx.ptr < program_start) { struct where wh = WHERE (sec_line, NULL); - if (!check_zero_padding (&sub_ctx, cat (mc_line, mc_header), &where)) + uint64_t off_start, off_end; + if (read_check_zero_padding (&sub_ctx, &off_start, &off_end)) + wr_message_padding_0 (cat (mc_line, mc_header), &wh, + off_start, off_end); + else wr_message_padding_n0 (cat (mc_line, mc_header), &wh, - read_ctx_get_offset (&sub_ctx), - program_start - sub_ctx.begin); + off_start, program_start - sub_ctx.begin); sub_ctx.ptr = program_start; } @@ -479,13 +482,18 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint) } else if (sub_ctx.ptr < next) { - if (handled - && !check_zero_padding (&sub_ctx, mc_line, &where)) + uint64_t off_start, off_end; + if (handled) { struct where wh = WHERE (sec_line, NULL); - wr_message_padding_n0 (mc_line, &wh, - read_ctx_get_offset (&sub_ctx), - next - sub_ctx.begin); + if (read_check_zero_padding (&sub_ctx, + &off_start, &off_end)) + wr_message_padding_0 (mc_line, &wh, + off_start, off_end); + else + wr_message_padding_n0 (mc_line, &wh, + off_start, + next - sub_ctx.begin); } sub_ctx.ptr = next; } @@ -596,11 +604,15 @@ check_debug_line::check_debug_line (checkstack &stack, dwarflint &lint) wr_error (where) << "sequence of opcodes not terminated with DW_LNE_end_sequence." << std::endl; - else if (sub_ctx.ptr != sub_ctx.end - && !check_zero_padding (&sub_ctx, mc_line, &wh)) - wr_message_padding_n0 (mc_line, &wh, - /*begin*/read_ctx_get_offset (&sub_ctx), - /*end*/sub_ctx.end - sub_ctx.begin); + else if (sub_ctx.ptr != sub_ctx.end) + { + uint64_t off_start, off_end; + if (read_check_zero_padding (&sub_ctx, &off_start, &off_end)) + wr_message_padding_0 (mc_line, &wh, off_start, off_end); + else + wr_message_padding_n0 (mc_line, &wh, + off_start, sub_ctx.end - sub_ctx.begin); + } } next: diff --git a/dwarflint/check_debug_pub.cc b/dwarflint/check_debug_pub.cc index 0ce3ff60e..1db93bf9a 100644 --- a/dwarflint/check_debug_pub.cc +++ b/dwarflint/check_debug_pub.cc @@ -1,5 +1,5 @@ /* Low-level checking of .debug_pub*. - Copyright (C) 2009 Red Hat, Inc. + Copyright (C) 2009, 2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -226,14 +226,17 @@ check_debug_pub::check_pub_structural () } struct where wh = WHERE (_m_sec->sect.id, NULL); - if (sub_ctx.ptr != sub_ctx.end - && !check_zero_padding (&sub_ctx, mc_pubtables, &wh)) + if (sub_ctx.ptr != sub_ctx.end) { - 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; + uint64_t off_start, off_end; + if (read_check_zero_padding (&sub_ctx, &off_start, &off_end)) + wr_message_padding_0 (mc_pubtables, &wh, off_start, off_end); + else + { + wr_message_padding_n0 (mc_pubtables | mc_error, &wh, + off_start, off_start + size); + retval = false; + } } } diff --git a/dwarflint/low.c b/dwarflint/low.c index 945af7b44..d49819a5d 100644 --- a/dwarflint/low.c +++ b/dwarflint/low.c @@ -134,26 +134,6 @@ cu_find_cu (struct cu *cu_chain, uint64_t offset) return NULL; } -bool -check_zero_padding (struct read_ctx *ctx, - enum message_category category, - struct where const *wh) -{ - assert (ctx->ptr != ctx->end); - const unsigned char *save_ptr = ctx->ptr; - while (!read_ctx_eof (ctx)) - if (*ctx->ptr++ != 0) - { - ctx->ptr = save_ptr; - return false; - } - - wr_message_padding_0 (category, wh, - (uint64_t)(save_ptr - ctx->begin), - (uint64_t)(ctx->end - ctx->begin)); - return true; -} - bool supported_version (unsigned version, size_t num_supported, struct where *where, ...) @@ -463,15 +443,19 @@ check_aranges_structural (struct elf_file *file, aranges_coverage_add (address, length); } - if (sub_ctx.ptr != sub_ctx.end - && !check_zero_padding (&sub_ctx, mc_aranges, - &WHERE (where.section, NULL))) + if (sub_ctx.ptr != sub_ctx.end) { - wr_message_padding_n0 (mc_aranges | mc_error, - &WHERE (where.section, NULL), - read_ctx_get_offset (&sub_ctx), - read_ctx_get_offset (&sub_ctx) + size); - retval = false; + uint64_t start, end; + if (read_check_zero_padding (&sub_ctx, &start, &end)) + wr_message_padding_0 (mc_aranges, &WHERE (where.section, NULL), + start, end); + else + { + wr_message_padding_n0 (mc_aranges | mc_error, + &WHERE (where.section, NULL), + start, start + size); + retval = false; + } } next: diff --git a/dwarflint/low.h b/dwarflint/low.h index 309e13c17..42361f8d0 100644 --- a/dwarflint/low.h +++ b/dwarflint/low.h @@ -101,9 +101,6 @@ extern "C" #define PRI_NOT_ENOUGH ": not enough data for %s.\n" extern bool supported_version (unsigned version, size_t num_supported, struct where *where, ...); - extern bool check_zero_padding (struct read_ctx *ctx, - enum message_category category, - struct where const *wh); struct section_coverage { diff --git a/dwarflint/readctx.c b/dwarflint/readctx.c index a17bd5a54..a8ca038b3 100644 --- a/dwarflint/readctx.c +++ b/dwarflint/readctx.c @@ -379,3 +379,32 @@ read_address_size (struct read_ctx *ctx, return true; } +static void +update_off (struct read_ctx *ctx, + uint64_t *ret_off) +{ + if (ret_off != NULL) + *ret_off = (uint64_t)(ctx->ptr - ctx->begin); +} + +bool +read_check_zero_padding (struct read_ctx *ctx, + uint64_t *ret_off_start, + uint64_t *ret_off_end) +{ + assert (ctx->ptr != ctx->end); + update_off (ctx, ret_off_start); + bool ret = true; + + const unsigned char *save_ptr = ctx->ptr; + while (!read_ctx_eof (ctx)) + if (*ctx->ptr++ != 0) + { + ctx->ptr = save_ptr; + goto done; + } + + done: + update_off (ctx, ret_off_end); + return ret; +} diff --git a/dwarflint/readctx.h b/dwarflint/readctx.h index d6f94bf8e..99b1c7da5 100644 --- a/dwarflint/readctx.h +++ b/dwarflint/readctx.h @@ -28,6 +28,8 @@ #include #include "../libelf/libelf.h" + +// xxx We don't really like this one #include "where.h" #ifdef __cplusplus @@ -87,6 +89,14 @@ bool read_address_size (struct read_ctx *ctx, int *address_sizep, struct where const *where); +/* See if what remains in the read context is just a zero padding. If + yes, return true. If it isn't, revert the read pointer back as if + nothing had happened and return false. Furthermore, in any case, + if any of the ret pointers is non-NULL, it is filled, respectively, + with start and end offset of the zero padding run. */ +bool read_check_zero_padding (struct read_ctx *ctx, + uint64_t *ret_off_start, + uint64_t *ret_off_end); #ifdef __cplusplus } #endif