Add support for anonymous local symbols.
This actually simplifies the code a bit as now all local symbols are
handled uniformly.
This should fix the build of www/webkit2-gtk3.
llvm-svn: 291569
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 59ef36c..887ca12 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -1014,6 +1014,7 @@
void readAnonymousDeclaration();
void readVersionDeclaration(StringRef VerStr);
std::vector<SymbolVersion> readSymbols();
+ void readLocals();
ScriptConfiguration &Opt = *ScriptConfig;
bool IsUnderSysroot;
@@ -1861,19 +1862,24 @@
if (consume("global:") || peek() != "local:")
Config->VersionScriptGlobals = readSymbols();
- // Next, read local symbols.
- if (consume("local:")) {
- if (consume("*")) {
- Config->DefaultSymbolVersion = VER_NDX_LOCAL;
- expect(";");
- } else {
- setError("local symbol list for anonymous version is not supported");
- }
- }
+ readLocals();
expect("}");
expect(";");
}
+void ScriptParser::readLocals() {
+ if (!consume("local:"))
+ return;
+ std::vector<SymbolVersion> Locals = readSymbols();
+ for (SymbolVersion V : Locals) {
+ if (V.Name == "*") {
+ Config->DefaultSymbolVersion = VER_NDX_LOCAL;
+ continue;
+ }
+ Config->VersionScriptLocals.push_back(V);
+ }
+}
+
// Reads a list of symbols, e.g. "VerStr { global: foo; bar; local: *; };".
void ScriptParser::readVersionDeclaration(StringRef VerStr) {
// Identifiers start at 2 because 0 and 1 are reserved
@@ -1885,16 +1891,7 @@
if (consume("global:") || peek() != "local:")
Config->VersionDefinitions.back().Globals = readSymbols();
- // Read local symbols.
- if (consume("local:")) {
- if (consume("*")) {
- Config->DefaultSymbolVersion = VER_NDX_LOCAL;
- expect(";");
- } else {
- for (SymbolVersion V : readSymbols())
- Config->VersionScriptLocals.push_back(V);
- }
- }
+ readLocals();
expect("}");
// Each version may have a parent version. For example, "Ver2"
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index f08fa62..6afe3dd 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -605,19 +605,16 @@
// If there's only one anonymous version definition in a version
// script file, the script does not actually define any symbol version,
-// but just specifies symbols visibilities. We assume that the script was
-// in the form of { global: foo; bar; local *; }. So, local is default.
-// In this function, we make specified symbols global.
+// but just specifies symbols visibilities.
template <class ELFT> void SymbolTable<ELFT>::handleAnonymousVersion() {
- for (SymbolVersion &Ver : Config->VersionScriptGlobals) {
- if (Ver.HasWildcard) {
- for (SymbolBody *B : findAllByVersion(Ver))
- B->symbol()->VersionId = VER_NDX_GLOBAL;
- continue;
- }
- for (SymbolBody *B : findByVersion(Ver))
- B->symbol()->VersionId = VER_NDX_GLOBAL;
- }
+ for (SymbolVersion &Ver : Config->VersionScriptGlobals)
+ assignExactVersion(Ver, VER_NDX_GLOBAL, "global");
+ for (SymbolVersion &Ver : Config->VersionScriptGlobals)
+ assignWildcardVersion(Ver, VER_NDX_GLOBAL);
+ for (SymbolVersion &Ver : Config->VersionScriptLocals)
+ assignExactVersion(Ver, VER_NDX_LOCAL, "local");
+ for (SymbolVersion &Ver : Config->VersionScriptLocals)
+ assignWildcardVersion(Ver, VER_NDX_LOCAL);
}
// Set symbol versions to symbols. This function handles patterns
@@ -673,10 +670,7 @@
Sym->body()->parseSymbolVersion();
// Handle edge cases first.
- if (!Config->VersionScriptGlobals.empty()) {
- handleAnonymousVersion();
- return;
- }
+ handleAnonymousVersion();
if (Config->VersionDefinitions.empty())
return;
@@ -687,8 +681,6 @@
// First, we assign versions to exact matching symbols,
// i.e. version definitions not containing any glob meta-characters.
- 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);
@@ -697,8 +689,6 @@
// i.e. version definitions containing glob meta-characters.
// Note that because the last match takes precedence over previous matches,
// we iterate over the definitions in the reverse order.
- for (SymbolVersion &Ver : Config->VersionScriptLocals)
- assignWildcardVersion(Ver, VER_NDX_LOCAL);
for (VersionDefinition &V : llvm::reverse(Config->VersionDefinitions))
for (SymbolVersion &Ver : V.Globals)
assignWildcardVersion(Ver, V.Id);
diff --git a/lld/test/ELF/version-script-anonymous-local.s b/lld/test/ELF/version-script-anonymous-local.s
new file mode 100644
index 0000000..dfe52b8
--- /dev/null
+++ b/lld/test/ELF/version-script-anonymous-local.s
@@ -0,0 +1,44 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+
+# RUN: echo "{ global: foo; local: bar; };" > %t.script
+# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
+# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s
+
+# CHECK: DynamicSymbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name:
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Binding:
+# CHECK-NEXT: Type:
+# CHECK-NEXT: Other:
+# CHECK-NEXT: Section:
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: foo
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type:
+# CHECK-NEXT: Other:
+# CHECK-NEXT: Section:
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: zed
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type:
+# CHECK-NEXT: Other:
+# CHECK-NEXT: Section:
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+
+.global foo
+foo:
+.global bar
+bar:
+.global zed
+zed: