This is an archive of the discontinued LLVM Phabricator instance.

[ELF] Consistently prioritize non-* wildcards overs "*" in version scripts
ClosedPublic

Authored by MaskRay on Aug 4 2019, 3:02 AM.

Details

Summary

We prioritize non-* wildcards overs VER_NDX_LOCAL/VER_NDX_GLOBAL "*".
This patch generalizes the rule to "*" of other versions and thus fixes PR40176.
I don't feel strongly about this GNU linkers' behavior but the
generalization simplifies code.

Delete config->defaultSymbolVersion which was used to special case
VER_NDX_LOCAL/VER_NDX_GLOBAL "*".

In SymbolTable::scanVersionScript, custom versions are handled the same
way as VER_NDX_LOCAL/VER_NDX_GLOBAL. So merge
config->versionScript{Locals,Globals} into config->versionDefinitions.
Overall this seems to simplify the code.

In SymbolTable::assign{Exact,Wildcard}Versions,
sym->verdefIndex == config->defaultSymbolVersion is changed to
verdefIndex == UINT32_C(-1).
This allows us to give duplicate assignment diagnostics for
{ global: foo; }; V1 { global: foo; };

In test/linkerscript/version-script.s:

vs_index of an undefined symbol changes from 0 to 1. This doesn't matter (arguably 1 is better because the binding is STB_GLOBAL) because vs_index of an undefined symbol is ignored.

Diff Detail

Repository
rL LLVM

Event Timeline

MaskRay created this revision.Aug 4 2019, 3:02 AM

Overall looks good to me. I've got a few suggestions on the refactoring. One other thing that might be worth doing to make this easier to review is to split it into two patches:

  • A refactoring change that doesn't change the wildcard behaviour.
  • The change to the wildcard behaviour.

Not got a strong opinion on that now I've gone through it.

ELF/Config.h
75 ↗(On Diff #213238)

names is very close to name. Perhaps patterns as this is what I think a SymbolVersion represents. For example foo*. Come to think of it, SymbolVersion could be confusing as it is more like a VersionPattern.

ELF/Driver.cpp
1021 ↗(On Diff #213238)

Would it be clearer to say [VER_NDX_LOCAL] instead of [0] and [VER_NDX_GLOBAL] instead of 1? In this file it is quite easy to see what 0 and 1 are from the push_back above, but this doesn't necessarily hold for other files.

ELF/ScriptParser.cpp
1347 ↗(On Diff #213238)

This file is where I was thinking that versionDefinitions[VER_NDX_LOCAL].names would be clearer for 0, and versionDefinitions[VER_NDX_GLOBAL] for 1.

1367 ↗(On Diff #213238)

Is this comment needed now that the +2 has been removed.

ELF/SymbolTable.cpp
207 ↗(On Diff #213238)

Would prefer verdefIndex = VER_NDX_LOCAL;

ELF/SyntheticSections.cpp
2775 ↗(On Diff #213238)

Any reason why in Sybols.cpp auto & was used instead of the const VersionDefinition & used here?

Maybe worth a named helper function that returns makeArrayRef(config->versionDefinitions).slice(2)); ? Looking at this line in isolation it is not obvious why?

ELF/Writer.cpp
399 ↗(On Diff #213238)

A similar comment to the slice(2). It isn't obvious from the line why the > 2 is here. Not a big problem but possibly worth a comment.

grimar added a comment.Aug 5 2019, 3:15 AM

Generally I also think it is fine.
A few comments from me (some of them seems were already mentioned by Peter).

ELF/Driver.cpp
1021 ↗(On Diff #213238)

What about accessing here and elsewhere as config->versionDefinitions[VER_NDX_LOCAL] and config->versionDefinitions[VER_NDX_GLOBAL]? I.e. idea is to get rid of magic values + increase the readability.

ELF/ScriptParser.cpp
1348 ↗(On Diff #213238)

During my work on LLD I was often asked to avoid using STL algorithms in favor of straightforward loops.

Perhaps I would do this here too now, for consistency with the rest of LLD code.

ELF/SyntheticSections.cpp
1166 ↗(On Diff #213238)

, plus 1 looks a bit strange here IMO because code has -1.
I understand this is because of "-2 + 1 == -1", but would be better if comment described this explicitly probably.
(i.e. it is assumed that reader knows there are exactly 2 more (VER_NDX_LOCAL + VER_NDX_GLOBAL) definitions in this array,
but this is not obvious, probably). Though may be it just me, so feel free to ignore.

ELF/Writer.cpp
399 ↗(On Diff #213238)

Needs a comment about what is 2.

test/ELF/version-script-reassign-glob.s
16 ↗(On Diff #213238)

CHECK -> FOO probably for consistency.

MaskRay updated this revision to Diff 213320.Aug 5 2019, 4:43 AM

Address review comments

Add a helper:

static inline ArrayRef<VersionDefinition> versionDefinitionsNotLocalOrGlobal() {
  return llvm::makeArrayRef(config->versionDefinitions).slice(2);
}

This turns out to simplify several places (.slice(2), .size() > 2, etc).

MaskRay marked 6 inline comments as done.Aug 5 2019, 4:51 AM

Overall looks good to me. I've got a few suggestions on the refactoring. One other thing that might be worth doing to make this easier to review is to split it into two patches:

  • A refactoring change that doesn't change the wildcard behaviour.
  • The change to the wildcard behaviour.

Not got a strong opinion on that now I've gone through it.

I starts from two patches :/ 1) merge config->versionScript{Locals,Globals} into config->versionDefinitions 2) delete defaultSymbolVersion. Then I realized just 1) would fix the ld.bfd/gold incompatibility though the code was a big uglier in readAnonymousDeclaration and readVersionDeclaration. So I think probably I should just merge 2) into 1)...

ELF/SymbolTable.cpp
207 ↗(On Diff #213238)

Here 0 (any number other than -1 works) is an arbitrary number to indicate the version has been assigned. Added a comment about this.

This change is why we can detect { global: foo; }; and V1 { global: foo}; duplicate assignment now.

MaskRay updated this revision to Diff 213322.Aug 5 2019, 4:53 AM

for (SymbolVersion &ver : v.patterns)
->
for (SymbolVersion &pat : v.patterns)

MaskRay marked 7 inline comments as done.Aug 5 2019, 4:56 AM
MaskRay updated this revision to Diff 213324.Aug 5 2019, 4:56 AM

Address review comment: CHECK -> FOO probably for consistency.

Harbormaster completed remote builds in B36120: Diff 213324.
grimar added a comment.Aug 5 2019, 5:20 AM

Minor nit is below and I do not have any more comments atm probably, looks good to me.

ELF/Config.h
310 ↗(On Diff #213324)

versionDefinitionsNotLocalOrGlobal looks a bit too long name.
May be namedVersionDefs or something else would be better?

Thanks for the update. I've not got any more comments.

ruiu added inline comments.Aug 5 2019, 6:04 AM
ELF/Config.h
310 ↗(On Diff #213324)

I feel the same. How about getUserDefinedVersions? Also I feel that this function needs a comment, as the magic number 2 is not obvious.

MaskRay updated this revision to Diff 213344.Aug 5 2019, 6:29 AM
MaskRay retitled this revision from [ELF] Consistently priority non-* wildcards overs "*" in version scripts to [ELF] Consistently prioritize non-* wildcards overs "*" in version scripts.

Rename the helper from versionDefinitionsNotLocalOrGlobal to namedVersionDefs

MaskRay updated this revision to Diff 213346.Aug 5 2019, 6:37 AM

Add a comment to namedVersionDefs

MaskRay marked 2 inline comments as done.Aug 5 2019, 6:39 AM
MaskRay added inline comments.
ELF/Config.h
310 ↗(On Diff #213324)

I went with namedVersionDefs, because global and local are sometimes referred to as anonymous, so named seems a good name. Will happy to change if there is a better name.

ruiu accepted this revision.Aug 5 2019, 6:46 AM

LGTM

This revision is now accepted and ready to land.Aug 5 2019, 6:46 AM
This revision was automatically updated to reflect the committed changes.