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.
... so does that mean that after the optimization, .debug_ranges and
.debug_aranges will not match?
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.
I've written the check, using the <dwarf> library. I'm getting a lot of
this:
warning: .debug_ranges (DIE 0xb): missing range 0x4030e0..0x409123, present in
.debug_aranges.
warning: .debug_aranges (DIE 0x6909): missing range 0x409130..0x409156, present in
.debug_ranges.
warning: .debug_aranges (DIE 0x6909): missing range 0x409160..0x4097a5, present in
.debug_ranges.
This excerpt is from dwarflint of the dwarflint binary itself. The
referred-to DIE is CUDIE of CU that the arange list under consideration
is related to.
I looked into the two warnings for DIE 0x6909, and the situation is:
- .debug_aranges have 0x409130..0x4097a5
- .debug_ranges have 0x409130..0x409156, 0x409160..0x4097a5
- .debug_ranges also have 0x409130..0x4097a5
So there's an overlap in .debug_ranges. Dwarflint currently only validates
.debug_aranges for overlaps, so the overlap is not flagged by earlier errors.
If I understand it correctly, this also means that there's no coalescing taking
place "behind the scenes", and mismatched ranges are flagged appropriately,
even if they cover the same area.
Doing the above, I found a bug in <dwarf> where dwarf_ranges could return 1 when
there was nothing at all in the range list. The iterator would than have _m_offset
of 1, but end()._m_offset would be 0, and the two wouldn't compare equal. That's
fixed in ebd7af on the dwarf branch, where return value of 1 is handled specially.
PM.