Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -173,9 +173,9 @@ if (!Body) SymVA = getLocalRelTarget(*File, RI, 0); else if (Target->needsGot(Type, *Body)) - SymVA = Out<ELFT>::Got->getEntryAddr(*Body); + SymVA = Body->getGotVA<ELFT>(); else - SymVA = getSymVA<ELFT>(*Body); + SymVA = Body->getVA<ELFT>(); // By optimizing TLS relocations, it is sometimes needed to skip // relocations that immediately follow TLS relocations. This function // knows how many slots we need to skip. @@ -213,9 +213,9 @@ continue; } - uintX_t SymVA = getSymVA<ELFT>(*Body); + uintX_t SymVA = Body->getVA<ELFT>(); if (Target->needsPlt(Type, *Body)) { - SymVA = Out<ELFT>::Plt->getEntryAddr(*Body); + SymVA = Body->getPltVA<ELFT>(); } else if (Target->needsGot(Type, *Body)) { if (Config->EMachine == EM_MIPS && needsMipsLocalGot(Type, Body)) // Under some conditions relocations against non-local symbols require @@ -223,7 +223,7 @@ // initialized by full address of the symbol. SymVA = Out<ELFT>::Got->getMipsLocalFullAddr(*Body); else - SymVA = Out<ELFT>::Got->getEntryAddr(*Body); + SymVA = Body->getGotVA<ELFT>(); if (Body->isTls()) Type = Target->getTlsGotRel(Type); } else if (!Target->needsCopyRel(Type, *Body) && Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -47,9 +47,6 @@ return Rel.r_addend; } -template <class ELFT> -typename llvm::object::ELFFile<ELFT>::uintX_t getSymVA(const SymbolBody &S); - template <class ELFT, bool IsRela> typename llvm::object::ELFFile<ELFT>::uintX_t getLocalRelTarget(const ObjectFile<ELFT> &File, @@ -118,7 +115,6 @@ bool addDynTlsEntry(SymbolBody *Sym); bool addCurrentModuleTlsIndex(); bool empty() const { return MipsLocalEntries == 0 && Entries.empty(); } - uintX_t getEntryAddr(const SymbolBody &B) const; uintX_t getMipsLocalFullAddr(const SymbolBody &B); uintX_t getMipsLocalPageAddr(uintX_t Addr); uintX_t getGlobalDynAddr(const SymbolBody &B) const; @@ -155,7 +151,6 @@ void writeTo(uint8_t *Buf) override; void addEntry(SymbolBody *Sym); bool empty() const; - uintX_t getEntryAddr(const SymbolBody &B) const; private: std::vector<const SymbolBody *> Entries; @@ -171,7 +166,6 @@ void writeTo(uint8_t *Buf) override; void addEntry(SymbolBody *Sym); bool empty() const { return Entries.empty(); } - uintX_t getEntryAddr(const SymbolBody &B) const; private: std::vector<std::pair<const SymbolBody *, unsigned>> Entries; Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -47,12 +47,6 @@ return Entries.empty(); } -template <class ELFT> -typename GotPltSection<ELFT>::uintX_t -GotPltSection<ELFT>::getEntryAddr(const SymbolBody &B) const { - return this->getVA() + B.GotPltIndex * sizeof(uintX_t); -} - template <class ELFT> void GotPltSection<ELFT>::finalize() { this->Header.sh_size = (Target->GotPltHeaderEntriesNum + Entries.size()) * sizeof(uintX_t); @@ -62,7 +56,7 @@ Target->writeGotPltHeader(Buf); Buf += Target->GotPltHeaderEntriesNum * sizeof(uintX_t); for (const SymbolBody *B : Entries) { - Target->writeGotPlt(Buf, Out<ELFT>::Plt->getEntryAddr(*B)); + Target->writeGotPlt(Buf, B->getPltVA<ELFT>()); Buf += sizeof(uintX_t); } } @@ -105,16 +99,8 @@ template <class ELFT> typename GotSection<ELFT>::uintX_t -GotSection<ELFT>::getEntryAddr(const SymbolBody &B) const { - return this->getVA() + - (Target->GotHeaderEntriesNum + MipsLocalEntries + B.GotIndex) * - sizeof(uintX_t); -} - -template <class ELFT> -typename GotSection<ELFT>::uintX_t GotSection<ELFT>::getMipsLocalFullAddr(const SymbolBody &B) { - return getMipsLocalEntryAddr(getSymVA<ELFT>(B)); + return getMipsLocalEntryAddr(B.getVA<ELFT>()); } template <class ELFT> @@ -176,7 +162,7 @@ // As the first approach, we can just store addresses for all symbols. if (Config->EMachine != EM_MIPS && canBePreempted(B, false)) continue; // The dynamic linker will take care of it. - uintX_t VA = getSymVA<ELFT>(*B); + uintX_t VA = B->getVA<ELFT>(); write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA); } } @@ -197,8 +183,8 @@ for (auto &I : Entries) { const SymbolBody *B = I.first; unsigned RelOff = I.second; - uint64_t Got = Target->UseLazyBinding ? Out<ELFT>::GotPlt->getEntryAddr(*B) - : Out<ELFT>::Got->getEntryAddr(*B); + uint64_t Got = + Target->UseLazyBinding ? B->getGotPltVA<ELFT>() : B->getGotVA<ELFT>(); uint64_t Plt = this->getVA() + Off; Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff); Off += Target->PltEntrySize; @@ -213,13 +199,6 @@ Entries.push_back(std::make_pair(Sym, RelOff)); } -template <class ELFT> -typename PltSection<ELFT>::uintX_t -PltSection<ELFT>::getEntryAddr(const SymbolBody &B) const { - return this->getVA() + Target->PltZeroSize + - B.PltIndex * Target->PltEntrySize; -} - template <class ELFT> void PltSection<ELFT>::finalize() { this->Header.sh_size = Target->PltZeroSize + Entries.size() * Target->PltEntrySize; @@ -251,7 +230,7 @@ if (Target->canRelaxTls(Type, Body)) { P->setSymbolAndType(Body->DynsymIndex, Target->getTlsGotRel(), Config->Mips64EL); - P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body); + P->r_offset = Body->getGotVA<ELFT>(); return true; } @@ -312,9 +291,9 @@ if (!CBP && Body && isGnuIFunc<ELFT>(*Body)) { P->setSymbolAndType(0, Target->IRelativeRel, Config->Mips64EL); if (Out<ELFT>::GotPlt) - P->r_offset = Out<ELFT>::GotPlt->getEntryAddr(*Body); + P->r_offset = Body->getGotPltVA<ELFT>(); else - P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body); + P->r_offset = Body->getGotVA<ELFT>(); continue; } @@ -333,9 +312,9 @@ P->setSymbolAndType(CBP ? Body->DynsymIndex : 0, Reloc, Config->Mips64EL); if (LazyReloc) - P->r_offset = Out<ELFT>::GotPlt->getEntryAddr(*Body); + P->r_offset = Body->getGotPltVA<ELFT>(); else if (NeedsGot) - P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body); + P->r_offset = Body->getGotVA<ELFT>(); else P->r_offset = C.getOffset(RI.r_offset) + C.OutSec->getVA(); @@ -348,7 +327,7 @@ if (CBP) S->r_addend = A; else if (Body) - S->r_addend = getSymVA<ELFT>(*Body) + A; + S->r_addend = Body->getVA<ELFT>() + A; else S->r_addend = getLocalRelTarget(File, R, A); } @@ -715,7 +694,7 @@ P->d_un.d_ptr = E.OutSec->getVA(); break; case Entry::SymAddr: - P->d_un.d_ptr = getSymVA<ELFT>(*E.Sym); + P->d_un.d_ptr = E.Sym->template getVA<ELFT>(); break; case Entry::PlainInt: P->d_un.d_val = E.Val; @@ -836,48 +815,8 @@ this->Header.sh_size = Off; } -template <class ELFT> -typename ELFFile<ELFT>::uintX_t elf2::getSymVA(const SymbolBody &S) { - switch (S.kind()) { - case SymbolBody::DefinedSyntheticKind: { - auto &D = cast<DefinedSynthetic<ELFT>>(S); - return D.Section.getVA() + D.Value; - } - case SymbolBody::DefinedRegularKind: { - const auto &DR = cast<DefinedRegular<ELFT>>(S); - InputSectionBase<ELFT> *SC = DR.Section; - if (!SC) - return DR.Sym.st_value; - - // Symbol offsets for AMDGPU need to be the offset in bytes of the symbol - // from the beginning of the section. - if (Config->EMachine == EM_AMDGPU) - return SC->getOffset(DR.Sym); - if (DR.Sym.getType() == STT_TLS) - return SC->OutSec->getVA() + SC->getOffset(DR.Sym) - - Out<ELFT>::TlsPhdr->p_vaddr; - return SC->OutSec->getVA() + SC->getOffset(DR.Sym); - } - case SymbolBody::DefinedCommonKind: - return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(S).OffsetInBss; - case SymbolBody::SharedKind: { - auto &SS = cast<SharedSymbol<ELFT>>(S); - if (SS.NeedsCopy) - return Out<ELFT>::Bss->getVA() + SS.OffsetInBss; - return 0; - } - case SymbolBody::UndefinedElfKind: - case SymbolBody::UndefinedKind: - return 0; - case SymbolBody::LazyKind: - assert(S.isUsedInRegularObj() && "Lazy symbol reached writer"); - return 0; - } - llvm_unreachable("Invalid symbol kind"); -} - // Returns a VA which a relocatin RI refers to. Used only for local symbols. -// For non-local symbols, use getSymVA instead. +// For non-local symbols, use SymbolBody::getVA instead. template <class ELFT, bool IsRela> typename ELFFile<ELFT>::uintX_t elf2::getLocalRelTarget(const ObjectFile<ELFT> &File, @@ -1526,7 +1465,7 @@ ESym->setBindingAndType(getSymbolBinding(Body), Type); ESym->st_size = Size; ESym->setVisibility(Body->getVisibility()); - ESym->st_value = getSymVA<ELFT>(*Body); + ESym->st_value = Body->getVA<ELFT>(); if (OutSec) ESym->st_shndx = OutSec->SectionIndex; @@ -1653,11 +1592,6 @@ template class SymbolTableSection<ELF64LE>; template class SymbolTableSection<ELF64BE>; -template ELFFile<ELF32LE>::uintX_t getSymVA<ELF32LE>(const SymbolBody &); -template ELFFile<ELF32BE>::uintX_t getSymVA<ELF32BE>(const SymbolBody &); -template ELFFile<ELF64LE>::uintX_t getSymVA<ELF64LE>(const SymbolBody &); -template ELFFile<ELF64BE>::uintX_t getSymVA<ELF64BE>(const SymbolBody &); - template uint32_t getLocalRelTarget(const ObjectFile<ELF32LE> &, const ELFFile<ELF32LE>::Elf_Rel &, uint32_t); Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -101,6 +101,15 @@ bool isInGot() const { return GotIndex != -1U; } bool isInPlt() const { return PltIndex != -1U; } + template <class ELFT> + typename llvm::object::ELFFile<ELFT>::uintX_t getVA() const; + template <class ELFT> + typename llvm::object::ELFFile<ELFT>::uintX_t getGotVA() const; + template <class ELFT> + typename llvm::object::ELFFile<ELFT>::uintX_t getGotPltVA() const; + template <class ELFT> + typename llvm::object::ELFFile<ELFT>::uintX_t getPltVA() const; + // A SymbolBody has a backreference to a Symbol. Originally they are // doubly-linked. A backreference will never change. But the pointer // in the Symbol may be mutated by the resolver. If you have a Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -8,9 +8,11 @@ //===----------------------------------------------------------------------===// #include "Symbols.h" -#include "InputSection.h" #include "Error.h" #include "InputFiles.h" +#include "InputSection.h" +#include "OutputSections.h" +#include "Target.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Config/config.h" @@ -26,6 +28,67 @@ using namespace lld; using namespace lld::elf2; +template <class ELFT> +typename ELFFile<ELFT>::uintX_t SymbolBody::getVA() const { + switch (kind()) { + case DefinedSyntheticKind: { + auto *D = cast<DefinedSynthetic<ELFT>>(this); + return D->Section.getVA() + D->Value; + } + case DefinedRegularKind: { + auto *D = cast<DefinedRegular<ELFT>>(this); + InputSectionBase<ELFT> *SC = D->Section; + + // This is an absolute symbol. + if (!SC) + return D->Sym.st_value; + + // Symbol offsets for AMDGPU need to be the offset in bytes of the symbol + // from the beginning of the section. + if (Config->EMachine == EM_AMDGPU) + return SC->getOffset(D->Sym); + if (D->Sym.getType() == STT_TLS) + return SC->OutSec->getVA() + SC->getOffset(D->Sym) - + Out<ELFT>::TlsPhdr->p_vaddr; + return SC->OutSec->getVA() + SC->getOffset(D->Sym); + } + case DefinedCommonKind: + return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(this)->OffsetInBss; + case SharedKind: { + auto *SS = cast<SharedSymbol<ELFT>>(this); + if (SS->NeedsCopy) + return Out<ELFT>::Bss->getVA() + SS->OffsetInBss; + return 0; + } + case UndefinedElfKind: + case UndefinedKind: + return 0; + case LazyKind: + assert(isUsedInRegularObj() && "Lazy symbol reached writer"); + return 0; + } + llvm_unreachable("Invalid symbol kind"); +} + +template <class ELFT> +typename ELFFile<ELFT>::uintX_t SymbolBody::getGotVA() const { + return Out<ELFT>::Got->getVA() + + (Out<ELFT>::Got->getMipsLocalEntriesNum() + GotIndex) * + sizeof(typename ELFFile<ELFT>::uintX_t); +} + +template <class ELFT> +typename ELFFile<ELFT>::uintX_t SymbolBody::getGotPltVA() const { + return Out<ELFT>::GotPlt->getVA() + + GotPltIndex * sizeof(typename ELFFile<ELFT>::uintX_t); +} + +template <class ELFT> +typename ELFFile<ELFT>::uintX_t SymbolBody::getPltVA() const { + return Out<ELFT>::Plt->getVA() + Target->PltZeroSize + + PltIndex * Target->PltEntrySize; +} + static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { if (VA == STV_DEFAULT) return VB; @@ -166,6 +229,26 @@ #endif } +template uint32_t SymbolBody::template getVA<ELF32LE>() const; +template uint32_t SymbolBody::template getVA<ELF32BE>() const; +template uint64_t SymbolBody::template getVA<ELF64LE>() const; +template uint64_t SymbolBody::template getVA<ELF64BE>() const; + +template uint32_t SymbolBody::template getGotVA<ELF32LE>() const; +template uint32_t SymbolBody::template getGotVA<ELF32BE>() const; +template uint64_t SymbolBody::template getGotVA<ELF64LE>() const; +template uint64_t SymbolBody::template getGotVA<ELF64BE>() const; + +template uint32_t SymbolBody::template getGotPltVA<ELF32LE>() const; +template uint32_t SymbolBody::template getGotPltVA<ELF32BE>() const; +template uint64_t SymbolBody::template getGotPltVA<ELF64LE>() const; +template uint64_t SymbolBody::template getGotPltVA<ELF64BE>() const; + +template uint32_t SymbolBody::template getPltVA<ELF32LE>() const; +template uint32_t SymbolBody::template getPltVA<ELF32BE>() const; +template uint64_t SymbolBody::template getPltVA<ELF64LE>() const; +template uint64_t SymbolBody::template getPltVA<ELF64BE>() const; + template int SymbolBody::compare<ELF32LE>(SymbolBody *Other); template int SymbolBody::compare<ELF32BE>(SymbolBody *Other); template int SymbolBody::compare<ELF64LE>(SymbolBody *Other); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1257,8 +1257,8 @@ template <class ELFT> static typename ELFFile<ELFT>::uintX_t getEntryAddr() { if (Config->EntrySym) { - if (SymbolBody *E = Config->EntrySym->repl()) - return getSymVA<ELFT>(*E); + if (SymbolBody *B = Config->EntrySym->repl()) + return B->getVA<ELFT>(); return 0; } if (Config->EntryAddr != uint64_t(-1))