diff options
-rw-r--r-- | lld/ELF/OutputSections.cpp | 9 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.cpp | 8 | ||||
-rw-r--r-- | lld/ELF/Symbols.h | 9 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 10 | ||||
-rw-r--r-- | lld/test/ELF/relocation-copy-alias.s | 6 | ||||
-rw-r--r-- | lld/test/ELF/weak-undef-shared.s | 19 |
6 files changed, 48 insertions, 13 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 6eeaa3ffc8e..146eaff0b7c 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -1363,12 +1363,13 @@ static bool sortMipsSymbols(const std::pair<SymbolBody *, unsigned> &L, } static uint8_t getSymbolBinding(SymbolBody *Body) { - uint8_t Visibility = Body->Backref->Visibility; + Symbol *S = Body->Backref; + uint8_t Visibility = S->Visibility; if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) return STB_LOCAL; - if (Config->NoGnuUnique && Body->Binding == STB_GNU_UNIQUE) + if (Config->NoGnuUnique && S->Binding == STB_GNU_UNIQUE) return STB_GLOBAL; - return Body->Binding; + return S->Binding; } template <class ELFT> void SymbolTableSection<ELFT>::finalize() { @@ -1442,7 +1443,7 @@ void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) { } ESym->st_name = P.second; ESym->st_size = Body.template getSize<ELFT>(); - ESym->setBindingAndType(Body.Binding, Body.Type); + ESym->setBindingAndType(STB_LOCAL, Body.Type); Buf += sizeof(*ESym); } } diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index b3f971eea90..d67ad8699f3 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -244,6 +244,7 @@ template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) { SymbolBody *Existing = Sym->Body; if (auto *L = dyn_cast<Lazy>(Existing)) { + Sym->Binding = New->Binding; if (New->isUndefined()) { addMemberFile(New, L); return; @@ -270,8 +271,11 @@ template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) { error(S); return; } - if (Comp < 0) + if (Comp < 0) { Sym->Body = New; + if (!New->isShared()) + Sym->Binding = New->Binding; + } } static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { @@ -300,6 +304,7 @@ template <class ELFT> Symbol *SymbolTable<ELFT>::insert(SymbolBody *New) { if (P.second) { Sym = new (Alloc) Symbol; Sym->Body = New; + Sym->Binding = New->isShared() ? STB_GLOBAL : New->Binding; Sym->Visibility = STV_DEFAULT; Sym->IsUsedInRegularObj = false; Sym->ExportDynamic = false; @@ -353,7 +358,6 @@ void SymbolTable<ELFT>::addMemberFile(SymbolBody *Undef, Lazy *L) { // but we also need to preserve its binding and type. if (Undef->isWeak()) { // FIXME: Consider moving these members to Symbol. - L->Binding = Undef->Binding; L->Type = Undef->Type; return; } diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 7aed12d4020..64b9fea9fd2 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -44,6 +44,13 @@ std::string demangle(StringRef Name); struct Symbol { SymbolBody *Body; + // Symbol binding. This is on the Symbol to track changes during resolution. + // In particular: + // An undefined weak is still weak when it resolves to a shared library. + // An undefined weak will not fetch archive members, but we have to remember + // it is weak. + uint8_t Binding; + // Symbol visibility. This is the computed minimum visibility of all // observed non-DSO symbols. unsigned Visibility : 2; @@ -66,6 +73,8 @@ struct Symbol { unsigned VersionScriptGlobal : 1; bool includeInDynsym() const; + + bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; } }; // The base class for real symbol classes. diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index faf3d0bb5ba..9ee44dcc55a 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -424,7 +424,8 @@ static int32_t findMipsPairedAddend(const uint8_t *Buf, const uint8_t *BufLoc, // True if non-preemptable symbol always has the same value regardless of where // the DSO is loaded. template <class ELFT> static bool isAbsolute(const SymbolBody &Body) { - if (Body.isUndefined() && Body.isWeak()) + Symbol *Sym = Body.Backref; + if (Body.isUndefined() && Sym->isWeak()) return true; // always 0 if (const auto *DR = dyn_cast<DefinedRegular<ELFT>>(&Body)) return DR->Section == nullptr; // Absolute symbol. @@ -521,7 +522,8 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) { const RelTy &RI = *I; uint32_t SymIndex = RI.getSymbol(Config->Mips64EL); SymbolBody &OrigBody = File.getSymbolBody(SymIndex); - SymbolBody &Body = OrigBody.repl(); + Symbol *Sym = OrigBody.Backref; + SymbolBody &Body = Sym ? *Sym->Body : OrigBody; uint32_t Type = RI.getType(Config->Mips64EL); // Ignore "hint" relocation because it is for optional code optimization. @@ -533,7 +535,7 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) { continue; // Set "used" bit for --as-needed. - if (OrigBody.isUndefined() && !OrigBody.isWeak()) + if (OrigBody.isUndefined() && Sym && !Sym->isWeak()) if (auto *S = dyn_cast<SharedSymbol<ELFT>>(&Body)) S->File->IsUsed = true; @@ -1342,7 +1344,7 @@ template <class ELFT> void Writer<ELFT>::createSections() { std::vector<DefinedCommon *> CommonSymbols; for (Symbol *S : Symtab.getSymbols()) { SymbolBody *Body = S->Body; - if (Body->isUndefined() && !Body->isWeak()) { + if (Body->isUndefined() && !S->isWeak()) { auto *U = dyn_cast<UndefinedElf<ELFT>>(Body); if (!U || !U->canKeepUndefined()) reportUndefined<ELFT>(Symtab, Body); diff --git a/lld/test/ELF/relocation-copy-alias.s b/lld/test/ELF/relocation-copy-alias.s index d3256d24b53..b7758f75c31 100644 --- a/lld/test/ELF/relocation-copy-alias.s +++ b/lld/test/ELF/relocation-copy-alias.s @@ -37,7 +37,7 @@ movl $5, b2 // CHECK: Name: b1 // CHECK-NEXT: Value: [[B:.*]] // CHECK-NEXT: Size: 1 -// CHECK-NEXT: Binding: Weak (0x2) +// CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: Object (0x1) // CHECK-NEXT: Other: 0 // CHECK-NEXT: Section: .bss @@ -45,7 +45,7 @@ movl $5, b2 // CHECK: Name: b2 // CHECK-NEXT: Value: [[B]] // CHECK-NEXT: Size: 1 -// CHECK-NEXT: Binding: Weak (0x2) +// CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: Object (0x1) // CHECK-NEXT: Other: 0 // CHECK-NEXT: Section: .bss @@ -53,7 +53,7 @@ movl $5, b2 // CHECK: Name: a2 // CHECK-NEXT: Value: [[A]] // CHECK-NEXT: Size: 1 -// CHECK-NEXT: Binding: Weak (0x2) +// CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: Object (0x1) // CHECK-NEXT: Other: 0 // CHECK-NEXT: Section: .bss diff --git a/lld/test/ELF/weak-undef-shared.s b/lld/test/ELF/weak-undef-shared.s new file mode 100644 index 00000000000..862a08632e2 --- /dev/null +++ b/lld/test/ELF/weak-undef-shared.s @@ -0,0 +1,19 @@ +// REQUIRES: x86 +// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux +// RUN: llvm-mc %p/Inputs/shared.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux +// RUN: ld.lld %t2.o -o %t2.so -shared +// RUN: ld.lld %t.o %t2.so -o %t.exe +// RUN: llvm-readobj -t %t.exe | FileCheck %s + +// CHECK: Name: bar +// CHECK-NEXT: Value: 0x11020 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Weak +// CHECK-NEXT: Type: Function +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: Undefined + +.global _start +_start: + .weak bar + .quad bar |