diff options
-rw-r--r-- | lld/ELF/InputSection.cpp | 3 | ||||
-rw-r--r-- | lld/ELF/OutputSections.cpp | 67 | ||||
-rw-r--r-- | lld/ELF/OutputSections.h | 2 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.cpp | 15 | ||||
-rw-r--r-- | lld/ELF/Symbols.h | 5 | ||||
-rw-r--r-- | lld/test/elf2/Inputs/archive3.s | 2 | ||||
-rw-r--r-- | lld/test/elf2/Inputs/archive4.s | 1 | ||||
-rw-r--r-- | lld/test/elf2/archive.s | 17 |
8 files changed, 70 insertions, 42 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 3f7ced0c746..cdcbe879f28 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -49,8 +49,7 @@ void InputSection<ELFT>::relocate( continue; SymVA = getLocalSymVA(Sym, File); } else { - const auto &Body = - *cast<ELFSymbolBody<ELFT>>(File.getSymbolBody(SymIndex)); + SymbolBody &Body = *File.getSymbolBody(SymIndex); SymVA = getSymVA<ELFT>(Body, BssSec); if (Target->relocNeedsPlt(Type, Body)) { SymVA = PltSec.getEntryAddr(Body); diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 5335cc5786d..9bcfaa6d02d 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -349,13 +349,14 @@ void OutputSection<ELFT>::addSection(InputSection<ELFT> *C) { template <class ELFT> typename ELFFile<ELFT>::uintX_t -lld::elf2::getSymVA(const ELFSymbolBody<ELFT> &S, - const OutputSection<ELFT> &BssSec) { +lld::elf2::getSymVA(const SymbolBody &S, const OutputSection<ELFT> &BssSec) { switch (S.kind()) { - case SymbolBody::DefinedSyntheticKind: - return cast<DefinedSynthetic<ELFT>>(S).Section.getVA() + S.Sym.st_value; + case SymbolBody::DefinedSyntheticKind: { + auto &D = cast<DefinedSynthetic<ELFT>>(S); + return D.Section.getVA() + D.Sym.st_value; + } case SymbolBody::DefinedAbsoluteKind: - return S.Sym.st_value; + return cast<DefinedAbsolute<ELFT>>(S).Sym.st_value; case SymbolBody::DefinedRegularKind: { const auto &DR = cast<DefinedRegular<ELFT>>(S); const InputSection<ELFT> *SC = &DR.Section; @@ -368,9 +369,9 @@ lld::elf2::getSymVA(const ELFSymbolBody<ELFT> &S, case SymbolBody::UndefinedKind: return 0; case SymbolBody::LazyKind: - break; + assert(S.isUsedInRegularObj() && "Lazy symbol reached writer"); + return 0; } - llvm_unreachable("Lazy symbol reached writer"); } template <class ELFT> @@ -409,8 +410,6 @@ void StringTableSection<Is64Bits>::writeTo(uint8_t *Buf) { } template <class ELFT> bool lld::elf2::includeInSymtab(const SymbolBody &B) { - if (B.isLazy()) - return false; if (!B.isUsedInRegularObj()) return false; @@ -521,21 +520,20 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *&Buf) { if (StrTabSec.isDynamic() && !includeInDynamicSymtab(*Body)) continue; - const auto &EBody = *cast<ELFSymbolBody<ELFT>>(Body); - const Elf_Sym &InputSym = EBody.Sym; auto *ESym = reinterpret_cast<Elf_Sym *>(Buf); Buf += sizeof(*ESym); + ESym->st_name = StrTabSec.getFileOff(Name); const OutputSection<ELFT> *Out = nullptr; const InputSection<ELFT> *Section = nullptr; - switch (EBody.kind()) { + switch (Body->kind()) { case SymbolBody::DefinedSyntheticKind: Out = &cast<DefinedSynthetic<ELFT>>(Body)->Section; break; case SymbolBody::DefinedRegularKind: - Section = &cast<DefinedRegular<ELFT>>(EBody).Section; + Section = &cast<DefinedRegular<ELFT>>(Body)->Section; break; case SymbolBody::DefinedCommonKind: Out = &BssSec; @@ -543,25 +541,33 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *&Buf) { case SymbolBody::UndefinedKind: case SymbolBody::DefinedAbsoluteKind: case SymbolBody::SharedKind: - break; case SymbolBody::LazyKind: - llvm_unreachable("Lazy symbol got to output symbol table!"); + break; + } + + unsigned char Binding = Body->isWeak() ? STB_WEAK : STB_GLOBAL; + unsigned char Type = STT_NOTYPE; + uintX_t Size = 0; + if (const auto *EBody = dyn_cast<ELFSymbolBody<ELFT>>(Body)) { + const Elf_Sym &InputSym = EBody->Sym; + Binding = InputSym.getBinding(); + Type = InputSym.getType(); + Size = InputSym.st_size; } - unsigned char Binding = InputSym.getBinding(); - unsigned char Visibility = EBody.getMostConstrainingVisibility(); + unsigned char Visibility = Body->getMostConstrainingVisibility(); if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) Binding = STB_LOCAL; - ESym->setBindingAndType(Binding, InputSym.getType()); - ESym->st_size = InputSym.st_size; + ESym->setBindingAndType(Binding, Type); + ESym->st_size = Size; ESym->setVisibility(Visibility); - ESym->st_value = getSymVA(EBody, BssSec); + ESym->st_value = getSymVA(*Body, BssSec); if (Section) Out = Section->getOutputSection(); - if (InputSym.isAbsolute()) + if (isa<DefinedAbsolute<ELFT>>(Body)) ESym->st_shndx = SHN_ABS; else if (Out) ESym->st_shndx = Out->getSectionIndex(); @@ -629,17 +635,14 @@ template class SymbolTableSection<ELF32BE>; template class SymbolTableSection<ELF64LE>; template class SymbolTableSection<ELF64BE>; -template ELFFile<ELF32LE>::uintX_t -getSymVA(const ELFSymbolBody<ELF32LE> &, const OutputSection<ELF32LE> &); - -template ELFFile<ELF32BE>::uintX_t -getSymVA(const ELFSymbolBody<ELF32BE> &, const OutputSection<ELF32BE> &); - -template ELFFile<ELF64LE>::uintX_t -getSymVA(const ELFSymbolBody<ELF64LE> &, const OutputSection<ELF64LE> &); - -template ELFFile<ELF64BE>::uintX_t -getSymVA(const ELFSymbolBody<ELF64BE> &, const OutputSection<ELF64BE> &); +template ELFFile<ELF32LE>::uintX_t getSymVA(const SymbolBody &, + const OutputSection<ELF32LE> &); +template ELFFile<ELF32BE>::uintX_t getSymVA(const SymbolBody &, + const OutputSection<ELF32BE> &); +template ELFFile<ELF64LE>::uintX_t getSymVA(const SymbolBody &, + const OutputSection<ELF64LE> &); +template ELFFile<ELF64BE>::uintX_t getSymVA(const SymbolBody &, + const OutputSection<ELF64BE> &); template ELFFile<ELF32LE>::uintX_t getLocalSymVA(const ELFFile<ELF32LE>::Elf_Sym *, const ObjectFile<ELF32LE> &); diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 96de43700a7..b0cf435ded1 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -34,7 +34,7 @@ template <class ELFT> class ELFSymbolBody; template <class ELFT> typename llvm::object::ELFFile<ELFT>::uintX_t -getSymVA(const ELFSymbolBody<ELFT> &S, const OutputSection<ELFT> &BssSec); +getSymVA(const SymbolBody &S, const OutputSection<ELFT> &BssSec); template <class ELFT> typename llvm::object::ELFFile<ELFT>::uintX_t diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index d077ce69065..6177e91d438 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -256,10 +256,23 @@ void SymbolTable::addLazy(Lazy *New) { if (Sym->Body == New) return; SymbolBody *Existing = Sym->Body; - if (Existing->isDefined() || Existing->isLazy() || Existing->isWeak()) + if (Existing->isDefined() || Existing->isLazy()) return; Sym->Body = New; assert(Existing->isUndefined() && "Unexpected symbol kind."); + + // Weak undefined symbols should not fetch members from archives. + // If we were to keep old symbol we would not know that an archive member was + // available if a strong undefined symbol shows up afterwards in the link. + // If a strong undefined symbol never shows up, this lazy symbol will + // get to the end of the link and must be treated as the weak undefined one. + // We set UsedInRegularObj in a similar way to what is done with shared + // symbols and mark it as weak to reduce how many special cases are needed. + if (Existing->isWeak()) { + New->setUsedInRegularObj(); + New->setWeak(); + return; + } addMemberFile(New); } diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 39e3d31b4ae..b47f365dc39 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -103,7 +103,7 @@ protected: } const unsigned SymbolKind : 8; - const unsigned IsWeak : 1; + unsigned IsWeak : 1; unsigned MostConstrainingVisibility : 2; unsigned IsUsedInRegularObj : 1; unsigned IsUsedInDynamicReloc : 1; @@ -282,6 +282,9 @@ public: // was already returned. std::unique_ptr<InputFile> getMember(); + void setWeak() { IsWeak = true; } + void setUsedInRegularObj() { IsUsedInRegularObj = true; } + private: ArchiveFile *File; const llvm::object::Archive::Symbol Sym; diff --git a/lld/test/elf2/Inputs/archive3.s b/lld/test/elf2/Inputs/archive3.s new file mode 100644 index 00000000000..3e11d431410 --- /dev/null +++ b/lld/test/elf2/Inputs/archive3.s @@ -0,0 +1,2 @@ +.global bar +bar: diff --git a/lld/test/elf2/Inputs/archive4.s b/lld/test/elf2/Inputs/archive4.s new file mode 100644 index 00000000000..e842874f187 --- /dev/null +++ b/lld/test/elf2/Inputs/archive4.s @@ -0,0 +1 @@ +.quad bar diff --git a/lld/test/elf2/archive.s b/lld/test/elf2/archive.s index e0e4c1ee554..f9cd17bd57b 100644 --- a/lld/test/elf2/archive.s +++ b/lld/test/elf2/archive.s @@ -1,8 +1,10 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/archive.s -o %t2 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/archive2.s -o %t3 -# RUN: llvm-ar rcs %tar %t2 %t3 -# RUN: lld -flavor gnu2 %t %tar -o %tout +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/archive3.s -o %t4 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/archive4.s -o %t5 +# RUN: llvm-ar rcs %tar %t2 %t3 %t4 +# RUN: lld -flavor gnu2 %t %tar %t5 -o %tout # RUN: llvm-nm %tout | FileCheck %s # REQUIRES: x86 @@ -13,6 +15,11 @@ .weak foo .quad foo -# CHECK: T _start -# CHECK: T end -# CHECK: w foo +.weak bar +.quad bar + + +# CHECK: T _start +# CHECK-NEXT: T bar +# CHECK-NEXT: T end +# CHECK-NEXT: w foo |