This is an archive of the discontinued LLVM Phabricator instance.

[ELF] Simplify handling of exportDynamic and isPreemptible
ClosedPublic

Authored by MaskRay on Aug 12 2019, 8:58 AM.

Details

Summary

In Writer::includeInDynSym(), exportDynamic is used by a Defined with
protected or default visibility, to record whether it is required to be
exported into .dynsym. It is set when any of the following conditions
hold:

  1. There is an interposable symbol from a DSO (Undefined or SharedSymbol with default visibility)
  2. If -shared or --export-dynamic is specified, any symbol in an object file/bitcode sets this property, unless suppressed by canBeOmittedFromSymbolTable().
  3. --dynamic-list when producing an executable

Bullet 3) does not play well with 1) and 2). When -shared is specified,
exportDynamic of most symbols is true. This makes it incapable to record
--dynamic-list marked symbols. We thus have obscure:

if (!config->shared)
  b->exportDynamic = true;
else if (b->includeInDynsym())
  b->isPreemptible = true;

This patch adds another bit Symbol::inDynamicList to record
3). We can thus simplify handleDynamicList() by unifying the DSO and

executable cases. It also allows us to simplify isPreemptible - now

the field is only used in finalizeSections() and later stages.

Event Timeline

MaskRay created this revision.Aug 12 2019, 8:58 AM

The code changes look good to me. I've made some suggestions on the name of the flag and some of the comments.

ELF/InputFiles.cpp
1485 ↗(On Diff #214644)

Post variable naming change, could we use newDefined or newSym to avoid the New (presumably to avoid clash with new).

ELF/Symbols.h
119–126

I've struggled with the name and comment here. I think it is because this is really the union of two separate properties that have a similar effect, with a similar name to a command line option that has a related but different effect. The two separate properties are:

  • In an executable, there is a Shared symbol with default visibility that we may preempt or define.
  • The symbol is present in a dynamic list.

Separate from this we have --export-dynamic which affects whether all symbols of the appropriate visibility defined in an executable should be put into the dynamic symbol table. The presence of --export-dynamic on the command line does not affect the exportDynamic flag in Symbol even though the name suggests that it should.

The best I can come up with for alternative is something like requiresDynamic or forceDynamic.

requiresDynamic is used by a Defined symbol with protected or default visibility, to record whether a symbol is required to be exported into the .dynsym. This is set when any of the following conditions hold:
- In an executable, when there is an existing Shared symbol with default visibility from an interposable DSO.
- When the symbol is present in the dynamic list file.
ELF/Writer.cpp
1659

A small nit, the comment implies that the dynamic list is mandatory.
// In a DSO, if the symbol is in a dynamic list then it specifies whether the symbol is preemptible.

MaskRay updated this revision to Diff 214758.Aug 12 2019, 10:18 PM
MaskRay marked 4 inline comments as done.
MaskRay edited the summary of this revision. (Show Details)

Given it more thought. Rather than extracting -shared or --export-dynamic logic outside exportDynamic,
we should instead pull the --dynamic-list information out.

Delete canOmitFromDynSym and add inDynamicList instead.

Added a new test dynamic-list-preempt2.s in rLLD368649 to test some interaction between exportDynamic is isPreemptible.

MaskRay marked an inline comment as done.Aug 12 2019, 10:21 PM

Thanks. These are very valuable suggestions. Changed the way exportDynamic is handled, compared with the first revision. isPreemptible can still be simplified.

peter.smith accepted this revision.Aug 13 2019, 1:20 AM

Thanks for the update, this looks a lot easier to understand. Looks good to me.

This revision is now accepted and ready to land.Aug 13 2019, 1:20 AM
MaskRay updated this revision to Diff 214784.Aug 13 2019, 2:09 AM

Add sym->inDynamicList = false; to SymbolTable::insert

Bit fields that may be referenced as ... = old.field in Symbol::replace should be initialized in SymbolTable::insert

This revision was automatically updated to reflect the committed changes.