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, 7 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, 7 months
Status 2009-01-26
by Petr Machata
= Work done last week:
* Time spent on elfutils: ~50%
* This was a bad week. The little time I spent on elfutils was
actually several false starts and code thrown away eventually. Later in
the week my RHEL responsibilities have kicked in and I spent the
remainder of the week on that. So at least I've updated the dwarflint
wiki page.
= Work scheduled for this week:
* Expected time spent on elfutils: 50-80%.
* Fix 10-byte LEB128 that Roland posted about. (This should
actually be already in.)
* Write .debug_ranges validation.
* Relocs.
PM
14 years, 8 months
elfutils status 2009-1-26
by Roland McGrath
(Actually it's 2009-1-27 here now.)
Last week:
Actual time on elfutils: 80%
* posted to dwarf-discuss list wrt imported_unit and reference identity
-> upshot: don't use imported_unit non-toplevel context unless not ref'd
-> might limit redundancy elimination in e.g. template instantiations
* 0.139 release
-> made fedorahosted release
-> 0.139-1 in rawhide, F-9/F-10 updates-testing
-> compatibility nit hacking
* attr value interfaces
** read-only side somewhat there
** still missing: refs, lines, macinfo, known enums, loclist, reloc
This week:
Expected time on elfutils: 80%
* post to dwarf-discuss wrt more imported_unit questions
*** vs CU-context attrs (stmt_list, macro_info): imported or importer?
*** vs .debug_macinfo
* attr value interfaces
** lines
** loclist?
** dwarf_edit counterpart
** contemplate references
* post or wikiize wrt dwarf_output class design
14 years, 8 months
dwarflint .debug_aranges
by Roland McGrath
Two things occur to me wrt .debug_aranges validation:
It's not an automatic error if there is no .debug_aranges section (or a
completely empty one). It's a high-level check that the aranges match the
CUs--but you can legitimately have just CUs that don't have any addresses.
You do a connectivity check for the CU pointers. It would also be useful
to do a "suspicious" check that there aren't multiple separate sets
pointing to the same CU. It is not clearly invalid per se to have
multiples, but it is clearly weird. Our high-level checks probably won't
try to account for multiple sets for a CU being correct.
Also, now that I look at your aranges code, I assume you either haven't
tested it yet or haven't pushed the current code. The "Covered length"
parsing is totally bogus. What follows the CU offset are two single bytes
(address_size, segment_size), not another offset-size value that's a
length. What you should check there is that the address_size matches the
address_size in the CU header, and that the segment_size is 0.
Thanks,
Roland
14 years, 8 months
0.139
by Roland McGrath
I pushed one nit (d759aa6). With that, I think 0.139 is good to go.
Thanks,
Roland
14 years, 8 months
build error on
by Benjamin De Kosnik
Running into a build error on up-to-date sources today.
%git status
# On branch dwarf
nothing to commit (working directory clean)
--
$src/elfutils/configure --enable-maintainer-mode --verbose
--prefix=$bld/H-x86-elfutils
and then
make
fails with:
make[2]: Entering directory `/mnt/share/bld/elfutils/libcpu'
m4 -Di386 -DDISASSEMBLER /mnt/share/src/elfutils/libcpu/defs/i386 \
| sed
'1,/^%%/d;/^#/d;/^[[:space:]]*$/d;s/[^:]*:\([^[:space:]]*\).*/MNE(\1)/;s/{[^}]*}//g;/INVALID/d'
\
| sort -u > i386.mnemonics
if gcc -D_GNU_SOURCE -DHAVE_CONFIG_H -I. -I/mnt/share/src/elfutils/libcpu
-I.. -I/mnt/share/src/elfutils/libcpu
-I/mnt/share/src/elfutils/libcpu/../lib
-I/mnt/share/src/elfutils/libcpu/../libelf
-I/mnt/share/src/elfutils/libcpu/../libebl
-I/mnt/share/src/elfutils/libcpu/../libdw
-I/mnt/share/src/elfutils/libcpu/../libasm -Wall -Wshadow -Wunused -Wextra
-std=gnu99 -fpic -Werror -g -O2 -MT i386_gendis.o -MD -MP -MF
".deps/i386_gendis.Tpo" -c -o i386_gendis.o
/mnt/share/src/elfutils/libcpu/i386_gendis.c; \
then mv -f ".deps/i386_gendis.Tpo" ".deps/i386_gendis.Po"; else rm -f
".deps/i386_gendis.Tpo"; exit 1; fi
byacc -pi386_ /mnt/share/src/elfutils/libcpu/i386_parse.y
byacc: e - line 240 of "/mnt/share/src/elfutils/libcpu/i386_parse.y", syntax
error
%defines
^
make[2]: *** [i386_parse.c] Error 1
make[2]: *** Waiting for unfinished jobs....
this is on F10, nothing special.
-benjamin
14 years, 8 months
0.139
by Roland McGrath
I'd already been doing test builds in expectation of 0.139 today.
I'm re-running those tests now on 80d94f48. If nothing new pops
up, I think we're ready to go.
Thanks,
Roland
14 years, 8 months
transifex committing bogons
by Roland McGrath
Who do I complain at about the 'transif' user committing crap to my repo?
Whether done by robot or human, someone has to be responsible, and
responsive to project administrators. The L10N/FAQ page is real short on
prominent answers to obvious questions for project admins like this one.
As requested, I enabled transif to commit to the elfutils repo on
git.fedorahosted.org. Then we got the following commit.
I understand doing a dummy commit to test the access.
I don't understand doing one and then not reverting it.
I don't understand committing bogus mis-formatting to my po/ChangeLog.
If you can't even do a dummy commit so that it's harmless to the project,
why should I trust you and your robot to be allowed to commit to our repo?
We will very much appreciate the contributions of translators, and we
recognize the great contribution of automating and streamlining the process
for translators and project maintainers. But lack of streamlined
automation is better than robots (or human contributors, however
well-meaning) we can't trust to touch our project's files.
Thanks,
Roland
commit cdc4ce361bb098bc0ca67315dfc839642a1af13d
Author: Dimitris Glezos <dimitris(a)glezos.com>
Date: Wed Jan 21 01:04:45 2009 +0000
Dummy commit, testing Transifex at
https://translate.fedoraproject.org/submit/module/elfutils/.
Transmitted-via: Transifex (translate.fedoraproject.org)
diff --git a/po/ChangeLog b/po/ChangeLog
index bbb72fa..95a51f3 100644
--- a/po/ChangeLog
+++ b/po/ChangeLog
@@ -1,4 +1,7 @@
-2007-06-05 Ulrich Drepper <drepper(a)redhat.com>
+Dummy commit, testing Transifex at
+https://translate.fedoraproject.org/submit/module/elfutils/.
+
+Transmitted-via: Transifex (translate.fedoraproject.org)2007-06-05 Ulrich Drepper <drepper(a)redhat.com>
* Makefile.in.in: Update from gettext 0.16.1.
* Rules-quot: Likewise.
diff --git a/po/Makefile.in.in b/po/Makefile.in.in
index 5022b8b..7cdfad7 100644
--- a/po/Makefile.in.in
+++ b/po/Makefile.in.in
@@ -9,6 +9,7 @@
# General Public License and is *not* in the public domain.
#
# Origin: gettext-0.16
+#
PACKAGE = @PACKAGE@
VERSION = @VERSION@
14 years, 8 months
Compiling wiht -fPIE
by Mark Wielaard
Hi,
When systemtap is bundled with elfutils (configure --with-elfutils) we
compile with -fPIE. This doesn't work with current trunk elfutils git on
i386 anymore because of the TEXTREL check in libdw/Mafefile.am:108
if readelf -d libelf.so | fgrep -q TEXTREL; then exit 1; fi
Would it be possible to make this work again?
Thanks,
Mark
14 years, 8 months