aranges
by Roland McGrath
I've added some read-side C++ support for rangelistptr attr values and for
aranges. The dwarf::range_list class is really just for the DW_AT_ranges
attr comparisons. debug_info_entry.ranges () is what things will use for
semantics (it uses dwarf_ranges, i.e. combining either ranges or lo/hi pc).
dwarf.aranges () is a slow, copying presentation of the aranges suitable
for comparing elements to a compile_unit.ranges (). I didn't make it a
thin reader because we won't really use this outside of dwarflint.
(The unit_by_addr, whenever I get to it, will be a thin layer on
dwarf_getarange_addr.)
dwarf.aranges () yields a map of compile_unit to arange_list.
arange_list and the other flavors from die.ranges () or attr_value.ranges ()
all act like set<pair<Dwarf_Addr, Dwarf_Addr>> (or unordered_set) for
templatey purposes. You can compare them to each other, and all have
a .to_string () for pretty-printing.
The comparisons canonicalize by coalescing contiguous adjacent ranges.
That is true for "semantically equal", and also notes for later what we can
do as an optimization in generating ranges and aranges for output. But
possibly one might want not to coalesce for dwarflint comparison, since
ranges/aranges not matching exactly from the generator seems suspicious.
Lots of tiny ranges that are actually adjacent and contiguous but generated
as many entries can be normal. It's especially common for C++ where
everything is in a zillion tiny little .gnu.linkonce sections. When the
program is finally linked, it all winds up in .text and packed in, so the
many entries have adjacent addresses and look superfluous. In fact they
are superfluous and we can coalesce them away for smaller .debug_aranges
sections. But they're not suspicious, since they made perfect sense as
emitted before the final link.
Another thing to note for output-side optimization is that it's common to
have many entries that are adjacent except for a gap of a few bytes. This
too is normal and correct as generated. The gaps are alignment bits in
.text between multiple entry points in a CU. It's correct precision to
leave the gaps there in DIE range lists. But .debug_aranges exists purely
for quick lookup of the containing CU. So when a gap that's not part of
any CU is small (i.e. less than sh_addralign of the section containing both
addresses), we can just coalesce across it so the addresses in the gap map
to the CU it's in the middle of. If someone is actually searching for the
gap addresses, they will just descend the CU and not find it, which is
fine. More commonly, we'll reduce the entries to just a few for each CU
and keep the table small so searches are fast.
The following is what I used to test this. But it really belongs in a
dwarflint high-level check, not in dwarfcmp. This code already showed some
interesting anomalies. dwarflint should eventually show the differences in
some way that's especially helpful for debugging the generators. That will
be handy in diagnosing and reporting the details of what GCC does wrong.
Someone should investigate these anomalies, but for now it will have to
take a back seat to our critical path on DWARF writing/transformation work.
Thanks,
Roland
==============================
diff --git a/src/dwarfcmp.cc b/src/dwarfcmp.cc
index 522b719..0000000 100644
--- a/src/dwarfcmp.cc
+++ b/src/dwarfcmp.cc
@@ -304,6 +304,20 @@ main (int argc, char *argv[])
dwarf file1 (dw1);
dwarf file2 (dw2);
+ {
+ const dwarf::aranges_map aranges = file1.aranges ();
+ for (dwarf::aranges_map::const_iterator i = aranges.begin ();
+ i != aranges.end ();
+ ++i)
+ {
+ const dwarf::compile_unit &cu = (*i).first;
+ const dwarf::arange_list &ranges = (*i).second;
+ cout << (cu.ranges () == ranges ? "match" : "mismatch")
+ << " aranges " << ranges.to_string () << " vs CU-ranges "
+ << cu.ranges ().to_string () << endl;
+ }
+ }
+
if (quiet)
result = !(file1 == file2);
else
14 years, 10 months
sequential reading of .debug_loc
by Petr Machata
Hi,
I'm poking into .debug_loc. Currently the validation is done only on
portions referenced from .debug_info. I rewrote the code to do it the
way it's done in other cases: .debug_info references are remembered, and
used to cross-check connectivity later, during sequential scan of
.debug_loc.
But when validating "holes", i.e. portions of .debug_loc that are not
referenced from .debug_info, I'm getting a lot of weird errors: negative
and empty ranges, invalid location expressions (opcode 0 is a norm). It
looks like the unreferenced portions are filled with garbage, and that
the section as a whole is not supposed to be scanned sequentially. But
if it's garbage, it screws the stream of location lists surprisingly seldom.
One example that I've found is
/usr/lib/debug/usr/lib64/openoffice.org/program/deployment680lx.uno.so.debug,
where the stream actually ends up screwed royally after offset 70dd, and
the file ends up with dozens of unresolved location list references.
readelf -wloc shows implausible location expressions after 70dd, too.
Many debuginfo files from openoffice.org suite show similar problems.
So... am I missing some arcane insider info (or just misreading the
spec), or are these actual errors in our DWARF files?
In the mean time, I switched back to the old way of validation, but I'm
attaching the patch (formed against 8aef81) in case anyone wants to see
on their own eyes.
PM
diff --git a/src/dwarflint.c b/src/dwarflint.c
index dc71805..5060994 100644
--- a/src/dwarflint.c
+++ b/src/dwarflint.c
@@ -170,8 +170,8 @@ enum message_category
mc_pubtables = 0x100000, // table of public names/types
mc_pubtypes = 0x200000, // .debug_pubtypes presence
mc_loc = 0x400000, // messages related to .debug_loc
- mc_ranges = 0x800000, // messages related to .debug_ranges
- mc_other = 0x1000000, // messages unrelated to any of the above
+ mc_ranges = 0x1000000, // messages related to .debug_ranges
+ mc_other = 0x2000000, // messages unrelated to any of the above
mc_all = 0xffffff00, // all areas
};
@@ -190,7 +190,7 @@ accept_message (struct message_criteria *crit, enum message_category cat)
}
static struct message_criteria warning_criteria
- = {mc_all & ~(mc_strings | mc_loc),
+ = {mc_all & ~(mc_strings),
mc_pubtypes};
static struct message_criteria error_criteria
= {mc_impact_4 | mc_error,
@@ -321,7 +321,7 @@ main (int argc, char *argv[])
warning_criteria.reject |= mc_acc_bloat | mc_pubtypes;
if (be_strict)
{
- warning_criteria.accept |= mc_strings | mc_loc;
+ warning_criteria.accept |= mc_strings;
if (!be_gnu)
warning_criteria.reject &= ~mc_pubtypes;
}
@@ -586,7 +586,6 @@ struct hole_info
static void coverage_init (struct coverage *ar, uint64_t size);
static void coverage_add (struct coverage *ar, uint64_t begin, uint64_t end);
-static bool coverage_is_covered (struct coverage *ar, uint64_t address);
static void coverage_find_holes (struct coverage *ar,
void (*cb)(uint64_t begin, uint64_t end, void *data),
void *data);
@@ -604,6 +603,7 @@ struct cu
uint64_t base; // DW_AT_low_pc value of CU DIE, 0 if not present.
struct addr_record die_addrs; // Addresses where DIEs begin in this CU.
struct ref_record die_refs; // DIE references into other CUs from this CU.
+ struct ref_record loc_refs; // DIE references into .debug_loc
struct where where; // Where was this section defined.
bool has_arange; // Whether we saw arange section pointing to this CU.
bool has_pubnames; // Likewise for pubnames.
@@ -619,24 +619,23 @@ static struct cu *cu_find_cu (struct cu *cu_chain, uint64_t offset);
static struct cu *check_debug_info_structural (struct read_ctx *ctx,
struct abbrev_table *abbrev_chain,
- Elf_Data *strings,
- Elf_Data *loc);
+ Elf_Data *strings);
static bool check_cu_structural (struct read_ctx *ctx,
struct cu *const cu,
struct abbrev_table *abbrev_chain,
Elf_Data *strings,
- Elf_Data *loc,
bool dwarf_64,
struct ref_record *die_refs,
- struct addr_record *loc_addrs,
- struct coverage *strings_coverage,
- struct coverage *loc_coverage);
+ struct coverage *strings_coverage);
static bool check_aranges_structural (struct read_ctx *ctx,
struct cu *cu_chain);
static bool check_pub_structural (struct read_ctx *ctx,
struct cu *cu_chain,
enum section_id sec);
-
+static bool check_loc_structural (struct read_ctx *ctx,
+ struct cu *cu_chain,
+ bool addr_64,
+ struct addr_record *addrs);
static const char *where_fmt (struct where *wh, char *ptr)
{
@@ -841,7 +840,7 @@ process_file (int fd __attribute__((unused)),
{
read_ctx_init (&ctx, dwarf, info_data);
cu_chain = check_debug_info_structural (&ctx, abbrev_chain,
- str_data, loc_data);
+ str_data);
}
else if (!tolerate_nodebug)
/* Hard error, not a message. We can't debug without this. */
@@ -872,6 +871,57 @@ process_file (int fd __attribute__((unused)),
wr_message (mc_impact_4 | mc_acc_suboptimal | mc_elf | mc_pubtypes,
&WHERE (sec_pubtypes, NULL), ": data not found.\n");
+ if (loc_data != NULL && cu_chain != NULL)
+ {
+ /* We can only do exhaustive .debug_loc validation, if all CUs
+ have the same address size. Sanity of address size is
+ checked when building the cu_chain. */
+ uint8_t address_size = 0;
+ for (struct cu *it = cu_chain; it != NULL; it = it->next)
+ if (address_size == 0)
+ address_size = it->address_size;
+ else if (address_size != it->address_size)
+ {
+ wr_message (mc_loc | mc_info, &it->where,
+ ": has different address size from the previous CU.\n");
+ address_size = 0;
+ break;
+ }
+
+ if (address_size != 0)
+ {
+ read_ctx_init (&ctx, dwarf, loc_data);
+
+ struct addr_record loclist_addrs;
+ memset (&loclist_addrs, 0, sizeof (loclist_addrs));
+
+ if (check_loc_structural (&ctx, cu_chain, address_size == 8,
+ &loclist_addrs))
+ {
+ bool have_unresolved = false;
+
+ /* Check that all references are resolved. */
+ for (struct cu *it = cu_chain; it != NULL; it = it->next)
+ for (size_t i = 0; i < it->loc_refs.size; ++i)
+ {
+ struct ref *ref = it->loc_refs.refs + i;
+ if (!addr_record_has_addr (&loclist_addrs, ref->addr))
+ {
+ if (!have_unresolved)
+ {
+ wr_error (&WHERE (sec_info, NULL),
+ ": unresolved location expression references:\n");
+ have_unresolved = true;
+ }
+ wr_error (&ref->who,
+ ": references 0x%" PRIx64 ".\n", ref->addr);
+ }
+ }
+ }
+ }
+ }
+ /* XXX check that all cu->loc_refs are satisfied. */
+
cu_free (cu_chain);
abbrev_table_free (abbrev_chain);
}
@@ -1620,27 +1670,6 @@ coverage_add (struct coverage *ar, uint64_t begin, uint64_t end)
}
}
-static bool
-coverage_is_covered (struct coverage *ar, uint64_t address)
-{
- assert (ar);
- assert (address <= ar->size);
-
- uint64_t bi = address / coverage_emt_bits;
- uint8_t bb = address % coverage_emt_bits;
- coverage_emt_type bm = (coverage_emt_type)1 << (coverage_emt_bits - 1 - bb);
- return !!(ar->buf[bi] & bm);
-}
-
-static bool
-coverage_pristine (struct coverage *ar, uint64_t begin, uint64_t length)
-{
- for (uint64_t i = 0; i < length; ++i)
- if (coverage_is_covered (ar, begin + i))
- return false;
- return true;
-}
-
static void
coverage_find_holes (struct coverage *ar,
void (*cb)(uint64_t begin, uint64_t end, void *user),
@@ -1844,6 +1873,7 @@ wr_check_zero_padding (struct read_ctx *ctx,
return true;
}
+/*
static bool
check_x_location_expression (struct read_ctx *ctx,
struct cu *cu,
@@ -1851,12 +1881,12 @@ check_x_location_expression (struct read_ctx *ctx,
struct addr_record *loc_addrs,
uint64_t addr, bool addr_64,
struct where *wh);
+*/
static struct cu *
check_debug_info_structural (struct read_ctx *ctx,
struct abbrev_table *abbrev_chain,
- Elf_Data *strings,
- Elf_Data *loc)
+ Elf_Data *strings)
{
struct ref_record die_refs;
memset (&die_refs, 0, sizeof (die_refs));
@@ -1872,16 +1902,6 @@ check_debug_info_structural (struct read_ctx *ctx,
strings_coverage = &strings_coverage_mem;
}
- struct coverage loc_coverage_mem, *loc_coverage = NULL;
- struct addr_record loc_addrs_mem, *loc_addrs = NULL;
- if (loc != NULL && check_category (mc_loc))
- {
- coverage_init (&loc_coverage_mem, loc->d_size);
- loc_coverage = &loc_coverage_mem;
- memset (&loc_addrs_mem, 0, sizeof (loc_addrs_mem));
- loc_addrs = &loc_addrs_mem;
- }
-
while (!read_ctx_eof (ctx))
{
const unsigned char *cu_begin = ctx->ptr;
@@ -1955,9 +1975,8 @@ check_debug_info_structural (struct read_ctx *ctx,
}
cu_ctx.ptr = ctx->ptr;
- if (!check_cu_structural (&cu_ctx, cur, abbrev_chain, strings, loc,
- dwarf_64, &die_refs, loc_addrs,
- strings_coverage, loc_coverage))
+ if (!check_cu_structural (&cu_ctx, cur, abbrev_chain, strings,
+ dwarf_64, &die_refs, strings_coverage))
{
success = false;
break;
@@ -2008,24 +2027,26 @@ check_debug_info_structural (struct read_ctx *ctx,
coverage_free (strings_coverage);
}
- if (loc_coverage != NULL)
- {
- if (success)
- coverage_find_holes (loc_coverage, found_hole,
- &((struct hole_info)
- {sec_loc, mc_loc, loc->d_buf}));
- coverage_free (loc_coverage);
- }
-
- if (loc_addrs != NULL)
- addr_record_free (loc_addrs);
-
if (!success || !references_sound)
{
cu_free (cu_chain);
cu_chain = NULL;
}
+ /* Reverse the chain, so that it's organized "naturally". Has
+ significant impact on performance when building set of all loc
+ references in CUs, as the addr_record_add doesn't have to add to
+ the beginning. */
+ 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;
+
return cu_chain;
}
@@ -2051,6 +2072,7 @@ get_location_opcode_operands (uint8_t opcode, uint8_t *op1, uint8_t *op2)
};
}
+/* CAT is message category. */
static void
check_location_expression (struct read_ctx *ctx, struct where *wh, bool addr_64)
{
@@ -2068,8 +2090,9 @@ check_location_expression (struct read_ctx *ctx, struct where *wh, bool addr_64)
uint8_t op1, op2;
if (!get_location_opcode_operands (opcode, &op1, &op2))
{
- wr_error (&where, ": can't decode opcode \"%s\".\n",
- dwarf_locexpr_opcode_string (opcode));
+ wr_message (mc_loc | mc_error, &where,
+ ": can't decode opcode \"%s\".\n",
+ dwarf_locexpr_opcode_string (opcode));
return;
}
@@ -2093,6 +2116,7 @@ check_location_expression (struct read_ctx *ctx, struct where *wh, bool addr_64)
}
}
+#if 0
static bool
check_x_location_expression (struct read_ctx *ctx,
struct cu *cu,
@@ -2228,6 +2252,7 @@ check_x_location_expression (struct read_ctx *ctx,
return retval;
}
+#endif
/*
@@ -2242,13 +2267,10 @@ read_die_chain (struct read_ctx *ctx,
struct cu *cu,
struct abbrev_table *abbrevs,
Elf_Data *strings,
- Elf_Data *loc,
bool dwarf_64, bool addr_64,
struct ref_record *die_refs,
- struct ref_record *die_loc_refs,
- struct addr_record *loc_addrs,
- struct coverage *strings_coverage,
- struct coverage *loc_coverage)
+ struct ref_record *local_die_refs,
+ struct coverage *strings_coverage)
{
bool got_die = false;
uint64_t sibling_addr = 0;
@@ -2320,7 +2342,7 @@ read_die_chain (struct read_ctx *ctx,
{
where.ref = &it->where;
- void record_ref (uint64_t addr, struct where *who, bool local)
+ void record_ref (uint64_t addr, bool local)
{
struct ref_record *record = &cu->die_refs;
if (local)
@@ -2337,11 +2359,11 @@ read_die_chain (struct read_ctx *ctx,
/* Address holds a CU-local reference, so add CU
offset to turn it into section offset. */
addr += cu->offset;
- record = die_loc_refs;
+ record = local_die_refs;
}
if (record != NULL)
- ref_record_add (record, addr, who);
+ ref_record_add (record, addr, &where);
}
uint8_t form = it->form;
@@ -2377,7 +2399,6 @@ read_die_chain (struct read_ctx *ctx,
}
bool check_locptr = false;
- bool locptr_64 = addr_64;
if (is_location_attrib (it->name))
{
switch (check_CU_location_form (form, dwarf_64))
@@ -2395,7 +2416,6 @@ read_die_chain (struct read_ctx *ctx,
wr_error (&where,
": location attribute with form \"%s\" in %d-bit CU.\n",
dwarf_form_string (form), (dwarf_64 ? 64 : 32));
- locptr_64 = !locptr_64;
/* fall-through */
case 1: /* locptr */
@@ -2455,7 +2475,7 @@ read_die_chain (struct read_ctx *ctx,
goto cant_read;
if (it->form == DW_FORM_ref_addr)
- record_ref (addr, &where, false);
+ record_ref (addr, false);
else if (abbrev->tag == DW_TAG_compile_unit
|| abbrev->tag == DW_TAG_partial_unit)
cu->base = addr;
@@ -2474,7 +2494,7 @@ read_die_chain (struct read_ctx *ctx,
if (it->name == DW_AT_sibling)
sibling_addr = value;
else if (it->form == DW_FORM_ref_udata)
- record_ref (value, &where, true);
+ record_ref (value, true);
break;
}
@@ -2489,7 +2509,7 @@ read_die_chain (struct read_ctx *ctx,
if (it->name == DW_AT_sibling)
sibling_addr = value;
else if (it->form == DW_FORM_ref1)
- record_ref (value, &where, true);
+ record_ref (value, true);
break;
}
@@ -2503,14 +2523,14 @@ read_die_chain (struct read_ctx *ctx,
if (it->name == DW_AT_sibling)
sibling_addr = value;
else if (it->form == DW_FORM_ref2)
- record_ref (value, &where, true);
+ record_ref (value, true);
break;
}
case DW_FORM_data4:
case DW_FORM_ref4:
{
- uint32_t value;
+ uint32_t value = -1;
if (!read_ctx_read_4ubyte (ctx, &value))
goto cant_read;
@@ -2518,14 +2538,11 @@ read_die_chain (struct read_ctx *ctx,
sibling_addr = value;
else if (check_locptr)
{
- struct read_ctx sub_ctx;
- read_ctx_init (&sub_ctx, ctx->dbg, loc);
- check_x_location_expression (&sub_ctx, cu, loc_coverage,
- loc_addrs, value, locptr_64,
- &where);
+ //printf ("loclist reference 32 %#" PRIx32 "\n", value);
+ ref_record_add (&cu->loc_refs, value, &where);
}
else if (it->form == DW_FORM_ref4)
- record_ref (value, &where, true);
+ record_ref (value, true);
break;
}
@@ -2540,14 +2557,11 @@ read_die_chain (struct read_ctx *ctx,
sibling_addr = value;
else if (check_locptr)
{
- struct read_ctx sub_ctx;
- read_ctx_init (&sub_ctx, ctx->dbg, loc);
- check_x_location_expression (&sub_ctx, cu, loc_coverage,
- loc_addrs, value, locptr_64,
- &where);
+ //printf ("loclist reference 64 %#" PRIx64 "\n", value);
+ ref_record_add (&cu->loc_refs, value, &where);
}
else if (it->form == DW_FORM_ref8)
- record_ref (value, &where, true);
+ record_ref (value, true);
break;
}
@@ -2618,10 +2632,10 @@ read_die_chain (struct read_ctx *ctx,
if (abbrev->has_children)
{
- int st = read_die_chain (ctx, cu, abbrevs, strings, loc,
+ int st = read_die_chain (ctx, cu, abbrevs, strings,
dwarf_64, addr_64,
- die_refs, die_loc_refs, loc_addrs,
- strings_coverage, loc_coverage);
+ die_refs, local_die_refs,
+ strings_coverage);
if (st == -1)
return -1;
else if (st == 0)
@@ -2672,12 +2686,9 @@ check_cu_structural (struct read_ctx *ctx,
struct cu *const cu,
struct abbrev_table *abbrev_chain,
Elf_Data *strings,
- Elf_Data *loc,
bool dwarf_64,
struct ref_record *die_refs,
- struct addr_record *loc_addrs,
- struct coverage *strings_coverage,
- struct coverage *loc_coverage)
+ struct coverage *strings_coverage)
{
uint16_t version;
uint64_t abbrev_offset;
@@ -2722,15 +2733,14 @@ check_cu_structural (struct read_ctx *ctx,
return false;
}
- struct ref_record die_loc_refs;
- memset (&die_loc_refs, 0, sizeof (die_loc_refs));
+ struct ref_record local_die_refs;
+ memset (&local_die_refs, 0, sizeof (local_die_refs));
bool retval = true;
- if (read_die_chain (ctx, cu, abbrevs, strings, loc,
+ if (read_die_chain (ctx, cu, abbrevs, strings,
dwarf_64, address_size == 8,
- die_refs, &die_loc_refs,
- loc_addrs, strings_coverage,
- loc_coverage) >= 0)
+ die_refs, &local_die_refs,
+ strings_coverage) >= 0)
{
for (size_t i = 0; i < abbrevs->size; ++i)
if (!abbrevs->abbr[i].used)
@@ -2738,13 +2748,13 @@ check_cu_structural (struct read_ctx *ctx,
": Abbreviation with code %" PRIu64 " is never used.\n",
abbrevs->abbr[i].code);
- if (!check_die_references (cu, &die_loc_refs))
+ if (!check_die_references (cu, &local_die_refs))
retval = false;
}
else
retval = false;
- ref_record_free (&die_loc_refs);
+ ref_record_free (&local_die_refs);
return retval;
}
@@ -3063,3 +3073,116 @@ check_pub_structural (struct read_ctx *ctx, struct cu *cu_chain,
return retval;
}
+
+
+static bool
+check_loc_structural (struct read_ctx *ctx,
+ struct cu *cu_chain,
+ bool addr_64,
+ struct addr_record *addrs)
+{
+ /* A record of all references for fast look-up of
+ unreferenced .debug_loc portions. */
+ struct addr_record refs;
+ memset (&refs, 0, sizeof (refs));
+ for (struct cu *it = cu_chain; it != NULL; it = it->next)
+ for (size_t i = 0; i < it->loc_refs.size; ++i)
+ addr_record_add (&refs, it->loc_refs.refs[i].addr);
+
+ uint64_t escape = addr_64 ? (uint64_t)-1 : (uint64_t)(uint32_t)-1;
+ while (!read_ctx_eof (ctx))
+ {
+ struct where where = WHERE (sec_loc, NULL);
+ uint64_t loclist_addr = read_ctx_get_offset (ctx);
+ where_reset_1 (&where, loclist_addr);
+ addr_record_add (addrs, loclist_addr);
+
+ if (!addr_record_has_addr (&refs, loclist_addr))
+ wr_message (mc_loc | mc_acc_bloat | mc_impact_2,
+ &where, ": unreferenced loclist.\n");
+
+ uint64_t base = -1;
+ while (!read_ctx_eof (ctx))
+ {
+ where_reset_2 (&where, read_ctx_get_offset (ctx));
+ /*
+ for (size_t i = 0; i < 32; ++i)
+ printf (" %02x", ctx->ptr[i]);
+ printf ("\n");
+ */
+ /* 7.7.3: the two addresses are the same size as used by
+ DW_FORM_addr on the target machine. */
+
+ /* begin address */
+ uint64_t begin_addr;
+ if (!read_ctx_read_offset (ctx, addr_64, &begin_addr))
+ {
+ wr_error (&where, ": can't read address range beginning.\n");
+ return false;
+ }
+
+ /* end address */
+ uint64_t end_addr;
+ if (!read_ctx_read_offset (ctx, addr_64, &end_addr))
+ {
+ wr_error (&where, ": can't read address range ending.\n");
+ return false;
+ }
+
+ if (begin_addr == 0 && end_addr == 0)
+ /* 2.6.6: A location list containing only an end of list
+ entry describes an object that exists in the source
+ code but not in the executable program. */
+ break;
+ else if (begin_addr == escape)
+ {
+ if (end_addr == base)
+ wr_message (mc_acc_bloat | mc_impact_3 | mc_loc, &where,
+ ": base address selection entry doesn't change base address.\n");
+ base = end_addr;
+ }
+ else
+ {
+ /* location expression length */
+ uint16_t len;
+ if (!read_ctx_read_2ubyte (ctx, &len))
+ {
+ wr_error (&where, ": can't read length of location expression.\n");
+ return false;
+ }
+ /* DWARF expression containing no operations
+ [i.e. length == 0] [...] represents a piece of an
+ object that is present in the source code but not in
+ the object code (perhaps due to optimization). */
+
+ if (end_addr < begin_addr)
+ wr_message (mc_loc | mc_error, &where,
+ ": has negative range 0x%" PRIx64 "..0x%" PRIx64 ".\n",
+ begin_addr, end_addr);
+ else if (begin_addr == end_addr && len > 0)
+ /* 2.6.6: A location list entry [...] whose beginning
+ and ending addresses are equal has no effect. */
+ wr_message (mc_acc_bloat | mc_impact_3 | mc_loc, &where,
+ ": location list entry covers no range.\n");
+
+ /* location expression itself */
+ struct read_ctx expr_ctx;
+ if (!read_ctx_init_sub (&expr_ctx, ctx, ctx->ptr, ctx->ptr + len))
+ {
+ not_enough:
+ wr_error (&where,
+ ": not enough data for location expression of length %d.\n",
+ len);
+ return false;
+ }
+
+ check_location_expression (&expr_ctx, &where, addr_64);
+ if (!read_ctx_skip (ctx, len))
+ /* "can't happen" */
+ goto not_enough;
+ }
+ }
+ }
+
+ return true;
+}
14 years, 10 months
elfutils status 2009-2-2
by Roland McGrath
Sorry for delayed report, I was really out of it early this week.
Last week:
Actual time on elfutils: 80%
* attr value interfaces
** misc fixes
** lines
** location/location lists
** dwarf_edit counterpart
*** now complete for copying purposes, modulo: macinfo, pubnames, refs
** germinating plan for references
*** iterator for value type
*** interfile equality and copying require non-generic solution
-> contemplating parameterizing by "reference resolver" class
This week:
Expected time on elfutils: 10%
* review
There was a meeting last week at which it was acknowledged that the
debuginfo revamp is not going to make Fedora 11. It was always an
extremely aggressive schedule, even with the most generous estimates of how
late in the Fedora cycle we could be done. So it's not really a surprise
that we won't make this cycle, though I was glad to act like we might and
concentrate on fast progress. This takes some of the immediate pressure
off since we don't have a target deadline looming very soon.
Unfortunately, I will not be keeping up quite the same pace in my
contributions because I need now to give some neglected other projects
their fair share of my time. But I still want to keep up the momentum and
try to hit all the same marks as soon as we can, not let it all slide all
the way into the next cycle.
Thanks,
Roland
14 years, 10 months