Now LLD does not export a strong defined symbol if it coalesces away a weak symbol defined in 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 faultThe problem is caused by the fact that we lose all information about coalesced symbols after the Resolver::resolve() method is finished.
The patch solves the problem by overriding the LinkingContext::notifySymbolTableCoalesce() method and saving names of coalesced symbols. Later in the buildDynamicSymbolTable() routine we use this information to export these symbols.
I think I don't like this pattern that uses a reference as a boolean attribute for an atom. I understand it's undeniably convenient in some cases, in particular when storing and restoring an atom with the attribute to/from disk using native/yaml format, but it is basically simulating a C++ member in a complicated manner using its own associative list. There is also a performance concern because in order to access the "field" we have to iterate over the reference list.
This can be a boolean field in the ELF class, can't this?
If the reason not to make it a member is native/yaml reader/writer, we should fix them to make it easy to do what we want to do.