Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -123,12 +123,6 @@ ArrayRef getSectionData() const; - // Returns a section that Rel is pointing to. Used by the garbage collector. - std::pair *, uintX_t> - getRelocTarget(const Elf_Rel &Rel) const; - std::pair *, uintX_t> - getRelocTarget(const Elf_Rela &Rel) const; - void relocate(uint8_t *Buf, uint8_t *BufEnd); std::vector Relocations; }; Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -78,43 +78,6 @@ } template -static DefinedRegular *getRelocTargetSym(elf::ObjectFile *File, - const typename ELFT::Rel &Rel) { - uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL); - SymbolBody &B = File->getSymbolBody(SymIndex).repl(); - if (auto *D = dyn_cast>(&B)) - if (D->Section) - return D; - return nullptr; -} - -// Returns a section that Rel relocation is pointing to. -template -std::pair *, typename ELFT::uint> -InputSectionBase::getRelocTarget(const Elf_Rel &Rel) const { - auto *D = getRelocTargetSym(File, Rel); - if (!D) - return std::make_pair(nullptr, 0); - if (!D->isSection()) - return std::make_pair(D->Section->Repl, D->Value); - const uint8_t *BufLoc = getSectionData().begin() + Rel.r_offset; - uintX_t Addend = - Target->getImplicitAddend(BufLoc, Rel.getType(Config->Mips64EL)); - return std::make_pair(D->Section->Repl, D->Value + Addend); -} - -template -std::pair *, typename ELFT::uint> -InputSectionBase::getRelocTarget(const Elf_Rela &Rel) const { - auto *D = getRelocTargetSym(File, Rel); - if (!D) - return std::make_pair(nullptr, 0); - if (!D->isSection()) - return std::make_pair(D->Section->Repl, D->Value); - return std::make_pair(D->Section->Repl, D->Value + Rel.r_addend); -} - -template InputSection::InputSection(elf::ObjectFile *F, const Elf_Shdr *Header) : InputSectionBase(F, Header, Base::Regular) {} Index: ELF/MarkLive.cpp =================================================================== --- ELF/MarkLive.cpp +++ ELF/MarkLive.cpp @@ -25,6 +25,7 @@ #include "OutputSections.h" #include "SymbolTable.h" #include "Symbols.h" +#include "Target.h" #include "Writer.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Object/ELF.h" @@ -38,31 +39,56 @@ using namespace lld; using namespace lld::elf; +// A resolved relocation. The Sec and Offset fields are set if the relocation +// was resolved to an offset within a section. +template +struct ResolvedReloc { + InputSectionBase *Sec; + typename ELFT::uint Offset; +}; + +template +static typename ELFT::uint getAddend(InputSectionBase *Sec, + const typename ELFT::Rel &Rel) { + return Target->getImplicitAddend(Sec->getSectionData().begin(), + Rel.getType(Config->Mips64EL)); +} + +template +static typename ELFT::uint getAddend(InputSectionBase *Sec, + const typename ELFT::Rela &Rel) { + return Rel.r_addend; +} + +template +static ResolvedReloc resolveReloc(InputSection *Sec, RelT &Rel) { + uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL); + SymbolBody &B = Sec->getFile()->getSymbolBody(SymIndex).repl(); + auto *D = dyn_cast>(&B); + if (!D || !D->Section) + return {nullptr, 0}; + typename ELFT::uint Offset = D->Value; + if (D->isSection()) + Offset += getAddend(Sec, Rel); + return {D->Section->Repl, Offset}; +} + // Calls Fn for each section that Sec refers to via relocations. template -static void forEachSuccessor( - InputSection *Sec, - std::function *, typename ELFT::uint Offset)> - Fn) { +static void forEachSuccessor(InputSection *Sec, + std::function)> Fn) { typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; typedef typename ELFT::Shdr Elf_Shdr; - typedef typename ELFT::uint uintX_t; ELFFile &Obj = Sec->getFile()->getObj(); for (const Elf_Shdr *RelSec : Sec->RelocSections) { if (RelSec->sh_type == SHT_RELA) { - for (const Elf_Rela &RI : Obj.relas(RelSec)) { - std::pair *, uintX_t> P = - Sec->getRelocTarget(RI); - Fn(P.first, P.second); - } + for (const Elf_Rela &RI : Obj.relas(RelSec)) + Fn(resolveReloc(Sec, RI)); } else { - for (const Elf_Rel &RI : Obj.rels(RelSec)) { - std::pair *, uintX_t> P = - Sec->getRelocTarget(RI); - Fn(P.first, P.second); - } + for (const Elf_Rel &RI : Obj.rels(RelSec)) + Fn(resolveReloc(Sec, RI)); } } } @@ -97,25 +123,25 @@ typedef typename ELFT::uint uintX_t; SmallVector *, 256> Q; - auto Enqueue = [&](InputSectionBase *Sec, uintX_t Offset) { - if (!Sec) + auto Enqueue = [&](ResolvedReloc R) { + if (!R.Sec) return; - if (auto *MS = dyn_cast>(Sec)) { + if (auto *MS = dyn_cast>(R.Sec)) { std::pair *, uintX_t> T = - MS->getRangeAndSize(Offset); + MS->getRangeAndSize(R.Offset); T.first->second = 0; } - if (Sec->Live) + if (R.Sec->Live) return; - Sec->Live = true; - if (InputSection *S = dyn_cast>(Sec)) + R.Sec->Live = true; + if (InputSection *S = dyn_cast>(R.Sec)) Q.push_back(S); }; auto MarkSymbol = [&](SymbolBody *Sym) { if (Sym) if (auto *D = dyn_cast>(Sym)) - Enqueue(D->Section, D->Value); + Enqueue({D->Section, D->Value}); }; // Add GC root symbols. @@ -138,7 +164,7 @@ for (InputSectionBase *Sec : F->getSections()) if (Sec && Sec != &InputSection::Discarded) if (isReserved(Sec) || Script::X->shouldKeep(Sec)) - Enqueue(Sec, 0); + Enqueue({Sec, 0}); // Mark all reachable sections. while (!Q.empty()) Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -1152,15 +1152,20 @@ } else { if (!HasReloc) fatal("FDE doesn't reference another section"); - InputSectionBase *Target = S->getRelocTarget(*RelI).first; - if (Target && Target->Live) { - uint32_t CieOffset = Offset + 4 - ID; - auto I = OffsetToIndex.find(CieOffset); - if (I == OffsetToIndex.end()) - fatal("invalid CIE reference"); - Cies[I->second].Fdes.push_back(EHRegion(S, Index)); - Out::EhFrameHdr->reserveFde(); - this->Header.sh_size += alignTo(Length, sizeof(uintX_t)); + uint32_t SymIndex = RelI->getSymbol(Config->Mips64EL); + SymbolBody &B = S->getFile()->getSymbolBody(SymIndex).repl(); + auto *D = dyn_cast>(&B); + if (D && D->Section) { + InputSectionBase *Target = D->Section->Repl; + if (Target && Target->Live) { + uint32_t CieOffset = Offset + 4 - ID; + auto I = OffsetToIndex.find(CieOffset); + if (I == OffsetToIndex.end()) + fatal("invalid CIE reference"); + Cies[I->second].Fdes.push_back(EHRegion(S, Index)); + Out::EhFrameHdr->reserveFde(); + this->Header.sh_size += alignTo(Length, sizeof(uintX_t)); + } } }