summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2017-01-18 14:43:01 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2017-01-18 14:43:01 +0000
commit1fc8b507770663043a85de766d29afa0f5aa653b (patch)
treecd9612cd3e263eef0367f3d6efba870cd7656d6b
parent72cd787e22843b80addacd48617572e2a6a8d24b (diff)
Give priority to linker scripts over preemption. LLD exports symbols that are also present in used shared libraries to make sure they are preempted at runtime. That is a reasonable default, but we must allow for it to be overwritten with linker script. If we don't, libraries that expect to be able to hide a c++ delete operator will fail. This should fix the firebird build. llvm-svn: 292370
-rw-r--r--lld/ELF/SymbolTable.cpp6
-rw-r--r--lld/ELF/Symbols.cpp3
-rw-r--r--lld/test/ELF/gc-sections-shared.s9
-rw-r--r--lld/test/ELF/version-script-hide-so-symbol.s28
4 files changed, 31 insertions, 15 deletions
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 6afe3dde9bab..b3e91c9f32e1 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -426,12 +426,8 @@ void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name,
std::tie(S, WasInserted) =
insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true, F);
// Make sure we preempt DSO symbols with default visibility.
- if (Sym.getVisibility() == STV_DEFAULT) {
+ if (Sym.getVisibility() == STV_DEFAULT)
S->ExportDynamic = true;
- // Exporting preempting symbols takes precedence over linker scripts.
- if (S->VersionId == VER_NDX_LOCAL)
- S->VersionId = VER_NDX_GLOBAL;
- }
if (WasInserted || isa<Undefined<ELFT>>(S->body())) {
replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef);
if (!S->isWeak())
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index 289bc18487a8..7c2b5fb959cc 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -299,7 +299,8 @@ uint8_t Symbol::computeBinding() const {
return Binding;
if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
return STB_LOCAL;
- if (VersionId == VER_NDX_LOCAL && !body()->isUndefined())
+ const SymbolBody *Body = body();
+ if (VersionId == VER_NDX_LOCAL && !Body->isUndefined() && !Body->isShared())
return STB_LOCAL;
if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE)
return STB_GLOBAL;
diff --git a/lld/test/ELF/gc-sections-shared.s b/lld/test/ELF/gc-sections-shared.s
index f1ac9cd345d4..a88f2b443479 100644
--- a/lld/test/ELF/gc-sections-shared.s
+++ b/lld/test/ELF/gc-sections-shared.s
@@ -19,15 +19,6 @@
# CHECK-NEXT: Section: Undefined (0x0)
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: bar
-# CHECK-NEXT: Value:
-# CHECK-NEXT: Size:
-# CHECK-NEXT: Binding: Global
-# CHECK-NEXT: Type:
-# CHECK-NEXT: Other:
-# CHECK-NEXT: Section: .text
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
# CHECK-NEXT: Name: bar2
# CHECK-NEXT: Value:
# CHECK-NEXT: Size:
diff --git a/lld/test/ELF/version-script-hide-so-symbol.s b/lld/test/ELF/version-script-hide-so-symbol.s
new file mode 100644
index 000000000000..b4f58be06de7
--- /dev/null
+++ b/lld/test/ELF/version-script-hide-so-symbol.s
@@ -0,0 +1,28 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld -shared %t.o -o %t2.so
+# RUN: echo "{ local: *; };" > %t.script
+# RUN: ld.lld --version-script %t.script -shared %t.o %t2.so -o %t.so
+# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s
+
+# The symbol foo must be hidden. This matches bfd and gold and is
+# required to make it possible for a c++ library to hide its own
+# operator delete.
+
+# CHECK: DynamicSymbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: @ (0)
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Local
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+ .global foo
+foo:
+ nop
+