blob: 70c79d26880420df5255a136bb43e047cedb7a8b [file] [log] [blame]
From be8275753fe23fb56c4cb5127695dad540b9053c Mon Sep 17 00:00:00 2001
From: Fangrui Song <maskray@google.com>
Date: Thu, 11 Jul 2019 11:16:44 +0000
Subject: [PATCH] [ELF] Warn rather than error when duplicate version
assignments occur
In lvm2, libdevmapper.so is linked with a version script with duplicate
version assignments:
DM_1_02_138 { global: ... dm_bitset_parse_list; ... };
DM_1_02_129 { global: ... dm_bitset_parse_list; ... };
ld.bfd silently accepts this while gold issues a warning. We currently
error, thus inhibit producing the executable. Change the error to
warning to allow this case, and improve the message.
There are some cases where ld.bfd error
`anonymous version tag cannot be combined with other version tags`
but we just warn. It is probably OK for now.
Reviewed By: grimar, ruiu
Differential Revision: https://reviews.llvm.org/D64549
llvm-svn: 365759
---
lld/ELF/SymbolTable.cpp | 19 ++++++++++++----
lld/test/ELF/version-script-reassign.s | 31 ++++++++++++++++++++++++++
lld/test/ELF/version-script.s | 6 -----
3 files changed, 46 insertions(+), 10 deletions(-)
create mode 100644 lld/test/ELF/version-script-reassign.s
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 0fd0eab9bda..252e1201c0c 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -201,6 +201,14 @@ void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
return;
}
+ auto getName = [](uint16_t ver) -> std::string {
+ if (ver == VER_NDX_LOCAL)
+ return "VER_NDX_LOCAL";
+ if (ver == VER_NDX_GLOBAL)
+ return "VER_NDX_GLOBAL";
+ return ("version '" + config->versionDefinitions[ver - 2].name + "'").str();
+ };
+
// Assign the version.
for (Symbol *sym : syms) {
// Skip symbols containing version info because symbol versions
@@ -209,10 +217,13 @@ void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
if (sym->getName().contains('@'))
continue;
- if (sym->versionId != config->defaultSymbolVersion &&
- sym->versionId != versionId)
- error("duplicate symbol '" + ver.name + "' in version script");
- sym->versionId = versionId;
+ if (sym->versionId == config->defaultSymbolVersion)
+ sym->versionId = versionId;
+ if (sym->versionId == versionId)
+ continue;
+
+ warn("attempt to reassign symbol '" + ver.name + "' of " +
+ getName(sym->versionId) + " to " + getName(versionId));
}
}
diff --git a/lld/test/ELF/version-script-reassign.s b/lld/test/ELF/version-script-reassign.s
new file mode 100644
index 00000000000..e2413295cc4
--- /dev/null
+++ b/lld/test/ELF/version-script-reassign.s
@@ -0,0 +1,31 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+# RUN: echo '{ local: foo; };' > %tl.ver
+# RUN: echo '{ global: foo; local: *; };' > %tg.ver
+# RUN: echo 'V1 { global: foo; };' > %t1.ver
+# RUN: echo 'V2 { global: foo; };' > %t2.ver
+
+## Note, ld.bfd errors on the two cases.
+# RUN: ld.lld -shared %t.o --version-script %tl.ver --version-script %t1.ver \
+# RUN: -o %t.so 2>&1 | FileCheck --check-prefix=LOCAL %s
+# RUN: llvm-readelf --dyn-syms %t.so | FileCheck --check-prefix=LOCAL-SYM %s
+# RUN: ld.lld -shared %t.o --version-script %tg.ver --version-script %t1.ver \
+# RUN: -o %t.so 2>&1 | FileCheck --check-prefix=GLOBAL %s
+# RUN: llvm-readelf --dyn-syms %t.so | FileCheck --check-prefix=GLOBAL-SYM %s
+
+## Note, ld.bfd silently accepts this case.
+# RUN: ld.lld -shared %t.o --version-script %t1.ver --version-script %t2.ver \
+# RUN: -o %t.so 2>&1 | FileCheck --check-prefix=V1-WARN %s
+# RUN: llvm-readelf --dyn-syms %t.so | FileCheck --check-prefix=V1-SYM %s
+
+# LOCAL: warning: attempt to reassign symbol 'foo' of VER_NDX_LOCAL to version 'V1'
+# LOCAL-SYM-NOT: foo
+
+# GLOBAL: warning: attempt to reassign symbol 'foo' of VER_NDX_GLOBAL to version 'V1'
+# GLOBAL-SYM: foo{{$}}
+
+# V1-WARN: warning: attempt to reassign symbol 'foo' of version 'V1' to version 'V2'
+# V1-SYM: foo@@V1
+
+.globl foo
+foo:
diff --git a/lld/test/ELF/version-script.s b/lld/test/ELF/version-script.s
index bba503b2d2e..8bbd769d33f 100644
--- a/lld/test/ELF/version-script.s
+++ b/lld/test/ELF/version-script.s
@@ -32,12 +32,6 @@
# RUN: FileCheck -check-prefix=ERR2 %s
# ERR2: EOF expected, but got VERSION_2.0
-# RUN: echo "VERSION_1.0 { global: foo1; local: *; };" > %t6.script
-# RUN: echo "VERSION_2.0 { global: foo1; local: *; };" >> %t6.script
-# RUN: not ld.lld --version-script %t6.script -shared %t.o %t2.so -o /dev/null 2>&1 | \
-# RUN: FileCheck -check-prefix=ERR3 %s
-# ERR3: duplicate symbol 'foo1' in version script
-
# RUN: echo "{ foo1; foo2; };" > %t.list
# RUN: ld.lld --version-script %t.script --dynamic-list %t.list %t.o %t2.so -o %t2
# RUN: llvm-readobj %t2 > /dev/null
--
2.22.0.657.g960e92d24f-goog