This is an archive of the discontinued LLVM Phabricator instance.

[ELF] Export strong defined symbol if it coalesces away a weak symbol defined in a shared library
ClosedPublic

Authored by atanasyan on Sep 3 2014, 1:06 AM.

Details

Summary

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 fault

The 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.

Diff Detail

Event Timeline

atanasyan updated this revision to Diff 13192.Sep 3 2014, 1:06 AM
atanasyan retitled this revision from to [ELF] Export strong defined symbol if it coalesces away a weak symbol defined in a shared library.
atanasyan updated this object.
atanasyan edited the test plan for this revision. (Show Details)
atanasyan added a project: lld.
atanasyan added a subscriber: Unknown Object (MLST).
shankarke edited edge metadata.Sep 3 2014, 9:52 AM

Could we just store the name in the ELFLinkingContext, that it can be exported ?

lib/ReaderWriter/ELF/DefaultTargetHandler.h
46 ↗(On Diff #13192)

Why in the target handler ?

ruiu added inline comments.Sep 3 2014, 10:10 AM
include/lld/Core/Reference.h
97 ↗(On Diff #13192)

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.

kledzik edited edge metadata.Sep 3 2014, 12:46 PM

Just add a StringMap ivar to ELFLinkingContext. Have notifySymbolTableCoalesce() add the atom name to the map when overriding a weak atom. In buildDynamicSymbolTable() check for atom->dynamicExport() OR (atom->scope() == scopeGlobal and its name is in the StringMap).

atanasyan updated this revision to Diff 13348.Sep 5 2014, 3:02 PM
atanasyan updated this object.
atanasyan edited edge metadata.

This patch implements more trivial approach to fix the bug. It does not create new references to mark symbols need to be exported. Instead of that the patch saves names of the strong defined symbols which coalesce away weak symbols and refers to this name set when build dynamic export table.

ruiu accepted this revision.Sep 5 2014, 3:06 PM
ruiu edited edge metadata.

LGTM

This revision is now accepted and ready to land.Sep 5 2014, 3:06 PM
shankarke accepted this revision.Sep 5 2014, 3:47 PM
shankarke edited edge metadata.
kledzik accepted this revision.Sep 5 2014, 6:33 PM
kledzik edited edge metadata.

LGTM

atanasyan closed this revision.Sep 8 2014, 2:55 AM

Thanks for review.

Closed by commit rL217363.