[Dwarf-Discuss] Split Dwarf vs. CU DW_AT_ranges / DW_AT_low_pc placement

David Blaikie dblaikie@gmail.com
Thu Mar 11 09:01:05 GMT 2021


+Mark in case he's got further context/perspective to share in the context
of this thread

One particular thing I'll pull out of the gdb-patches thread is:

"But the rnglists
(loclists) themselves can still use relocations. A large part of them
is non-shared addresses, so using indexes (into the .debug_addr
addr_base) would simply be extra overhead."

That's not quite right - while a direct mapping from debug_loc and
debug_ranges (at least location and range lists not using base address
selection entries) to debug_loclist and debug_rnglist would produce a
similar number of addresses and relocations - there's a lot to be gained by
using DW_RLE/LLE_base_addressx entries - then you can strategically reuse
an already-existing debug_addr entry and avoid another relocation all
together (debug_loc and debug_ranges couldn't do this, even when using a
base address selection entry - that base address couldn't be shared with
other lists, since it was inline). This has significant savings, and was
the main reason I suggested to Paul Robinson that range lists should get
the same handling as loclists - since optimized builds use a lot of range
listst and their relocations were taking up a huge amount of the remaining
.o/executable contribution to debug info. This (rnglists.dwo with strategic
use of base address selection entries) was the main win we saw when
switching Google from DWARFv4+GNU-extension Split DWARF to DWARFv5 and
justified the not insignificant work of updating the various DWARF
consumers we had (including a few of those patches upstreamed to gdb, lldb,
and various internal and external symbolizers).

also, as to the original motivation for Split DWARF (reduce object size,
reduce relocations, etc) - mostly a distributed build system where the cost
of shipping all the object files to the link step is a significant
bottleneck - so reduced object size (so reducing the DWARF object size -
which is both .debug_* sizes, and .rela.debug_* sizes equally - well,
except we do use -gz so .debug_* sizes are much smaller, but .rela.debug_*
is not compressed - so reducing relocations is /extra/ important).

And a neat note: Actually after DWARFv5 we have a .rela.debug_addr which is
/smaller/ than .rela.debug_line, which is sort of surprising/noteworthy.
That means that .rela.debug_addr has just one address for each section* -
but it also has an entry for each global variable, which .debug_line
doesn't have, so I'd usually expect .rela.debug_line to be a strict subset
of .rela.debug_addr - except that DWARFv5 moved the debug_line strings out
to .debug_line_str, which added a relocation for every file/directory name
- pushing the number of relocations up over the trimmed down
rela.debug_addr.

I haven't done GCC V Clang comparisons in a while - but it might be worth
trying some with Split DWARF, as I suspect this rnglist stuff and strategic
base address selection logic may carry quite some weight.

Picked a random file from the LLVM tree and built it with -O3 -gdwarf-5
-gsplit-dwarf with Clang and GCC ToT and some relevant stats:

Probably the lower bound for relocations is GCC's .rela.debug_line since it
uses the DWARFv3 line tables, without relocations for each directory and
file name, so basically one relocation per section (this build used
-ffunction-sections, so that amounts to one relocation per function):

 2.29Ki .rela.debug_line

GCC's other .rela.debug_*:

  291Ki .rela.debug_addr

   74Ki .rela.debug_rnglists

Clang's:

  7Ki .rela.debug_line
 45Ki .rela.debug_addr

Or, with the "prefer DW_AT_ranges, even when the range is contiguous":

  6Ki .rela.debug_addr


And with a custom form...

 2.20Ki   0.0%       0    .rela.debug_addr

And comparing the .rela.debug_line and .rela.debug_addr in this last
example - there's exactly one more debug_addr relocation than debug_line
relocation, the one global variable in this CU.

(I went to look a bit further and GCC's .debug_loclists.dwo but it seems
there's something about it that llvm-dwarfdump can't understand - it only
prints a handful of rather mangled location lists... not sure which
component (GCC, llvm-dwarfdump, or both) is getting things confused here -
oh, maybe some kind of DWARF extension for the "views" system, by the looks
of it)

* actually there's one bit left: DW_AT_low_pc - it can't use an
addrx+offset encoding. So for now I've implemented a mode in Clang where
DW_AT_ranges instead of DW_AT_low/high_pc is used even when a DIE has a
contiguous address, so that a strategic base address can be used, reducing
the size of .{rela.}debug_addr a bit more, at the expense of a slightly
larger .debug_rnglists.dwo. I hope to propose/add some kind of addrx+offset
form to DWARFv6 to address this gap (& I've prototyped that in Clang too,
under a flag).

On Wed, Mar 10, 2021 at 11:23 PM Simon Marchi via Dwarf-Discuss <
dwarf-discuss at lists.dwarfstd.org> wrote:

> On 2021-03-10 10:59 a.m., Jakub Jelinek via Dwarf-Discuss wrote:> Hi!
> >
> > We got a report today that GCC even for -gdwarf-5 -gsplit-dwarf uses
> > .debug_rnglists section + DW_AT_ranges + DW_AT_low_pc +
> DW_AT_rnglists_base
> > attributes in the DW_TAG_skeleton_unit (and then some DW_AT_ranges in
> > .debug_info.dwo that use DW_FORM_rnglistx, but no .debug_rnglists.dwo
> > section).  That is the same spot where
> > the DWARF 4 split DWARF extension was using, but the .debug_ranges
> > section wasn't really placeable into dwo files.
> > So, my first question is whether that is really invalid DWARF 5 or not.
> >
> > LLVM seems to emit instead:
> > .debug_rnglists section + DW_AT_ranges + DW_AT_low_pc +
> DW_AT_rnglists_base
> > attributes in the DW_TAG_skeleton_unit (but .debug_rnglists only contains
> > the ranges for the whole CU) and then
> > .debug_rnglistsx.dwo section and DW_AT_ranges in .debug_info.dwo (not on
> the
> > DW_TAG_compile_unit though) that refer to that.
> >
> > Would it be ok to emit only DW_AT_low_pc in DW_TAG_skeleton_unit and
> > .debug_rnglists.dwo section and DW_AT_ranges (but not
> DW_AT_rnglists_base)
> > in DW_TAG_compile_unit?  I mean, is there any benefit in having the CU
> > ranges on the skeleton over .debug_info.dwo?  Do split debug info
> consumers
> > need to essentially merge the attributes from the skeleton unit and
> > corresponding compile unit?
>
> Just for the record, I think I stumbled on those differences earlier
> when fixing GDB consuming clang's DWARF 5 range lists.  I asked on the
> gdb-patches list:
>
>   https://sourceware.org/pipermail/gdb-patches/2020-November/173053.html
>
> Mark Wielaard's opinion was that both ways were valid.  I'll follow the
> discussions here to see if the community settles on another
> interpretation.
>
> Simon
> _______________________________________________
> Dwarf-Discuss mailing list
> Dwarf-Discuss at lists.dwarfstd.org
> http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.dwarfstd.org/pipermail/dwarf-discuss-dwarfstd.org/attachments/20210311/bd39d0d2/attachment.html>



More information about the Dwarf-discuss mailing list