This is an archive of the discontinued LLVM Phabricator instance.

[ELF] - Fixed incorrect logic of version assignments when mixing wildcards with values matching.
ClosedPublic

Authored by grimar on Jun 30 2016, 7:56 AM.

Details

Summary

Previously we had incorrect logic here. Imagine we would have the next script:

LIBSAMPLE_1.0
{
  global:
   a_2;
 local:
  *;
};

LIBSAMPLE_2.0
{
  global:
   a*;
};

According to previous logic it would assign version 1 to a_2 and then
would try to reassign it to version 2 because of applying wildcard a*.
And show a warning about that.

Generally Ian Lance Tailor wrote about next rules that should be applied:
(http://www.airs.com/blog/archives/300)

Here are the current rules for gold:

  • If there is an exact match for the mangled name, we use it.

If there is more than one exact match, we give a warning, and we use the first tag in the script which matches.
If a symbol has an exact match as both global and local for the same version tag, we give an error.

  • Otherwise, we look for an extern C++ or an extern Java exact match. If we find an exact match, we use it.

If there is more than one exact match, we give a warning, and we use the first tag in the script which matches.
If a symbol has an exact match as both global and local for the same version tag, we give an error.

  • Otherwise, we look through the wildcard patterns, ignoring “*” patterns. We look through the version tags in reverse order. For each version tag, we look through the global patterns and then the local patterns. We use the first match we find (i.e., the last matching version tag in the file).
  • Otherwise, we use the “*” pattern if there is one. We give a warning if there are multiple “*” patterns.

Patch makes wildcard matching to be in revered order and to follow after the regular naming matching.

Diff Detail

Repository
rL LLVM

Event Timeline

grimar updated this revision to Diff 62361.Jun 30 2016, 7:56 AM
grimar retitled this revision from to [ELF] - Fixed incorrect logic of version assignments when mixing wildcards with values matching..
grimar updated this object.
grimar added reviewers: ruiu, rafael.
grimar added subscribers: llvm-commits, grimar.
grimar updated this revision to Diff 62370.Jun 30 2016, 8:29 AM

That probably looks a bit better. May be a wrong place for Reverser,
or may be we have something like that in LLVM already ? I did not find.

ruiu added inline comments.Jun 30 2016, 11:45 PM
ELF/Config.h
40 ↗(On Diff #62370)

I think it's not worth to store this property as a member of this variable. You can always compute it from Name when needed.

ELF/SymbolTable.cpp
565–566 ↗(On Diff #62370)

This function should probably be inlined to the place where you call it because non-wildcard patterns and wildcard patterns shares less code. For example, you don't need to call findAll for non-wildcards (but instead you want to call find). You don't want to issue a warning if non-wildcards. So this function is not actually common code for both cases.

628 ↗(On Diff #62370)

Reverse is overkill. You can just iterate in the reverse order by this.

for (size_t I = Config->SymbolVersions.size() - 1; I != 0; --I) {
  VersionSymbol &Sym = Config->SymbolVersions[I];
  ...
}
grimar added inline comments.Jul 1 2016, 2:36 AM
ELF/Config.h
40 ↗(On Diff #62370)

Idea here was to avoid several searches of "*?". Since I do 2 iterations now,
one for wildcarded names and one for not.

Also I planned to use this struct to add the flag
IsExternCpp or something for externs handling patch.

ruiu added inline comments.Jul 1 2016, 2:54 AM
ELF/Config.h
40 ↗(On Diff #62370)

Yes, I understand that, but finding "*?" is pretty cheap, and number of symbols in version scripts is not that large.

grimar added inline comments.Jul 1 2016, 3:01 AM
ELF/Config.h
40 ↗(On Diff #62370)

Ok.
So relative to possible patch for externs:
What about possible list of extern c++ symbols ? Do you suggest to make a separate array for them ?

ruiu added inline comments.Jul 1 2016, 3:37 AM
ELF/Config.h
40 ↗(On Diff #62370)

I didn't suggest that -- IsExternCpp may make sense.

grimar added inline comments.Jul 1 2016, 3:44 AM
ELF/Config.h
40 ↗(On Diff #62370)

Ok. So I am removing HasWildcard and VersionSymbol from this patch, and will probably add VersionSymbol back with IsExternCpp field for externs patch then.

ELF/SymbolTable.cpp
628 ↗(On Diff #62370)

Sure I can :) That just looks a bit different from loop above making me think it do something special, when it is not.
Will fix.

ruiu added inline comments.Jul 1 2016, 3:47 AM
ELF/SymbolTable.cpp
628 ↗(On Diff #62370)

I'd rewrite the above for-loop with an explicit index as well because &V - Config->SymbolVersions.data() is not intuitive.

grimar added inline comments.Jul 1 2016, 3:48 AM
ELF/SymbolTable.cpp
628 ↗(On Diff #62370)

ok

grimar updated this revision to Diff 62482.Jul 1 2016, 4:41 AM
  • Addressed review comments.
ELF/SymbolTable.cpp
565–566 ↗(On Diff #62370)

Done.

grimar updated this revision to Diff 62483.Jul 1 2016, 4:43 AM
  • minor changes.
grimar updated this revision to Diff 62494.Jul 1 2016, 7:40 AM
  • Restored testcase removed by mistake previously.
ruiu added inline comments.Jul 2 2016, 12:03 AM
ELF/SymbolTable.cpp
581 ↗(On Diff #62494)

Define hasWildcard(StringRef S) and use early continue.

if (hasWildcard(Name))
  continue;
601 ↗(On Diff #62494)

Early continue.

602–603 ↗(On Diff #62494)
for (SymbolBody *B : findAll(Name))
grimar updated this revision to Diff 62663.Jul 4 2016, 4:19 AM
grimar marked 3 inline comments as done.
  • Addressed review comments.
ELF/SymbolTable.cpp
581 ↗(On Diff #62494)

Done.

601 ↗(On Diff #62494)

Done.

602–603 ↗(On Diff #62494)

Done.

emaste added a subscriber: emaste.Jul 4 2016, 6:38 AM
ruiu accepted this revision.Jul 6 2016, 2:13 PM
ruiu edited edge metadata.

LGTM with a few nits.

ELF/SymbolTable.cpp
599 ↗(On Diff #62663)

You don't have to do this in this patch, but + 2 seems too magical and needs to be handled in a better way. I think it is better to add VersionId member to Version struct and store the version id to that member.

603 ↗(On Diff #62663)
I >= 0
This revision is now accepted and ready to land.Jul 6 2016, 2:13 PM
grimar added inline comments.Jul 6 2016, 11:45 PM
ELF/SymbolTable.cpp
603 ↗(On Diff #62663)

This will not work. If for Config->SymbolVersions.size() == 1, for example,
first iteration will pass, but then since "I" is unsigned it will be equal 0xffffffff and loop will continue,
when it should terminate.
Changing to "I > 0" will not work as expected either.

grimar added inline comments.Jul 7 2016, 12:32 AM
ELF/SymbolTable.cpp
599 ↗(On Diff #62663)

I`ll prepare a patch.

This revision was automatically updated to reflect the committed changes.