We incorrectly mark a shared library as needed when it is referenced by an another (un)needed shared library.
Reproducible example:
#!/usr/bin/env bash
cat >1.c <<\EOF
int foo() { return 1; }
EOF
cat >2.c <<\EOF
int foo();
int bar() { return 3; }
int baz() { return foo(); }
EOF
cat >main.c <<\EOF
int main() { return 0; }
EOF
clang-18 -o lib1.so 1.c -fPIC -shared
clang-18 -o lib2.so 2.c -fPIC -shared
clang-18 -o main.o main.c -c -ffunction-sections
LDs=(ld.eld)
SFs=(eld)
for i in "${!SFs[@]}"; do
${LDs[$i]} -o main.${SFs[$i]}.out main.o --as-needed lib2.so lib1.so
done
$ llvm-readelf --dynamic main.eld.out
# Dynamic section at offset 0x1000 contains 9 entries:
# Tag Type Name/Value
# 0x0000000000000001 (NEEDED) Shared library: [lib1.so]
# 0x0000000000000004 (HASH) 0x4001b0
# 0x0000000000000006 (SYMTAB) 0x40017
This issue causes a simple hello-world x86-64 program to unnecessarily have libgcc_s.so.1 and ld-linux-x86-64.so.2 as DT_NEEDED libraries. Neither GNU nor lld have these DT_NEEDED dependency for the same hello-world program.