Useless `DT_NEEDED` tags after Garbage Collection
Fri Oct 19 05:56:00 GMT 2018
On Thu, Oct 18, 2018 at 08:38:37PM +0200, Christoph Conrads wrote:
> My goal is to create a shared library without dead code linking only
> against other needed libraries.
> The situation is as follows:
> I want to make my code, let us call it "Alpha", available as a shared
> library. Alpha depends on "Beta". The source code for Beta is
> available, I must link statically against Beta, and I cannot modify Beta
> but I can compile and link as needed. Beta depends on the shared library
> Gamma. Let us call this library `libgamma.so`.
> Alpha has an API exposed via functions with default visibility. All of
> Beta's functions have hidden visibility. To minimize the size of the
> Alpha shared library (let us call it "libalpha.so"), I pass
> * `-fPIC -ffunction-sections` to the compiler when compiling Alpha and
> * `--gc-sections` to the linker when linking `libalpha.so`.
> This has the desired effect of removing all dead code from
> `libalpha.so`. As a side-effect, linking against `libgamma.so` is not
> necessary anymore but ld will still add a `DT_NEEDED` tag for
> `libgamma.so`, even in the presence of `--as-needed`.
> Question 1:
> > Is there a way to have ld detect and ignore unused `DT_NEEDED` tags
> > due to garbage collection?
> This can be done manually by omitting `libgamma.so` from the command
> line but this is error prone, tedious, and might not work with the next
> release of Beta.
> I concluded that ld must be computing `DT_NEEDED` tags before performing
> garbage collection.
Correct. It's done when loading symbols for the library in question.
> A relocatable object file seemed to solve my problem:
> * Compile an Alpha static library, pass `-fPIC -ffunction-sections` to
> the compiler, ensure all API symbols have default visibility, hidden
> * Compile a Beta static library, pass `-fPIC -ffunction-sections` to the
> compiler, ensure all symbols have hidden visibility.
> * Create a relocatable object from the Alpha static library and the Beta
> static library with `--gc-sections --gc-keep-exported`. All dead code
> is removed in this step.
> * Create a shared library from the relocatable object, pass
> `--as-needed` to the linker.
> Unfortunately, the creation of the relocatable object does not work as I
> had planned because one has to pass all of Alpha's symbols with default
> visibility with the linker option `--entry`.
Really? And multiple --entry options made a difference?
Did you mean --undefined (or -u) rather than --entry? Even so, I'm
surprised that you would need to use the -u trick on a linker
supporting --gc-keep-exported. What binutils version and target are
> Luckily I misspelt the
> symbol names once. Lo and behold, ld simply ignored the non-existent
> symbol and created the relocatable object containing all symbols with
> default visibility and without dead code just as I had envisioned it.
> Question 2:
> > Is there a way to create a relocatable object with `--gc-sections
> > --gc-keep-exported` and without `--entry` on the command line?
> Question 3:
> > Assuming, a relocatable object with `--gc-sections
> > --gc-keep-exported` must also be built using `--entry`, can I rely on
> > the behavior of ld if the symbol name passed to `--entry` does not
> > exist? That is, ld will still create a relocatable object?
Australia Development Lab, IBM
More information about the Binutils