diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index e60e90528083..d5ff181b4f9e 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -173,9 +173,9 @@ void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd, if (!Body) SymVA = getLocalRelTarget(*File, RI, 0); else if (Target->needsGot(Type, *Body)) - SymVA = Out::Got->getEntryAddr(*Body); + SymVA = Body->getGotVA(); else - SymVA = getSymVA(*Body); + SymVA = Body->getVA(); // 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 @@ void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd, continue; } - uintX_t SymVA = getSymVA(*Body); + uintX_t SymVA = Body->getVA(); if (Target->needsPlt(Type, *Body)) { - SymVA = Out::Plt->getEntryAddr(*Body); + SymVA = Body->getPltVA(); } 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 @@ void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd, // initialized by full address of the symbol. SymVA = Out::Got->getMipsLocalFullAddr(*Body); else - SymVA = Out::Got->getEntryAddr(*Body); + SymVA = Body->getGotVA(); if (Body->isTls()) Type = Target->getTlsGotRel(Type); } else if (!Target->needsCopyRel(Type, *Body) && diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index ec17fe75ed55..14194f73666b 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -47,12 +47,6 @@ template bool GotPltSection::empty() const { return Entries.empty(); } -template -typename GotPltSection::uintX_t -GotPltSection::getEntryAddr(const SymbolBody &B) const { - return this->getVA() + B.GotPltIndex * sizeof(uintX_t); -} - template void GotPltSection::finalize() { this->Header.sh_size = (Target->GotPltHeaderEntriesNum + Entries.size()) * sizeof(uintX_t); @@ -62,7 +56,7 @@ template void GotPltSection::writeTo(uint8_t *Buf) { Target->writeGotPltHeader(Buf); Buf += Target->GotPltHeaderEntriesNum * sizeof(uintX_t); for (const SymbolBody *B : Entries) { - Target->writeGotPlt(Buf, Out::Plt->getEntryAddr(*B)); + Target->writeGotPlt(Buf, B->getPltVA()); Buf += sizeof(uintX_t); } } @@ -103,18 +97,10 @@ template bool GotSection::addCurrentModuleTlsIndex() { return true; } -template -typename GotSection::uintX_t -GotSection::getEntryAddr(const SymbolBody &B) const { - return this->getVA() + - (Target->GotHeaderEntriesNum + MipsLocalEntries + B.GotIndex) * - sizeof(uintX_t); -} - template typename GotSection::uintX_t GotSection::getMipsLocalFullAddr(const SymbolBody &B) { - return getMipsLocalEntryAddr(getSymVA(B)); + return getMipsLocalEntryAddr(B.getVA()); } template @@ -176,7 +162,7 @@ template void GotSection::writeTo(uint8_t *Buf) { // 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(*B); + uintX_t VA = B->getVA(); write(Entry, VA); } } @@ -197,8 +183,8 @@ template void PltSection::writeTo(uint8_t *Buf) { for (auto &I : Entries) { const SymbolBody *B = I.first; unsigned RelOff = I.second; - uint64_t Got = Target->UseLazyBinding ? Out::GotPlt->getEntryAddr(*B) - : Out::Got->getEntryAddr(*B); + uint64_t Got = + Target->UseLazyBinding ? B->getGotPltVA() : B->getGotVA(); uint64_t Plt = this->getVA() + Off; Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff); Off += Target->PltEntrySize; @@ -213,13 +199,6 @@ template void PltSection::addEntry(SymbolBody *Sym) { Entries.push_back(std::make_pair(Sym, RelOff)); } -template -typename PltSection::uintX_t -PltSection::getEntryAddr(const SymbolBody &B) const { - return this->getVA() + Target->PltZeroSize + - B.PltIndex * Target->PltEntrySize; -} - template void PltSection::finalize() { this->Header.sh_size = Target->PltZeroSize + Entries.size() * Target->PltEntrySize; @@ -251,7 +230,7 @@ bool RelocationSection::applyTlsDynamicReloc(SymbolBody *Body, if (Target->canRelaxTls(Type, Body)) { P->setSymbolAndType(Body->DynsymIndex, Target->getTlsGotRel(), Config->Mips64EL); - P->r_offset = Out::Got->getEntryAddr(*Body); + P->r_offset = Body->getGotVA(); return true; } @@ -312,9 +291,9 @@ template void RelocationSection::writeTo(uint8_t *Buf) { if (!CBP && Body && isGnuIFunc(*Body)) { P->setSymbolAndType(0, Target->IRelativeRel, Config->Mips64EL); if (Out::GotPlt) - P->r_offset = Out::GotPlt->getEntryAddr(*Body); + P->r_offset = Body->getGotPltVA(); else - P->r_offset = Out::Got->getEntryAddr(*Body); + P->r_offset = Body->getGotVA(); continue; } @@ -333,9 +312,9 @@ template void RelocationSection::writeTo(uint8_t *Buf) { P->setSymbolAndType(CBP ? Body->DynsymIndex : 0, Reloc, Config->Mips64EL); if (LazyReloc) - P->r_offset = Out::GotPlt->getEntryAddr(*Body); + P->r_offset = Body->getGotPltVA(); else if (NeedsGot) - P->r_offset = Out::Got->getEntryAddr(*Body); + P->r_offset = Body->getGotVA(); else P->r_offset = C.getOffset(RI.r_offset) + C.OutSec->getVA(); @@ -348,7 +327,7 @@ template void RelocationSection::writeTo(uint8_t *Buf) { if (CBP) S->r_addend = A; else if (Body) - S->r_addend = getSymVA(*Body) + A; + S->r_addend = Body->getVA() + A; else S->r_addend = getLocalRelTarget(File, R, A); } @@ -715,7 +694,7 @@ template void DynamicSection::writeTo(uint8_t *Buf) { P->d_un.d_ptr = E.OutSec->getVA(); break; case Entry::SymAddr: - P->d_un.d_ptr = getSymVA(*E.Sym); + P->d_un.d_ptr = E.Sym->template getVA(); break; case Entry::PlainInt: P->d_un.d_val = E.Val; @@ -835,48 +814,8 @@ void OutputSection::addSection(InputSectionBase *C) { this->Header.sh_size = Off; } -template -typename ELFFile::uintX_t elf2::getSymVA(const SymbolBody &S) { - switch (S.kind()) { - case SymbolBody::DefinedSyntheticKind: { - auto &D = cast>(S); - return D.Section.getVA() + D.Value; - } - case SymbolBody::DefinedRegularKind: { - const auto &DR = cast>(S); - InputSectionBase *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::TlsPhdr->p_vaddr; - return SC->OutSec->getVA() + SC->getOffset(DR.Sym); - } - case SymbolBody::DefinedCommonKind: - return Out::Bss->getVA() + cast(S).OffsetInBss; - case SymbolBody::SharedKind: { - auto &SS = cast>(S); - if (SS.NeedsCopy) - return Out::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 typename ELFFile::uintX_t elf2::getLocalRelTarget(const ObjectFile &File, @@ -1523,7 +1462,7 @@ void SymbolTableSection::writeGlobalSymbols(uint8_t *Buf) { ESym->setBindingAndType(getSymbolBinding(Body), Type); ESym->st_size = Size; ESym->setVisibility(Body->getVisibility()); - ESym->st_value = getSymVA(*Body); + ESym->st_value = Body->getVA(); if (OutSec) ESym->st_shndx = OutSec->SectionIndex; @@ -1650,11 +1589,6 @@ template class SymbolTableSection; template class SymbolTableSection; template class SymbolTableSection; -template ELFFile::uintX_t getSymVA(const SymbolBody &); -template ELFFile::uintX_t getSymVA(const SymbolBody &); -template ELFFile::uintX_t getSymVA(const SymbolBody &); -template ELFFile::uintX_t getSymVA(const SymbolBody &); - template uint32_t getLocalRelTarget(const ObjectFile &, const ELFFile::Elf_Rel &, uint32_t); diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 93bd997c3b30..7045720bf452 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -47,9 +47,6 @@ getAddend(const typename llvm::object::ELFFile::Elf_Rela &Rel) { return Rel.r_addend; } -template -typename llvm::object::ELFFile::uintX_t getSymVA(const SymbolBody &S); - template typename llvm::object::ELFFile::uintX_t getLocalRelTarget(const ObjectFile &File, @@ -118,7 +115,6 @@ public: 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 @@ public: void writeTo(uint8_t *Buf) override; void addEntry(SymbolBody *Sym); bool empty() const; - uintX_t getEntryAddr(const SymbolBody &B) const; private: std::vector Entries; @@ -171,7 +166,6 @@ public: 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> Entries; diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index ad6423f5e93f..6bc285ce5132 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/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 llvm::ELF; using namespace lld; using namespace lld::elf2; +template +typename ELFFile::uintX_t SymbolBody::getVA() const { + switch (kind()) { + case DefinedSyntheticKind: { + auto *D = cast>(this); + return D->Section.getVA() + D->Value; + } + case DefinedRegularKind: { + auto *D = cast>(this); + InputSectionBase *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::TlsPhdr->p_vaddr; + return SC->OutSec->getVA() + SC->getOffset(D->Sym); + } + case DefinedCommonKind: + return Out::Bss->getVA() + cast(this)->OffsetInBss; + case SharedKind: { + auto *SS = cast>(this); + if (SS->NeedsCopy) + return Out::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 +typename ELFFile::uintX_t SymbolBody::getGotVA() const { + return Out::Got->getVA() + + (Out::Got->getMipsLocalEntriesNum() + GotIndex) * + sizeof(typename ELFFile::uintX_t); +} + +template +typename ELFFile::uintX_t SymbolBody::getGotPltVA() const { + return Out::GotPlt->getVA() + + GotPltIndex * sizeof(typename ELFFile::uintX_t); +} + +template +typename ELFFile::uintX_t SymbolBody::getPltVA() const { + return Out::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 @@ std::string elf2::demangle(StringRef Name) { #endif } +template uint32_t SymbolBody::template getVA() const; +template uint32_t SymbolBody::template getVA() const; +template uint64_t SymbolBody::template getVA() const; +template uint64_t SymbolBody::template getVA() const; + +template uint32_t SymbolBody::template getGotVA() const; +template uint32_t SymbolBody::template getGotVA() const; +template uint64_t SymbolBody::template getGotVA() const; +template uint64_t SymbolBody::template getGotVA() const; + +template uint32_t SymbolBody::template getGotPltVA() const; +template uint32_t SymbolBody::template getGotPltVA() const; +template uint64_t SymbolBody::template getGotPltVA() const; +template uint64_t SymbolBody::template getGotPltVA() const; + +template uint32_t SymbolBody::template getPltVA() const; +template uint32_t SymbolBody::template getPltVA() const; +template uint64_t SymbolBody::template getPltVA() const; +template uint64_t SymbolBody::template getPltVA() const; + template int SymbolBody::compare(SymbolBody *Other); template int SymbolBody::compare(SymbolBody *Other); template int SymbolBody::compare(SymbolBody *Other); diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index f4be2061a485..67cbaa327f3e 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -101,6 +101,15 @@ public: bool isInGot() const { return GotIndex != -1U; } bool isInPlt() const { return PltIndex != -1U; } + template + typename llvm::object::ELFFile::uintX_t getVA() const; + template + typename llvm::object::ELFFile::uintX_t getGotVA() const; + template + typename llvm::object::ELFFile::uintX_t getGotPltVA() const; + template + typename llvm::object::ELFFile::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 diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 8c31989c88cd..c65be556ba1c 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1257,8 +1257,8 @@ static uint32_t getELFFlags() { template static typename ELFFile::uintX_t getEntryAddr() { if (Config->EntrySym) { - if (SymbolBody *E = Config->EntrySym->repl()) - return getSymVA(*E); + if (SymbolBody *B = Config->EntrySym->repl()) + return B->getVA(); return 0; } if (Config->EntryAddr != uint64_t(-1))