summaryrefslogtreecommitdiffstats
path: root/lld/ELF/SymbolTable.cpp
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2019-08-05 14:31:39 +0000
committerFangrui Song <maskray@google.com>2019-08-05 14:31:39 +0000
commite28a70daf4e685ed4b50619fb30983b4464fae1c (patch)
tree4a5bb115f6a58f96669f788bb0de95aac9861eea /lld/ELF/SymbolTable.cpp
parent0039f87fa5c9b621d2e3aee0e79f1bab297cd5ef (diff)
downloadbcm5719-llvm-e28a70daf4e685ed4b50619fb30983b4464fae1c.tar.gz
bcm5719-llvm-e28a70daf4e685ed4b50619fb30983b4464fae1c.zip
[ELF] Consistently prioritize non-* wildcards overs "*" in version scripts
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. Reviewed By: ruiu Differential Revision: https://reviews.llvm.org/D65716 llvm-svn: 367869
Diffstat (limited to 'lld/ELF/SymbolTable.cpp')
-rw-r--r--lld/ELF/SymbolTable.cpp59
1 files changed, 30 insertions, 29 deletions
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 3faeed8c2bd..9463aeeba99 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -73,7 +73,7 @@ Symbol *SymbolTable::insert(StringRef name) {
sym->setName(name);
sym->symbolKind = Symbol::PlaceholderKind;
- sym->versionId = config->defaultSymbolVersion;
+ sym->versionId = VER_NDX_GLOBAL;
sym->visibility = STV_DEFAULT;
sym->isUsedInRegularObj = false;
sym->exportDynamic = false;
@@ -192,7 +192,7 @@ void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
return "VER_NDX_LOCAL";
if (ver == VER_NDX_GLOBAL)
return "VER_NDX_GLOBAL";
- return ("version '" + config->versionDefinitions[ver - 2].name + "'").str();
+ return ("version '" + config->versionDefinitions[ver].name + "'").str();
};
// Assign the version.
@@ -203,8 +203,12 @@ void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
if (sym->getName().contains('@'))
continue;
- if (sym->versionId == config->defaultSymbolVersion)
+ // If the version has not been assigned, verdefIndex is -1. Use an arbitrary
+ // number (0) to indicate the version has been assigned.
+ if (sym->verdefIndex == UINT32_C(-1)) {
+ sym->verdefIndex = 0;
sym->versionId = versionId;
+ }
if (sym->versionId == versionId)
continue;
@@ -214,15 +218,14 @@ void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
}
void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId) {
- if (!ver.hasWildcard)
- return;
-
// Exact matching takes precendence over fuzzy matching,
// so we set a version to a symbol only if no version has been assigned
// to the symbol. This behavior is compatible with GNU.
- for (Symbol *b : findAllByVersion(ver))
- if (b->versionId == config->defaultSymbolVersion)
- b->versionId = versionId;
+ for (Symbol *sym : findAllByVersion(ver))
+ if (sym->verdefIndex == UINT32_C(-1)) {
+ sym->verdefIndex = 0;
+ sym->versionId = versionId;
+ }
}
// This function processes version scripts by updating the versionId
@@ -233,26 +236,24 @@ void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId) {
void SymbolTable::scanVersionScript() {
// First, we assign versions to exact matching symbols,
// i.e. version definitions not containing any glob meta-characters.
- for (SymbolVersion &ver : config->versionScriptGlobals)
- assignExactVersion(ver, VER_NDX_GLOBAL, "global");
- for (SymbolVersion &ver : config->versionScriptLocals)
- assignExactVersion(ver, VER_NDX_LOCAL, "local");
for (VersionDefinition &v : config->versionDefinitions)
- for (SymbolVersion &ver : v.globals)
- assignExactVersion(ver, v.id, v.name);
-
- // Next, we assign versions to fuzzy matching symbols,
- // i.e. version definitions containing glob meta-characters.
- for (SymbolVersion &ver : config->versionScriptGlobals)
- assignWildcardVersion(ver, VER_NDX_GLOBAL);
- for (SymbolVersion &ver : config->versionScriptLocals)
- assignWildcardVersion(ver, VER_NDX_LOCAL);
-
- // Note that because the last match takes precedence over previous matches,
- // we iterate over the definitions in the reverse order.
+ for (SymbolVersion &pat : v.patterns)
+ assignExactVersion(pat, v.id, v.name);
+
+ // Next, assign versions to wildcards that are not "*". Note that because the
+ // last match takes precedence over previous matches, we iterate over the
+ // definitions in the reverse order.
for (VersionDefinition &v : llvm::reverse(config->versionDefinitions))
- for (SymbolVersion &ver : v.globals)
- assignWildcardVersion(ver, v.id);
+ for (SymbolVersion &pat : v.patterns)
+ if (pat.hasWildcard && pat.name != "*")
+ assignWildcardVersion(pat, v.id);
+
+ // Then, assign versions to "*". In GNU linkers they have lower priority than
+ // other wildcards.
+ for (VersionDefinition &v : config->versionDefinitions)
+ for (SymbolVersion &pat : v.patterns)
+ if (pat.hasWildcard && pat.name == "*")
+ assignWildcardVersion(pat, v.id);
// Symbol themselves might know their versions because symbols
// can contain versions in the form of <name>@<version>.
@@ -262,7 +263,7 @@ void SymbolTable::scanVersionScript() {
// isPreemptible is false at this point. To correctly compute the binding of a
// Defined (which is used by includeInDynsym()), we need to know if it is
- // VER_NDX_LOCAL or not. If defaultSymbolVersion is VER_NDX_LOCAL, we should
- // compute symbol versions before handling --dynamic-list.
+ // VER_NDX_LOCAL or not. Compute symbol versions before handling
+ // --dynamic-list.
handleDynamicList();
}
OpenPOWER on IntegriCloud