LLD does not create a record in the .dynsym if a strong symbol defined in the executable file replaces a weak symbol from a shared library. This bug affects all ELF architectures and leads to segfault:
% cat foo.c extern int __attribute__((weak)) flag; int foo() { return flag; } % cat main.c int flag = 1; int foo(); int main() { return foo() == 1 ? 0 : -1; } % clang -c -fPIC foo.c main.c % lld -flavor gnu -target x86_64 -shared -o libfoo.so ... foo.o % lld -flavor gnu -target x86_64 -o a.out ... main.o libfoo.so % ./a.out Segmentation fault
The problem is in the Resolver class. We lose all information about coalesced symbols after the Resolver::resolve() method is finished. Besides, the symbol resolving code is target independent and we need to keep it in this state.
The patch solves the problem by introducing a new class ELFResolver which is inherited from the Resolver class. In this new class we override the checkUndefines() method, iterate over atoms and configure dynamic export settings for ELFDefinedAtom when necessary.
The Driver class requests an instance if the Resolver class from the LinkingContext. For non-ELF targets we continue to use Resolver class. For ELF targets we create an instance of ELFResolver.