This is an archive of the discontinued LLVM Phabricator instance.

[ELF2] Add --undefined option
ClosedPublic

Authored by denis-protivensky on Oct 1 2015, 6:46 AM.

Details

Summary

Add symbol specified with -u as undefined which may cause additional object files from archives to be linked into the resulting binary.

Diff Detail

Repository
rL LLVM

Event Timeline

denis-protivensky retitled this revision from to [ELF2] Add --undefined option.
denis-protivensky updated this object.
denis-protivensky added reviewers: ruiu, rafael.
denis-protivensky added a project: lld.
denis-protivensky added a subscriber: llvm-commits.
ruiu added inline comments.Oct 1 2015, 7:44 AM
ELF/SymbolTable.cpp
82–83 ↗(On Diff #36236)

nit: If it gets two lines, I'd write like this

resolve<ELFT>(
    new (Alloc) ...);
83 ↗(On Diff #36236)

Why optional? All symbols specified with -u must be resolved, no?

ELF/Symbols.h
250–263 ↗(On Diff #36236)

This seems overkill because I don't think we are going to allocate a lot of Synthetic Undefined symbols. Can you simply make these static fields non-static? It's going to allocate a Elf_Sym per Undefined, but that wouldn't really affect anything to performance.

ELF/SymbolTable.cpp
83 ↗(On Diff #36236)

As I understand, the doc says it shouldn't make linking process degrade, I mean, it shouldn't cause link errors if some of these undefined symbols are not resolved. The only purpose of this is to trigger adding of object files from archives if they contain symbols specified.
These symbols technically don't have any logical impact on binary, so with these left undefined there won't be any changes in runtime behavior since these undefines are not used by any code.

ELF/Symbols.h
250–263 ↗(On Diff #36236)

Good.

ruiu added inline comments.Oct 1 2015, 8:38 AM
ELF/SymbolTable.cpp
83 ↗(On Diff #36236)

Yeah, that's right.

Is there any reason we can't merge canKeepUndefined with isWeak?

rafael edited edge metadata.Oct 1 2015, 10:35 AM

Change the last test to create a shared library and check the the 'unknown' symbol shows up only on the regular symbol table, not the dynamic one.

Change the last test to create a shared library and check the the 'unknown' symbol shows up only on the regular symbol table, not the dynamic one.

Good.

ELF/SymbolTable.cpp
83 ↗(On Diff #36236)

We can't use weak undefined symbol to trigger resolution and addition of object files from archives.
This is explicitly stated in the ELF reference:
"The link editor does not extract archive members to resolve undefined weak symbols."

ELF/Symbols.h
250–263 ↗(On Diff #36236)

Looks like I won't be able to rework this fully. I need a flag to indicate that the symbol is not "regular" undefined, but a special one added with -u. This flag is the SyntheticOptional symbol itself, and I check its address with what current Undefined object holds in canKeepUndefined. Otherwise I'll need to hold std::unique_ptr with synthetic symbol generated dynamically, for example, and check that it's not empty, but I won't be able to distinguish between entry point and --undefined added symbol (they now have two separate static symbols SyntheticRequired and SyntheticOptional).
I'll move static initializer to a better place though.

denis-protivensky edited edge metadata.

Updated:

  • simplify initialization of static synthetic symbol
  • add test to check that undefined symbol is not in dynamic table
ruiu accepted this revision.Oct 2 2015, 10:38 AM
ruiu edited edge metadata.

LGTM

ELF/SymbolTable.cpp
91 ↗(On Diff #36356)

This is not guaranteed to be thread-safe since if this function is called simultaneously, two assignments could run at the same time, and although that looks benign, that's a race condition.

It is OK for now. We don't do multi-threading soon. We probably want to have a init() function for each file which initialize static members. We can do that later.

This revision is now accepted and ready to land.Oct 2 2015, 10:38 AM

It is OK for now. We don't do multi-threading soon. We probably want to have a init() function for each file which initialize static members. We can do that later.

It should be possible to statically initialize this somehow, but need
to look deeper a bit on why just

template <class ELFT>
typename DefinedAbsolute<ELFT>::Elf_Sym
DefinedAbsolute<ELFT>::IgnoreUndef = {0, 0, ..., 2, 0... };

Doesn't compile.

Cheers,
Rafael

This revision was automatically updated to reflect the committed changes.