Support dead-stripping in ELF objects

Michael Spencer bigcheesegs at gmail.com
Fri Apr 5 17:44:53 PDT 2013


On Fri, Apr 5, 2013 at 3:41 PM, Robinson, Paul <
Paul_Robinson at playstation.sony.com> wrote:

> Michael,
> Understanding what guarantees the compiler is making is certainly good.
> The goal of my patch is:
> * Any reference to a function uses a relocation whose symbol is that
>   function's symbol (not relaxed to .text+N, and in the case of a call
>   within the same .text section, not relaxed to a fixed offset).
> * Any reference to a statically allocated data item uses a relocation
>   whose symbol is that variable's symbol (not relaxed to .data+N or
>   whatever section it is).
> * In-memory constants (.rodata*) count as data items and are treated the
>   same way as a variable.
>
> The use of function symbol relocations implicitly divides the .text
> section into atoms identifiable by symbol name.  Thus individual functions
> can be dead-stripped if there are no references to that function's symbol.
> Data items and in-memory constants whose only references are from
> dead-stripped functions can also be dead-stripped.
>
> > > I've thought about this in terms of both deadstripping
> > > and
> > > how to make atomization of ELF files faster and have the following:
> > >
> > > Section flags:
> > > * SHF_VALID_SIZE
>
> A better flag name might be SHF_ATOMIZED (symbols can certainly all have
> valid sizes without defining atoms for you).
>

This is a much better name.


> > >    * If a relocation in this section has a target symbol which is in a
> > > section with this flag set, r_addend must be less than st_size.
>
> Michael, I think this bullet wants to be "If any relocation has a target
> symbol which is defined in a section with this flag set, r_addend must be
> less than st_size."  It doesn't matter which section is making the
> reference.
>

Ah, correct.


>
> > >
> > >    This is separate from SHF_SUBSECTION_VIA_SYMBOLS because it makes
> > > atomization faster even in cases where symbol data cannot be moved.
> > > This is
> > > important as it allows the assembler to preform more relaxation to get
> > > smaller output while still allowing for this optimization.
>
> Michael, the net effect I see is that the compiler has defined symbols that
> subdivide the section, and promises that there are no relocations that use
> a symbol for one subsection but the target is in a different subsection.
>
> I believe my patch does this for .text, .data, and .rodata* sections,
> and so could set the section flag on those sections.  On the other hand,
> my patch is mainly driven by symbol type, not the section-of-definition;
> so the atomization occurs because that's just how the compiler works, not
> because the assembler is paying attention to all the symbols for a given
> section and causing them to define subsections.
>

I agree that your patch does most of the work required to do this. My only
issue with it specifically is documentation and the basis on which it
decides to do this (entire file vs per section). With those changes I would
be glad to see it go in.


>
> I'm not clear on what value you gain from atoms that can't be independently
> moved, though.
>

It increases performance of doing the atomization because you can make more
assumptions. It has no semantic benefit.


>
> > >
> > > * SHF_DEADSTRIP - This section may be removed if it is dead. If
> > > SHF_SUBSECTION_VIA_SYMBOLS is also set, symbols and their data may be
> > > removed if dead.
> > >
> > >    This is separate because the assembler may have preformed
> > > relaxation
> > > within a section, but you would still like the entire section to be
> > > removed
> > > if it is not referenced. This also provides a way to limit the effect
> > > of
> > > --gc-sections without hard coding the names of sections not to remove
> > > (such
> > > as .init and .fini).
>
> Michael, again I'm looking for the use case where we genuinely want to
> permit the possibilities you've identified:
> * The object is atomized for you, but the atoms have to stick together in
>   their sections. [SHF_VALID_SIZE alone] (or SHF_ATOMIZED)
> * The atoms can be shuffled, but not can be removed
>   [SHF_SUBSECTIONS_VIA_SYMBOLS alone] [well, implies +SHF_ATOMIZED]
> * Section is not atomized but can be removed as a whole
>   [SHF_DEADSTRIP alone]
> * Atoms can be selectively removed; this is the one with the identified
>   use case...
>   [SHF_SUBSECTIONS_VIA_SYMBOLS+SHF_DEADSTRIP]
>
> Saying "the assembler could do this or that or the other thing" isn't
> really all that convincing.  WHY would the assembler do all these weird
> things?  Identifying dead-strippable atoms, sure, because then the linker
> can actually do something positive to reduce the size of the final image.
> But identifying atoms that cannot be stripped? or even reordered? How is
> that useful?  I'm willing to be persuaded but there needs to be some
> actual utility to all these cases before we burn so many bits.
>
> If the distinctions aren't useful, then one section flag that means
> SHF_SUBSECTIONS_VIA_SYMBOLS+SHF_ATOMIZED+SHF_DEADSTRIP is enough.
>

* SHF_ATOMIZED
  This is important to be able to be alone for performance reasons. All
current code can use this without breaking, even if it makes assumptions
about the ABI. It's just letting the linker know that the compiler did what
the compiler almost always does, which is give correct symbol sizes.

* SHF_SUBSECTIONS_VIA_SYMBOLS
  Alone this is not very useful. But it's important for SHF_ATOMIZED to be
not tied to this for compatibility reasons.

* SHF_DEADSTRIP
  This is important in cases where you care about code size, especially on
platforms where relaxation can greatly shrink code size, but you still want
to remove entirely dead sections. This is based on
-f{function,data}-sections + --gc-sections generating a larger binary in
practice than just --gc-sections in cases where most code is not dead. It's
also important for this to be per section instead of a linker flag because
not all sections can be removed if not referenced. The alternative is
keeping a hard coded list of special sections in the linker, which is what
we do now.


>
> > >
> > > Symbol flags (which we'll have to find a place to embed, probably
> > > st_other
> > > which has 6 free bits):
> > > * STF_NO_DEADSTRIP - Never remove this symbol or symbols it references
> > > even
> > > if it is in a SHF_SUBSECTION_VIA_SYMBOLS or SHF_DEADSTRIP section
>
> Michael, you propose that we could have symbols that are never referenced,
> that the linker doesn't know about a-priori, that aren't special in some
> way such as the image entrypoint symbols, and that the compiler will
> identify as one that it does not want to be eliminated?  Like what?
> I'm happy to concede my ignorance but if you're just enumerating all the
> possibilities then I think maybe a little YAGNI is appropriate.
>

I added this specifically because it's used in practice on Darwin.


> --paulr
>

- Michael Spencer
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130405/cef2d3c7/attachment.html>


More information about the llvm-commits mailing list