ELF linkers extract an archive member to satisfy an undefined symbol from a shared object. (Do Unix linkers have this behavior?) Here is an example:
1 | echo '.globl _start; _start: call bb' > a.s |
ld extracts c.a(c.o)
and exports cc
into the dynamic symbol table. ld.bfd, gold, and ld.lld have the same behavior.
This behavior intrigued me because link.exe (PE/COFF) and ld64 (Mach-O) don't inspect undefined symbols in DLL/dylib for symbol resolution.
1 | # On macOS |
We know that an undef from a DSO can interact with a .o definition. The .o definition needs to be exported to .dynsym in case the DSO relies on symbols in the executable. (PE/COFF and Mach-O don't need/have the behavior.)
This does not necessarily generalize to the interaction between a DSO and an archive.
If a DSO linked into the final executable has incomplete DT_NEEDED entries, I can imagine that not extracting archive members to satisfy a DSO undef can cause ld.so "unresolved symbol" errors. (--no-allow-shlib-undefined can flag similar fragile links.) However, if every DSO is linked with -z defs (--no-undefined), not extracting archive members appears to be very robust. (My summary of [1].)
In my ld -rpath=. a.o b.so c.a
ELF example, if we make c.so DF_SYMBOLIC, a.out will have definitions trying to interpose c.so definitions in vain. Linkers seem to have no ability detect such one definition rule violation. (One definition rule is C++'s, but we can reuse the concept: multiple definitions have more or less unreliability.)
In [2], I raised the point that it can be difficult to make --no-undefined happy because all linkers as I know don't support an option listing allowed undefined symbols. Mach-O ld64 defaults to -undefined error
but can switch to -undefined suppress
for an ELFish behavior.
Related discussions:
[1] https://bugs.llvm.org/show_bug.cgi?id=43554 [2] https://reviews.llvm.org/D108006 (propose --no-search-static-libs-for-shlib-undefined to ld.lld)