diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2017-04-04 20:03:34 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2017-04-04 20:03:34 +0000 |
commit | 8465d083921c56ac35d2c292da316dd470641ef2 (patch) | |
tree | a7e56e836ccbe376a1294cb5f324935b015e0e02 | |
parent | 08f943c5630d8ee31d6a93227171d2f05db59e62 (diff) | |
download | bcm5719-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.cpp | 14 | ||||
-rw-r--r-- | lld/test/ELF/hidden-vis-shared.s | 18 |
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 |