[lld] 7a7cea9 - [ELF] Version script: simplify wildcard matching. NFC (#223202)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 12 21:32:28 PDT 2026
Author: Fangrui Song
Date: 2026-09-13T04:32:23Z
New Revision: 7a7cea921c3e450903b57e5f4b2992f1dce4c410
URL: https://github.com/llvm/llvm-project/commit/7a7cea921c3e450903b57e5f4b2992f1dce4c410
DIFF: https://github.com/llvm/llvm-project/commit/7a7cea921c3e450903b57e5f4b2992f1dce4c410.diff
LOG: [ELF] Version script: simplify wildcard matching. NFC (#223202)
Replace a loop over non-"*" wildcard patterns and another loop over "*"
with a single loop that calls the inlined
`SymbolTable::assignWildcardVersion`.
Added:
Modified:
lld/ELF/SymbolTable.cpp
lld/ELF/SymbolTable.h
Removed:
################################################################################
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 6841b5ca15a5d..810cb6df5afcd 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -234,16 +234,14 @@ bool SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId) {
return !syms.empty();
}
-void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId) {
- // Exact matching takes precedence 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 *sym : findAllByVersion(ver, /*includeNonDefault=*/false))
- if (!sym->versionScriptAssigned) {
- sym->versionScriptAssigned = true;
- sym->versionId = versionId;
- }
-}
+namespace {
+struct WildcardPattern {
+ SymbolVersion ver;
+ uint16_t versionId;
+ WildcardPattern(const SymbolVersion &ver, uint16_t versionId)
+ : ver(ver), versionId(versionId) {}
+};
+} // namespace
// This function processes version scripts by updating the versionId
// member of symbols.
@@ -276,51 +274,55 @@ void SymbolTable::scanVersionScript() {
assignExact(pat, VER_NDX_LOCAL, "local");
}
- // 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(ctx.arg.versionDefinitions)) {
- for (SymbolVersion &pat : v.nonLocalPatterns)
- if (pat.hasWildcard && pat.name != "*")
- assignWildcardVersion(pat, v.id);
- for (SymbolVersion &pat : v.localPatterns)
- if (pat.hasWildcard && pat.name != "*")
- assignWildcardVersion(pat, VER_NDX_LOCAL);
- }
-
- // Then, assign versions to "*". In GNU linkers they have lower priority than
- // other wildcards.
+ // Next, collect wildcards in precedence order, where "*" patterns have the
+ // lowest precedence in GNU ld. Because the last match takes precedence over
+ // previous matches, we iterate over the definitions in the reverse order.
+ SmallVector<WildcardPattern, 0> pats, asterisks;
bool globalAsteriskFound = false;
bool localAsteriskFound = false;
bool asteriskReported = false;
- auto assignAsterisk = [&](SymbolVersion &pat, VersionDefinition *ver,
- bool isLocal) {
- if (!asteriskReported) {
- if ((isLocal && globalAsteriskFound) ||
- (!isLocal && localAsteriskFound)) {
- Warn(ctx)
- << "wildcard pattern '*' is used for both 'local' and 'global' "
- "scopes in version script";
- asteriskReported = true;
- } else if (!isLocal && globalAsteriskFound) {
- Warn(ctx) << "wildcard pattern '*' is used for multiple version "
- "definitions in "
- "version script";
- asteriskReported = true;
- } else {
- localAsteriskFound = isLocal;
- globalAsteriskFound = !isLocal;
+ for (VersionDefinition &v : llvm::reverse(ctx.arg.versionDefinitions)) {
+ for (bool isLocal : {false, true}) {
+ uint16_t id = isLocal ? VER_NDX_LOCAL : v.id;
+ for (SymbolVersion &pat :
+ isLocal ? v.localPatterns : v.nonLocalPatterns) {
+ if (!pat.hasWildcard)
+ continue;
+ if (pat.name != "*") {
+ pats.emplace_back(pat, id);
+ continue;
+ }
+ if (!asteriskReported) {
+ if ((isLocal && globalAsteriskFound) ||
+ (!isLocal && localAsteriskFound)) {
+ Warn(ctx)
+ << "wildcard pattern '*' is used for both 'local' and 'global' "
+ "scopes in version script";
+ asteriskReported = true;
+ } else if (!isLocal && globalAsteriskFound) {
+ Warn(ctx) << "wildcard pattern '*' is used for multiple version "
+ "definitions in version script";
+ asteriskReported = true;
+ } else {
+ localAsteriskFound = isLocal;
+ globalAsteriskFound = !isLocal;
+ }
+ }
+ asterisks.emplace_back(pat, id);
+ }
+ }
+ }
+ pats.append(asterisks);
+
+ // Exact matching takes precedence over wildcard matching, so a wildcard
+ // assigns a version only if none has been assigned.
+ for (auto &pat : pats) {
+ for (Symbol *sym : findAllByVersion(pat.ver, /*includeNonDefault=*/false)) {
+ if (!sym->versionScriptAssigned) {
+ sym->versionScriptAssigned = true;
+ sym->versionId = pat.versionId;
}
}
- assignWildcardVersion(pat, isLocal ? (uint16_t)VER_NDX_LOCAL : ver->id);
- };
- for (VersionDefinition &v : llvm::reverse(ctx.arg.versionDefinitions)) {
- for (SymbolVersion &pat : v.nonLocalPatterns)
- if (pat.hasWildcard && pat.name == "*")
- assignAsterisk(pat, &v, false);
- for (SymbolVersion &pat : v.localPatterns)
- if (pat.hasWildcard && pat.name == "*")
- assignAsterisk(pat, &v, true);
}
// Handle --dynamic-list. If a specified symbol is also matched by local: in a
diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h
index e485ad2edb000..058684bf84af2 100644
--- a/lld/ELF/SymbolTable.h
+++ b/lld/ELF/SymbolTable.h
@@ -88,7 +88,6 @@ class SymbolTable {
llvm::StringMap<SmallVector<Symbol *, 0>> &getDemangledSyms();
bool assignExactVersion(SymbolVersion ver, uint16_t versionId);
- void assignWildcardVersion(SymbolVersion ver, uint16_t versionId);
Ctx &ctx;
More information about the llvm-commits
mailing list