When or what makes gcc add dependencies?

68 Views Asked by At

I was investigating an issue with sudo and at some point I've noticed that gcc adds libintl as a sudo dependency:

$ ldd src/sudo
    /lib/ld-musl-x86_64.so.1 (0x77e7c812f000)
    libintl.so.8 => /usr/lib/libintl.so.8 (0x77e7c7d0d000)
    libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x77e7c812f000)

supposedly for no reason.

My guess is that if sudo depends on libintl, then one of the symbols of the latter should be in the symbol table of one of the sudo constituents.

sudo is built this way:

$ gcc -o sudo conversation.o error.o exec.o \
exec_pty.o get_pty.o net_ifs.o load_plugins.o \
parse_args.o sudo.o sudo_edit.o tgetpass.o \
ttysize.o utmp.o ../common/libcommon.la \
../compat/libreplace.la ...

and this:

$ { readelf -s src/conversation.o;
readelf -s src/error.o; readelf -s src/exec.o;
readelf -s src/exec_pty.o; readelf -s src/get_pty.o;
readelf -s src/net_ifs.o; readelf -s src/load_plugins.o;
readelf -s src/parse_args.o; readelf -s src/sudo.o;
readelf -s src/sudo_edit.o; readelf -s src/tgetpass.o;
readelf -s src/ttysize.o; readelf -s src/utmp.o;
readelf -s common/.libs/libcommon.a;
readelf -s compat/.libs/libreplace.a; } \
| grep -E "intl|gettext"

gives nothing.

What am I missing? How can I further clarify the issue? readelf -s /usr/lib/libintl.so.8.1.4 output is in the gist.

UPD

$ ldd /lib/ld-musl-x86_64.so.1
        ldd (0x787ce30fe000)
1

There are 1 best solutions below

0
x-yuri On

By default the linker adds every library passed via -l as a dependency:

Normally the linker will add a DT_NEEDED tag for each dynamic library mentioned on the command line, regardless of whether the library is actually needed or not.

The --as-needed switch was supposedly added in 2.15.90. With it a library is added only if it contains symbols needed by the code.

So in Alpine Linux 3.4 (gcc-5.3.0) it behaves normally: it gets -lintl, and adds libintl as a dependency.

In Alpine Linux >= 3.5 (gcc-6.2.1) it behaves as if --as-needed was passed: it gets -lintl, but it doesn't add the library as a dependency, because it was not used (referenced).

And the last piece of the puzzle is the Alpine Linux commit (5.3.0 -> 6.1.0) that makes gcc pass --as-needed to the linker.

Actually it can be reproduced more easily (thanks yvs2014).