Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -217,11 +217,11 @@ if (!RelocatedSection) error("Unsupported relocation reference"); if (auto *S = dyn_cast>(RelocatedSection)) { - S->RelocSections.push_back(&Sec); + S->RelocSections.emplace_back(InputSection::RelocSec(S, &Sec)); } else if (auto *S = dyn_cast>(RelocatedSection)) { if (S->RelocSection) error("Multiple relocation sections to .eh_frame are not supported"); - S->RelocSection = &Sec; + S->RelocSection.reset(new InputSection::RelocSec(S, &Sec)); } else { error("Relocations pointing to SHF_MERGE are not supported"); } Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -14,6 +14,9 @@ #include "lld/Core/LLVM.h" #include "llvm/Object/ELF.h" +#include +#include + namespace lld { namespace elf2 { @@ -79,11 +82,29 @@ using RelIteratorRange = llvm::iterator_range *>; + struct RelocData { + bool Optimized = false; + }; + struct RelocSec { + RelocSec(InputSectionBase *B, const Elf_Shdr *Sec); + const Elf_Shdr *Sec = nullptr; + std::vector Relocs; + }; + template - void relocate(uint8_t *Buf, uint8_t *BufEnd, RelIteratorRange Rels); + void relocate(uint8_t *Buf, uint8_t *BufEnd, RelIteratorRange Rels, + const RelocSec &Sec); private: template + void relocateNotOptimized(uint8_t *Buf, uint8_t *BufEnd, + RelIteratorRange Rels, const RelocSec &Sec); + + template + void relocateOptimized(uint8_t *Buf, uint8_t *BufEnd, + RelIteratorRange Rels, const RelocSec &Sec); + + template uint8_t *findMipsPairedReloc(uint8_t *Buf, uint32_t SymIndex, uint32_t Type, RelIteratorRange Rels); }; @@ -140,7 +161,7 @@ uintX_t getOffset(uintX_t Offset); // Relocation section that refer to this one. - const Elf_Shdr *RelocSection = nullptr; + std::unique_ptr RelocSection; }; // This corresponds to a non SHF_MERGE section of an input file. @@ -159,14 +180,14 @@ // beginning of the output section. void writeTo(uint8_t *Buf); - // Relocation sections that refer to this one. - SmallVector RelocSections; - // The offset from beginning of the output sections this section was assigned // to. The writer sets a value. uint64_t OutSecOff = 0; static bool classof(const InputSectionBase *S); + + // Relocation sections that refer to this one. + std::list RelocSections; }; // MIPS .reginfo section provides information on the registers used by the code Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -88,6 +88,20 @@ } template +InputSectionBase::RelocSec::RelocSec(InputSectionBase *B, + const Elf_Shdr *Sec) + : Sec(Sec) { + ELFFile &EObj = B->File->getObj(); + if (Sec->sh_type == SHT_RELA) { + RelIteratorRange Rels = EObj.relas(Sec); + Relocs.resize(Rels.end() - Rels.begin()); + } else { + RelIteratorRange Rels = EObj.rels(Sec); + Relocs.resize(Rels.end() - Rels.begin()); + } +} + +template InputSection::InputSection(ObjectFile *F, const Elf_Shdr *Header) : InputSectionBase(F, Header, Base::Regular) {} @@ -139,24 +153,25 @@ template template -void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd, - RelIteratorRange Rels) { +void InputSectionBase::relocateNotOptimized(uint8_t *Buf, uint8_t *BufEnd, + RelIteratorRange Rels, + const RelocSec &Sec) { typedef Elf_Rel_Impl RelType; size_t Num = Rels.end() - Rels.begin(); for (size_t I = 0; I < Num; ++I) { const RelType &RI = *(Rels.begin() + I); - uint32_t SymIndex = RI.getSymbol(Config->Mips64EL); - uint32_t Type = RI.getType(Config->Mips64EL); + const RelocData &RelData = *(Sec.Relocs.begin() + I); uintX_t Offset = getOffset(RI.r_offset); - if (Offset == (uintX_t)-1) + if (Offset == (uintX_t)-1 || RelData.Optimized) continue; + uint32_t SymIndex = RI.getSymbol(Config->Mips64EL); + uint32_t Type = RI.getType(Config->Mips64EL); uint8_t *BufLoc = Buf + Offset; uintX_t AddrLoc = OutSec->getVA() + Offset; auto NextRelocs = llvm::make_range(&RI, Rels.end()); - if (Target->isTlsLocalDynamicReloc(Type) && - !Target->isTlsOptimized(Type, nullptr)) { + if (Target->isTlsLocalDynamicReloc(Type)) { Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, Out::Got->getLocalTlsIndexVA() + getAddend(RI)); @@ -168,22 +183,6 @@ if (SymIndex >= SymTab->sh_info) Body = File->getSymbolBody(SymIndex)->repl(); - if (Target->isTlsOptimized(Type, Body)) { - uintX_t SymVA; - if (!Body) - SymVA = getLocalRelTarget(*File, RI, 0); - else if (Target->relocNeedsGot(Type, *Body)) - SymVA = Out::Got->getEntryAddr(*Body); - else - SymVA = getSymVA(*Body); - // 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. - I += Target->relocateTlsOptimize(BufLoc, BufEnd, Type, AddrLoc, SymVA, - *Body); - continue; - } - // Handle relocations for local symbols -- they never get // resolved so we don't allocate a SymbolBody. uintX_t A = getAddend(RI); @@ -206,8 +205,7 @@ continue; } - if (Target->isTlsGlobalDynamicReloc(Type) && - !Target->isTlsOptimized(Type, Body)) { + if (Target->isTlsGlobalDynamicReloc(Type)) { Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, Out::Got->getGlobalDynAddr(*Body) + getAddend(RI)); @@ -250,6 +248,51 @@ } } +template +template +void InputSectionBase::relocateOptimized(uint8_t *Buf, uint8_t *BufEnd, + RelIteratorRange Rels, + const RelocSec &Sec) { + typedef Elf_Rel_Impl RelType; + size_t Num = Rels.end() - Rels.begin(); + for (size_t I = 0; I < Num; ++I) { + const RelType &RI = *(Rels.begin() + I); + const RelocData &RelData = *(Sec.Relocs.begin() + I); + uintX_t Offset = getOffset(RI.r_offset); + if (Offset == (uintX_t)-1 || !RelData.Optimized) + continue; + uint32_t SymIndex = RI.getSymbol(Config->Mips64EL); + uint32_t Type = RI.getType(Config->Mips64EL); + const Elf_Shdr *SymTab = File->getSymbolTable(); + + SymbolBody *Body = nullptr; + if (SymIndex >= SymTab->sh_info) + Body = File->getSymbolBody(SymIndex)->repl(); + + uintX_t SymVA; + if (!Body) + SymVA = getLocalRelTarget(*File, RI, 0); + else if (Target->relocNeedsGot(Type, *Body)) + SymVA = Out::Got->getEntryAddr(*Body); + else + SymVA = getSymVA(*Body); + // 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. + I += Target->relocateTlsOptimize(Buf + Offset, BufEnd, Type, + OutSec->getVA() + Offset, SymVA, *Body); + } +} + +template +template +void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd, + RelIteratorRange Rels, + const RelocSec &Sec) { + relocateNotOptimized(Buf, BufEnd, Rels, Sec); + relocateOptimized(Buf, BufEnd, Rels, Sec); +} + template void InputSection::writeTo(uint8_t *Buf) { if (this->Header->sh_type == SHT_NOBITS) return; @@ -260,11 +303,11 @@ ELFFile &EObj = this->File->getObj(); uint8_t *BufEnd = Buf + OutSecOff + Data.size(); // Iterate over all relocation sections that apply to this section. - for (const Elf_Shdr *RelSec : this->RelocSections) { - if (RelSec->sh_type == SHT_RELA) - this->relocate(Buf, BufEnd, EObj.relas(RelSec)); + for (const RelocSec &RelSec : this->RelocSections) { + if (RelSec.Sec->sh_type == SHT_RELA) + this->relocate(Buf, BufEnd, EObj.relas(RelSec.Sec), RelSec); else - this->relocate(Buf, BufEnd, EObj.rels(RelSec)); + this->relocate(Buf, BufEnd, EObj.rels(RelSec.Sec), RelSec); } } Index: ELF/MarkLive.cpp =================================================================== --- ELF/MarkLive.cpp +++ ELF/MarkLive.cpp @@ -46,13 +46,13 @@ typedef typename ELFFile::Elf_Shdr Elf_Shdr; 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)) + for (const InputSectionBase::RelocSec &RelSec : Sec->RelocSections) { + if (RelSec.Sec->sh_type == SHT_RELA) { + for (const Elf_Rela &RI : Obj.relas(RelSec.Sec)) if (InputSectionBase *Succ = Sec->getRelocTarget(RI)) Fn(Succ); } else { - for (const Elf_Rel &RI : Obj.rels(RelSec)) + for (const Elf_Rel &RI : Obj.rels(RelSec.Sec)) if (InputSectionBase *Succ = Sec->getRelocTarget(RI)) Fn(Succ); } Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -1265,10 +1265,10 @@ template void EHOutputSection::addSection(InputSectionBase *C) { auto *S = cast>(C); - const Elf_Shdr *RelSec = S->RelocSection; - if (!RelSec) + if (!S->RelocSection) return addSectionAux( S, make_range((const Elf_Rela *)nullptr, (const Elf_Rela *)nullptr)); + const Elf_Shdr *RelSec = S->RelocSection->Sec; ELFFile &Obj = S->getFile()->getObj(); if (RelSec->sh_type == SHT_RELA) return addSectionAux(S, Obj.relas(RelSec)); @@ -1306,14 +1306,14 @@ } for (EHInputSection *S : Sections) { - const Elf_Shdr *RelSec = S->RelocSection; - if (!RelSec) + if (!S->RelocSection) continue; + const Elf_Shdr *RelSec = S->RelocSection->Sec; ELFFile &EObj = S->getFile()->getObj(); if (RelSec->sh_type == SHT_RELA) - S->relocate(Buf, nullptr, EObj.relas(RelSec)); + S->relocate(Buf, nullptr, EObj.relas(RelSec), *S->RelocSection.get()); else - S->relocate(Buf, nullptr, EObj.rels(RelSec)); + S->relocate(Buf, nullptr, EObj.rels(RelSec), *S->RelocSection.get()); } } Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -37,6 +37,8 @@ typedef typename ELFFile::Elf_Sym Elf_Sym; typedef typename ELFFile::Elf_Sym_Range Elf_Sym_Range; typedef typename ELFFile::Elf_Rela Elf_Rela; + typedef typename InputSectionBase::RelocSec RelocSec; + typedef typename InputSectionBase::RelocData RelocData; Writer(SymbolTable &S) : Symtab(S) {} void run(); @@ -48,10 +50,11 @@ template void scanRelocs(InputSectionBase &C, - iterator_range *> Rels); + iterator_range *> Rels, + RelocSec &D); void scanRelocs(InputSection &C); - void scanRelocs(InputSectionBase &S, const Elf_Shdr &RelSec); + void scanRelocs(InputSectionBase &S, RelocSec &RelSec); void updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr, uintX_t VA); void assignAddresses(); void buildSectionMap(); @@ -193,10 +196,17 @@ } template -static bool handleTlsRelocation(unsigned Type, SymbolBody *Body, - InputSectionBase &C, RelT &RI) { +static bool scanOptRelocation(unsigned Type, SymbolBody *Body, + InputSectionBase &C, RelT &RI, + typename Writer::RelocData &R) { + bool IsHint = Target->isHintReloc(Type); + R.Optimized = IsHint || Target->isTlsOptimized(Type, Body); + // Ignore "hint" relocation because it is for optional code optimization. + if (IsHint) + return true; + if (Target->isTlsLocalDynamicReloc(Type)) { - if (Target->isTlsOptimized(Type, nullptr)) + if (R.Optimized) return true; if (Out::Got->addCurrentModuleTlsIndex()) Out::RelaDyn->addReloc({&C, &RI}); @@ -207,8 +217,7 @@ return false; if (Target->isTlsGlobalDynamicReloc(Type)) { - bool Opt = Target->isTlsOptimized(Type, Body); - if (!Opt && Out::Got->addDynTlsEntry(Body)) { + if (!R.Optimized && Out::Got->addDynTlsEntry(Body)) { Out::RelaDyn->addReloc({&C, &RI}); Out::RelaDyn->addReloc({nullptr, nullptr}); Body->setUsedInDynamicReloc(); @@ -232,18 +241,17 @@ template void Writer::scanRelocs( InputSectionBase &C, - iterator_range *> Rels) { + iterator_range *> Rels, RelocSec &D) { typedef Elf_Rel_Impl RelType; const ObjectFile &File = *C.getFile(); - for (const RelType &RI : Rels) { + size_t Num = Rels.end() - Rels.begin(); + for (size_t I = 0; I < Num; ++I) { + const RelType &RI = *(Rels.begin() + I); + RelocData &RelData = *(D.Relocs.begin() + I); uint32_t SymIndex = RI.getSymbol(Config->Mips64EL); SymbolBody *Body = File.getSymbolBody(SymIndex); uint32_t Type = RI.getType(Config->Mips64EL); - // Ignore "hint" relocation because it is for optional code optimization. - if (Target->isHintReloc(Type)) - continue; - if (Target->isGotRelative(Type)) HasGotOffRel = true; @@ -255,7 +263,7 @@ if (Body) Body = Body->repl(); - if (handleTlsRelocation(Type, Body, C, RI)) + if (scanOptRelocation(Type, Body, C, RI, RelData)) continue; if (Target->relocNeedsDynRelative(Type)) { @@ -355,18 +363,17 @@ if (!(C.getSectionHdr()->sh_flags & SHF_ALLOC)) return; - for (const Elf_Shdr *RelSec : C.RelocSections) - scanRelocs(C, *RelSec); + for (InputSectionBase::RelocSec &RelSec : C.RelocSections) + scanRelocs(C, RelSec); } template -void Writer::scanRelocs(InputSectionBase &S, - const Elf_Shdr &RelSec) { +void Writer::scanRelocs(InputSectionBase &S, RelocSec &RelSec) { ELFFile &EObj = S.getFile()->getObj(); - if (RelSec.sh_type == SHT_RELA) - scanRelocs(S, EObj.relas(&RelSec)); + if (RelSec.Sec->sh_type == SHT_RELA) + scanRelocs(S, EObj.relas(RelSec.Sec), RelSec); else - scanRelocs(S, EObj.rels(&RelSec)); + scanRelocs(S, EObj.rels(RelSec.Sec), RelSec); } template @@ -820,7 +827,7 @@ scanRelocs(*S); else if (auto *S = dyn_cast>(C)) if (S->RelocSection) - scanRelocs(*S, *S->RelocSection); + scanRelocs(*S, *S->RelocSection.get()); } }