summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2017-04-04 20:03:34 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2017-04-04 20:03:34 +0000
commit8465d083921c56ac35d2c292da316dd470641ef2 (patch)
treea7e56e836ccbe376a1294cb5f324935b015e0e02
parent08f943c5630d8ee31d6a93227171d2f05db59e62 (diff)
downloadbcm5719-llvm-8465d083921c56ac35d2c292da316dd470641ef2.tar.gz
bcm5719-llvm-8465d083921c56ac35d2c292da316dd470641ef2.zip
Don't resolve hidden undef to a DSO.
The ELF spec says: all of the non-default visibility attributes, when applied to a symbol reference, imply that a definition to satisfy that reference must be provided within the current executable or shared object. But we were trying to resolve those undef references to shared symbols. That causes odd results like creating a got entry with a relocation pointing to 0. llvm-svn: 299464
-rw-r--r--lld/ELF/SymbolTable.cpp14
-rw-r--r--lld/test/ELF/hidden-vis-shared.s18
2 files changed, 29 insertions, 3 deletions
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 2b0a7a17974..42b4fdc26fa 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -251,9 +251,13 @@ Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, bool IsLocal,
InputFile *File) {
Symbol *S;
bool WasInserted;
+ uint8_t Visibility = getVisibility(StOther);
std::tie(S, WasInserted) =
- insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, File);
- if (WasInserted) {
+ insert(Name, Type, Visibility, CanOmitFromDynSym, File);
+ // An undefined symbol with non default visibility must be satisfied
+ // in the same DSO.
+ if (WasInserted ||
+ (isa<SharedSymbol>(S->body()) && Visibility != STV_DEFAULT)) {
S->Binding = Binding;
replaceBody<Undefined>(S, Name, IsLocal, StOther, Type, File);
return S;
@@ -428,7 +432,11 @@ void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *File, StringRef Name,
if (Sym.getVisibility() == STV_DEFAULT)
S->ExportDynamic = true;
- if (WasInserted || isa<Undefined>(S->body())) {
+ SymbolBody *Body = S->body();
+ // An undefined symbol with non default visibility must be satisfied
+ // in the same DSO.
+ if (WasInserted ||
+ (isa<Undefined>(Body) && Body->getVisibility() == STV_DEFAULT)) {
replaceBody<SharedSymbol>(S, File, Name, Sym.st_other, Sym.getType(), &Sym,
Verdef);
if (!S->isWeak())
diff --git a/lld/test/ELF/hidden-vis-shared.s b/lld/test/ELF/hidden-vis-shared.s
new file mode 100644
index 00000000000..f3fa206895a
--- /dev/null
+++ b/lld/test/ELF/hidden-vis-shared.s
@@ -0,0 +1,18 @@
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2.o
+// RUN: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld %t.o %t2.so -o %t
+// RUN: llvm-readobj -r %t | FileCheck %s
+// RUN: ld.lld %t2.so %t.o -o %t
+// RUN: llvm-readobj -r %t | FileCheck %s
+
+// CHECK: Relocations [
+// CHECK-NEXT: ]
+
+.global _start
+_start:
+callq bar
+.hidden bar
+.weak bar
OpenPOWER on IntegriCloud