Extract an archive member to satisfy a DSO undef
2021-08-15 16:00:00 Author: maskray.me(查看原文) 阅读量:31 收藏

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
2
3
4
5
6
7
8
9
echo '.globl _start; _start: call bb' > a.s
echo '.globl bb; bb: call cc' > b.s
echo '.globl cc; cc: nop' > c.s
cc -c a.s b.s c.s
rm -f c.a && ar rc c.a c.o
ld -shared -z defs c.o -o c.so
ld -shared -z defs b.o ./c.so -o b.so

ld -rpath=. a.o b.so c.a

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
2
3
4
5
6
7
8
9
10
11
# On macOS
echo '.globl _main; _main: call bb' > a.s
echo '.globl bb; bb: call cc' > b.s
echo '.globl cc; cc: nop' > c.s
clang --target=x86_64-apple-darwin -c a.s b.s c.s
rm -f c.a && ar rc c.a c.o

clang -dynamiclib c.o -o c.dylib
clang -dynamiclib b.o c.dylib -o b.dylib
clang a.o b.dylib c.a
# a.out doesn't define or reference cc

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)


文章来源: http://maskray.me/blog/2021-08-15-extract-archive-member-to-satisfy-dso-undef
如有侵权请联系:admin#unsafe.sh