Index: ELF/ICF.cpp =================================================================== --- ELF/ICF.cpp +++ ELF/ICF.cpp @@ -121,9 +121,7 @@ template uint64_t ICF::getHash(InputSection *S) { uint64_t Flags = S->Flags; uint64_t H = hash_combine(Flags, S->getSize()); - for (const Elf_Shdr *Rel : S->RelocSections) - H = hash_combine(H, (uint64_t)Rel->sh_size); - return H; + return hash_combine(H, S->NumRelocations); } // Returns true if Sec is subject of ICF. @@ -212,21 +210,15 @@ template bool ICF::equalsConstant(const InputSection *A, const InputSection *B) { - if (A->RelocSections.size() != B->RelocSections.size()) + if (A->NumRelocations != B->NumRelocations) return false; - for (size_t I = 0, E = A->RelocSections.size(); I != E; ++I) { - const Elf_Shdr *RA = A->RelocSections[I]; - const Elf_Shdr *RB = B->RelocSections[I]; - ELFFile FileA = A->getObj(); - ELFFile FileB = B->getObj(); - if (RA->sh_type == SHT_RELA) { - if (!relocationEq(check(FileA.relas(RA)), check(FileB.relas(RB)))) - return false; - } else { - if (!relocationEq(check(FileA.rels(RA)), check(FileB.rels(RB)))) - return false; - } + if (A->AreRelocsRela) { + if (!relocationEq(A->relas(), B->relas())) + return false; + } else { + if (!relocationEq(A->rels(), B->rels())) + return false; } return A->Flags == B->Flags && A->getSize() == B->getSize() && @@ -268,20 +260,9 @@ template bool ICF::equalsVariable(const InputSection *A, const InputSection *B) { - for (size_t I = 0, E = A->RelocSections.size(); I != E; ++I) { - const Elf_Shdr *RA = A->RelocSections[I]; - const Elf_Shdr *RB = B->RelocSections[I]; - ELFFile FileA = A->getObj(); - ELFFile FileB = B->getObj(); - if (RA->sh_type == SHT_RELA) { - if (!variableEq(A, B, check(FileA.relas(RA)), check(FileB.relas(RB)))) - return false; - } else { - if (!variableEq(A, B, check(FileA.rels(RA)), check(FileB.rels(RB)))) - return false; - } - } - return true; + if (A->AreRelocsRela) + return variableEq(A, B, A->relas(), B->relas()); + return variableEq(A, B, A->rels(), B->rels()); } // The main function of ICF. Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -121,6 +121,8 @@ // .o file. template class ObjectFile : public ELFFileBase { typedef ELFFileBase Base; + typedef typename ELFT::Rel Elf_Rel; + typedef typename ELFT::Rela Elf_Rela; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::SymRange Elf_Sym_Range; Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -379,17 +379,27 @@ InputSectionBase *Target = getRelocTarget(Sec); if (!Target) return nullptr; - if (auto *S = dyn_cast>(Target)) { - S->RelocSections.push_back(&Sec); - return nullptr; + const Elf_Rel *First; + size_t NumRelocations; + bool IsRela = Sec.sh_type == SHT_RELA; + if (IsRela) { + ArrayRef Rels = check(this->getObj().relas(&Sec)); + First = Rels.begin(); + NumRelocations = Rels.size(); + } else { + ArrayRef Rels = check(this->getObj().rels(&Sec)); + First = Rels.begin(); + NumRelocations = Rels.size(); } - if (auto *S = dyn_cast>(Target)) { - if (S->RelocSection) - fatal(getFilename(this) + - ": multiple relocation sections to .eh_frame are not supported"); - S->RelocSection = &Sec; + if (Target->FirstRelocation) + fatal(getFilename(this) + + ": multiple relocation sections to one section are not supported"); + Target->FirstRelocation = First; + Target->AreRelocsRela = IsRela; + assert(isUInt<31>(NumRelocations)); + Target->NumRelocations = NumRelocations; + if (isa>(Target) || isa>(Target)) return nullptr; - } fatal(getFilename(this) + ": relocations pointing to SHF_MERGE are not supported"); } Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -96,7 +96,10 @@ InputSectionBase() : InputSectionData(Regular, "", ArrayRef(), false, false), - Repl(this) {} + Repl(this) { + NumRelocations = 0; + AreRelocsRela = false; + } InputSectionBase(ObjectFile *File, const Elf_Shdr *Header, StringRef Name, Kind SectionKind); @@ -106,6 +109,20 @@ Kind SectionKind); OutputSectionBase *OutSec = nullptr; + // Relocations that refer to this section. + const Elf_Rel *FirstRelocation = nullptr; + unsigned NumRelocations : 31; + unsigned AreRelocsRela : 1; + ArrayRef rels() const { + assert(!AreRelocsRela); + return llvm::makeArrayRef(FirstRelocation, NumRelocations); + } + ArrayRef relas() const { + assert(AreRelocsRela); + return llvm::makeArrayRef(static_cast(FirstRelocation), + NumRelocations); + } + // This pointer points to the "real" instance of this instance. // Usually Repl == this. However, if ICF merges two sections, // Repl pointer of one section points to another section. So, @@ -219,8 +236,6 @@ // rather than a single large blob of data. std::vector Pieces; - // Relocation section that refer to this one. - const Elf_Shdr *RelocSection = nullptr; }; // This corresponds to a non SHF_MERGE section of an input file. @@ -245,9 +260,6 @@ // beginning of the output section. void writeTo(uint8_t *Buf); - // Relocation sections that refer to this one. - llvm::TinyPtrVector RelocSections; - // The offset from beginning of the output sections this section was assigned // to. The writer sets a value. uint64_t OutSecOff = 0; Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -55,6 +55,9 @@ !Config->GcSections || !(Flags & SHF_ALLOC)), File(File), Flags(Flags), Entsize(Entsize), Type(Type), Link(Link), Info(Info), Repl(this) { + NumRelocations = 0; + AreRelocsRela = false; + // The ELF spec states that a value of 0 means the section has // no alignment constraits. uint64_t V = std::max(Addralign, 1); @@ -471,12 +474,10 @@ // we handle relocations directly here. auto *IS = dyn_cast>(this); if (IS && !(IS->Flags & SHF_ALLOC)) { - for (const Elf_Shdr *RelSec : IS->RelocSections) { - if (RelSec->sh_type == SHT_RELA) - IS->relocateNonAlloc(Buf, check(IS->getObj().relas(RelSec))); - else - IS->relocateNonAlloc(Buf, check(IS->getObj().rels(RelSec))); - } + if (IS->AreRelocsRela) + IS->relocateNonAlloc(Buf, IS->relas()); + else + IS->relocateNonAlloc(Buf, IS->rels()); return; } @@ -609,12 +610,11 @@ if (!this->Pieces.empty()) return; - if (RelocSection) { - ELFFile Obj = this->getObj(); - if (RelocSection->sh_type == SHT_RELA) - split(check(Obj.relas(RelocSection))); + if (this->NumRelocations) { + if (this->AreRelocsRela) + split(this->relas()); else - split(check(Obj.rels(RelocSection))); + split(this->rels()); return; } split(makeArrayRef(nullptr, nullptr)); Index: ELF/MarkLive.cpp =================================================================== --- ELF/MarkLive.cpp +++ ELF/MarkLive.cpp @@ -80,15 +80,12 @@ template static void forEachSuccessor(InputSection &Sec, std::function)> Fn) { - ELFFile Obj = Sec.getFile()->getObj(); - for (const typename ELFT::Shdr *RelSec : Sec.RelocSections) { - if (RelSec->sh_type == SHT_RELA) { - for (const typename ELFT::Rela &Rel : check(Obj.relas(RelSec))) - Fn(resolveReloc(Sec, Rel)); - } else { - for (const typename ELFT::Rel &Rel : check(Obj.rels(RelSec))) - Fn(resolveReloc(Sec, Rel)); - } + if (Sec.AreRelocsRela) { + for (const typename ELFT::Rela &Rel : Sec.relas()) + Fn(resolveReloc(Sec, Rel)); + } else { + for (const typename ELFT::Rel &Rel : Sec.rels()) + Fn(resolveReloc(Sec, Rel)); } if (Sec.DependentSection) Fn({Sec.DependentSection, 0}); @@ -146,18 +143,17 @@ static void scanEhFrameSection(EhInputSection &EH, std::function)> Enqueue) { - if (!EH.RelocSection) + if (!EH.NumRelocations) return; // Unfortunately we need to split .eh_frame early since some relocations in // .eh_frame keep other section alive and some don't. EH.split(); - ELFFile EObj = EH.getFile()->getObj(); - if (EH.RelocSection->sh_type == SHT_RELA) - scanEhFrameSection(EH, check(EObj.relas(EH.RelocSection)), Enqueue); + if (EH.AreRelocsRela) + scanEhFrameSection(EH, EH.relas(), Enqueue); else - scanEhFrameSection(EH, check(EObj.rels(EH.RelocSection)), Enqueue); + scanEhFrameSection(EH, EH.rels(), Enqueue); } // We do not garbage-collect two types of sections: Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -1169,12 +1169,11 @@ if (Sec->Pieces.empty()) return; - if (const Elf_Shdr *RelSec = Sec->RelocSection) { - ELFFile Obj = Sec->getFile()->getObj(); - if (RelSec->sh_type == SHT_RELA) - addSectionAux(Sec, check(Obj.relas(RelSec))); + if (Sec->NumRelocations) { + if (Sec->AreRelocsRela) + addSectionAux(Sec, Sec->relas()); else - addSectionAux(Sec, check(Obj.rels(RelSec))); + addSectionAux(Sec, Sec->rels()); return; } addSectionAux(Sec, makeArrayRef(nullptr, nullptr)); Index: ELF/Relocations.h =================================================================== --- ELF/Relocations.h +++ ELF/Relocations.h @@ -81,11 +81,9 @@ SymbolBody *Sym; }; -template -void scanRelocations(InputSectionBase &, const typename ELFT::Shdr &); +template void scanRelocations(InputSectionBase &); -template -void createThunks(InputSectionBase &, const typename ELFT::Shdr &); +template void createThunks(InputSectionBase &); template std::string getLocation(InputSectionBase &S, typename ELFT::uint Offset); Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -796,14 +796,11 @@ } } -template -void scanRelocations(InputSectionBase &S, - const typename ELFT::Shdr &RelSec) { - ELFFile EObj = S.getFile()->getObj(); - if (RelSec.sh_type == SHT_RELA) - scanRelocs(S, check(EObj.relas(&RelSec))); +template void scanRelocations(InputSectionBase &S) { + if (S.AreRelocsRela) + scanRelocs(S, S.relas()); else - scanRelocs(S, check(EObj.rels(&RelSec))); + scanRelocs(S, S.rels()); } template @@ -826,33 +823,22 @@ } } -template -void createThunks(InputSectionBase &S, - const typename ELFT::Shdr &RelSec) { - ELFFile EObj = S.getFile()->getObj(); - if (RelSec.sh_type == SHT_RELA) - createThunks(S, check(EObj.relas(&RelSec))); +template void createThunks(InputSectionBase &S) { + if (S.AreRelocsRela) + createThunks(S, S.relas()); else - createThunks(S, check(EObj.rels(&RelSec))); + createThunks(S, S.rels()); } -template void scanRelocations(InputSectionBase &, - const ELF32LE::Shdr &); -template void scanRelocations(InputSectionBase &, - const ELF32BE::Shdr &); -template void scanRelocations(InputSectionBase &, - const ELF64LE::Shdr &); -template void scanRelocations(InputSectionBase &, - const ELF64BE::Shdr &); - -template void createThunks(InputSectionBase &, - const ELF32LE::Shdr &); -template void createThunks(InputSectionBase &, - const ELF32BE::Shdr &); -template void createThunks(InputSectionBase &, - const ELF64LE::Shdr &); -template void createThunks(InputSectionBase &, - const ELF64BE::Shdr &); +template void scanRelocations(InputSectionBase &); +template void scanRelocations(InputSectionBase &); +template void scanRelocations(InputSectionBase &); +template void scanRelocations(InputSectionBase &); + +template void createThunks(InputSectionBase &); +template void createThunks(InputSectionBase &); +template void createThunks(InputSectionBase &); +template void createThunks(InputSectionBase &); template std::string getLocation(InputSectionBase &S, uint32_t Offset); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -54,8 +54,7 @@ void addReservedSymbols(); void addInputSec(InputSectionBase *S); void createSections(); - void forEachRelSec(std::function &, - const typename ELFT::Shdr &)> Fn); + void forEachRelSec(std::function &)> Fn); void sortSections(); void finalizeSections(); void addPredefinedSections(); @@ -641,8 +640,7 @@ template void Writer::forEachRelSec( - std::function &, const typename ELFT::Shdr &)> - Fn) { + std::function &)> Fn) { for (InputSectionBase *IS : Symtab::X->Sections) { if (!IS->Live) continue; @@ -653,14 +651,8 @@ // processed by InputSection::relocateNonAlloc. if (!(IS->Flags & SHF_ALLOC)) continue; - if (auto *S = dyn_cast>(IS)) { - for (const Elf_Shdr *RelSec : S->RelocSections) - Fn(*S, *RelSec); - continue; - } - if (auto *S = dyn_cast>(IS)) - if (S->RelocSection) - Fn(*S, *S->RelocSection); + if (isa>(IS) || isa>(IS)) + Fn(*IS); } } Index: test/ELF/invalid/invalid-elf.test =================================================================== --- test/ELF/invalid/invalid-elf.test +++ test/ELF/invalid/invalid-elf.test @@ -26,6 +26,6 @@ # RUN: not ld.lld %p/Inputs/multiple-eh-relocs.elf -o %t2 2>&1 | \ # RUN: FileCheck --check-prefix=INVALID-EH-RELOCS %s -# INVALID-EH-RELOCS: multiple relocation sections to .eh_frame are not supported +# INVALID-EH-RELOCS: multiple relocation sections to one section are not supported .long foo