Useless `DT_NEEDED` tags after Garbage Collection

Christoph Conrads christoph.conrads@fluent.ai
Thu Oct 18 18:38:00 GMT 2018


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
  Beta,
* `--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. 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
  otherwise.
* 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`. 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?



More information about the Binutils mailing list