{
struct read_ctx ctx;
read_ctx_init (&ctx, sec->data, file->other_byte_order);
+ uint64_t off_start, off_end;
std::vector <cu_head> ret;
while (!read_ctx_eof (&ctx))
/* 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.
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,
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);
/* 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
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;
}
}
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;
}
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:
/* 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
}
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;
+ }
}
}
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, ...)
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:
#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
{
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;
+}
#include <stdbool.h>
#include "../libelf/libelf.h"
+
+// xxx We don't really like this one
#include "where.h"
#ifdef __cplusplus
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