aboutsummaryrefslogtreecommitdiff
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)
downloadllvm-1fc8b507770663043a85de766d29afa0f5aa653b.zip
llvm-1fc8b507770663043a85de766d29afa0f5aa653b.tar.gz
llvm-1fc8b507770663043a85de766d29afa0f5aa653b.tar.bz2
Port r292146.llvmorg-4.0.0-rc1
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 6afe3dd..b3e91c9 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 289bc18..7c2b5fb 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 f1ac9cd..a88f2b4 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 0000000..b4f58be
--- /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
+