diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2016-06-09 18:01:35 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2016-06-09 18:01:35 +0000 |
commit | ca8c994818f1e18c1290c9d64893a76a376f0941 (patch) | |
tree | 5c705e24cfe95ea6df52758dcd23fe4491d1d363 /lld | |
parent | 00b385e3a5530cb613783f8bdf5614e7c8b869e2 (diff) | |
download | bcm5719-llvm-ca8c994818f1e18c1290c9d64893a76a376f0941.tar.gz bcm5719-llvm-ca8c994818f1e18c1290c9d64893a76a376f0941.zip |
ELF: Compute used bit for --as-needed during symbol resolution.
We can now use this to decide whether to emit a verneed during the final
pass over the symbols. We were previously wrongly creating a verneed entry
in the case where all references to a DSO's symbols were weak.
In a future change we may also want to use the used bit to control whether
shared symbols are preemptible and appear in the dynsym. This seems a little
tricky to do at the moment because isNeeded() is templated.
The only other functional change here is that we emit a DT_NEEDED for DSOs
whose symbols are all preempted by objects that appear later in the link. But
that doesn't seem too important to me.
Differential Revision: http://reviews.llvm.org/D21171
llvm-svn: 272282
Diffstat (limited to 'lld')
-rw-r--r-- | lld/ELF/SymbolTable.cpp | 14 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 8 | ||||
-rw-r--r-- | lld/test/ELF/verneed-as-needed-weak.s | 14 |
3 files changed, 26 insertions, 10 deletions
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 4117487b58d..cfce3d94ddd 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -238,9 +238,12 @@ Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, uint8_t Binding, cast<Undefined>(S->body())->File = File; return S; } - if (Binding != STB_WEAK && - (S->body()->isShared() || S->body()->isLazy())) - S->Binding = Binding; + if (Binding != STB_WEAK) { + if (S->body()->isShared() || S->body()->isLazy()) + S->Binding = Binding; + if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(S->body())) + SS->File->IsUsed = true; + } if (auto *L = dyn_cast<Lazy>(S->body())) { // An undefined weak will not fetch archive members, but we have to remember // its type. See also comment in addLazyArchive. @@ -393,8 +396,11 @@ void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name, // Make sure we preempt DSO symbols with default visibility. if (Sym.getVisibility() == STV_DEFAULT) S->ExportDynamic = true; - if (WasInserted || isa<Undefined>(S->body())) + if (WasInserted || isa<Undefined>(S->body())) { replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef); + if (!S->isWeak()) + F->IsUsed = true; + } } template <class ELFT> diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index bbb8085e981..9caf7a0526d 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -813,11 +813,6 @@ template <class ELFT> void Writer<ELFT>::createSections() { for (Symbol *S : Symtab.getSymbols()) { SymbolBody *Body = S->body(); - // Set "used" bit for --as-needed. - if (S->IsUsedInRegularObj && !S->isWeak()) - if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(Body)) - SS->File->IsUsed = true; - // We only report undefined symbols in regular objects. This means that we // will accept an undefined reference in bitcode if it can be optimized out. if (S->IsUsedInRegularObj && Body->isUndefined() && !S->isWeak()) @@ -834,7 +829,8 @@ template <class ELFT> void Writer<ELFT>::createSections() { if (isOutputDynamic() && S->includeInDynsym()) { Out<ELFT>::DynSymTab->addSymbol(Body); if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(Body)) - Out<ELFT>::VerNeed->addSymbol(SS); + if (SS->File->isNeeded()) + Out<ELFT>::VerNeed->addSymbol(SS); } } diff --git a/lld/test/ELF/verneed-as-needed-weak.s b/lld/test/ELF/verneed-as-needed-weak.s new file mode 100644 index 00000000000..fc8911cfbd2 --- /dev/null +++ b/lld/test/ELF/verneed-as-needed-weak.s @@ -0,0 +1,14 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: ld.lld %t.o --as-needed %S/Inputs/verneed1.so -o %t +# RUN: llvm-readobj -V %t | FileCheck %s + +# CHECK: SHT_GNU_verneed { +# CHECK-NEXT: } + +.weak f1 + +.globl _start +_start: +.data +.long f1 |