From 2b6fb803840d20ee7e93fd947b4990a983ed3652 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 28 Apr 2016 18:42:04 +0000 Subject: [PATCH] Skip scanRelocs for non-alloc sections. Relocations against sections with no SHF_ALLOC bit are R_ABS relocations. Currently we are creating Relocations vector for them, but that is wasteful. This patch is to skip vector construction and to directly apply relocations in place. This patch seems to be pretty effective for large executables with debug info. r266158 (Rafael's patch to change the way how we apply relocations) caused a temporary performance degradation for such executables, but this patch makes it even faster than before. Time to link clang with debug info (output size is 1070 MB): before r266158: 15.312 seconds (0%) r266158: 17.301 seconds (+13.0%) Head: 16.484 seconds (+7.7%) w/patch: 13.166 seconds (-14.0%) Differential Revision: http://reviews.llvm.org/D19645 llvm-svn: 267917 --- lld/ELF/InputSection.cpp | 42 +++++++++++++++++++++++++++++ lld/ELF/InputSection.h | 3 +++ lld/ELF/Writer.cpp | 29 +++++++------------- lld/test/ELF/relocation-non-alloc.s | 2 +- 4 files changed, 56 insertions(+), 20 deletions(-) diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 59625edec9b7..0ab60f425e0a 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -226,8 +226,50 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P, llvm_unreachable("Invalid expression"); } +// This function applies relocations to sections without SHF_ALLOC bit. +// Such sections are never mapped to memory at runtime. Debug sections are +// an example. Relocations in non-alloc sections are much easier to +// handle than in allocated sections because it will never need complex +// treatement such as GOT or PLT (because at runtime no one refers them). +// So, we handle relocations for non-alloc sections directly in this +// function as a performance optimization. +template +template +void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef Rels) { + const unsigned Bits = sizeof(uintX_t) * 8; + for (const RelTy &Rel : Rels) { + uint8_t *BufLoc = Buf + Rel.r_offset; + uintX_t AddrLoc = this->OutSec->getVA() + Rel.r_offset; + uint32_t Type = Rel.getType(Config->Mips64EL); + SymbolBody &Sym = this->File->getRelocTargetSym(Rel); + + if (Target->getRelExpr(Type, Sym) != R_ABS) { + error(this->getSectionName() + " has non-ABS reloc"); + return; + } + + uint64_t SymVA = SignExtend64(getSymVA( + Type, getAddend(Rel), AddrLoc, Sym, BufLoc, *this->File, R_ABS)); + Target->relocateOne(BufLoc, Type, SymVA); + } +} + template void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) { + // scanReloc function in Writer.cpp constructs Relocations + // vector only for SHF_ALLOC'ed sections. For other sections, + // we handle relocations directly here. + auto *IS = dyn_cast>(this); + if (IS && !(IS->Header->sh_flags & SHF_ALLOC)) { + for (const Elf_Shdr *RelSec : IS->RelocSections) { + if (RelSec->sh_type == SHT_RELA) + IS->relocateNonAlloc(Buf, IS->File->getObj().relas(RelSec)); + else + IS->relocateNonAlloc(Buf, IS->File->getObj().rels(RelSec)); + } + return; + } + const unsigned Bits = sizeof(uintX_t) * 8; for (const Relocation &Rel : Relocations) { uintX_t Offset = Rel.Offset; diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 3fd5d12579b9..21e536f2f6af 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -218,6 +218,9 @@ public: // Size of chunk with thunks code. uint64_t getThunksSize() const; + template + void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef Rels); + private: template void copyRelocations(uint8_t *Buf, llvm::ArrayRef Rels); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index c4d515ce0e89..514b21a58267 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -532,12 +532,10 @@ template template void Writer::scanRelocs(InputSectionBase &C, ArrayRef Rels) { uintX_t Flags = C.getSectionHdr()->sh_flags; - bool IsAlloc = Flags & SHF_ALLOC; bool IsWrite = Flags & SHF_WRITE; auto AddDyn = [=](const DynamicReloc &Reloc) { - if (IsAlloc) - Out::RelaDyn->addReloc(Reloc); + Out::RelaDyn->addReloc(Reloc); }; const elf::ObjectFile &File = *C.getFile(); @@ -593,7 +591,7 @@ void Writer::scanRelocs(InputSectionBase &C, ArrayRef Rels) { // in a read-only section, we need to create a copy relocation for the // symbol. if (auto *B = dyn_cast>(&Body)) { - if (IsAlloc && !IsWrite && needsCopyRel(Expr, *B)) { + if (!IsWrite && needsCopyRel(Expr, *B)) { if (!B->needsCopy()) addCopyRelSymbol(B); C.Relocations.push_back({Expr, Type, Offset, Addend, &Body}); @@ -630,10 +628,9 @@ void Writer::scanRelocs(InputSectionBase &C, ArrayRef Rels) { if (Target->UseLazyBinding) { Out::GotPlt->addEntry(Body); - if (IsAlloc) - Out::RelaPlt->addReloc({Rel, Out::GotPlt, - Body.getGotPltOffset(), - !Preemptible, &Body, 0}); + Out::RelaPlt->addReloc({Rel, Out::GotPlt, + Body.getGotPltOffset(), + !Preemptible, &Body, 0}); } else { if (Body.isInGot()) continue; @@ -744,17 +741,11 @@ template void Writer::scanRelocs(InputSection &C) { // Scan all relocations. Each relocation goes through a series // of tests to determine if it needs special treatment, such as // creating GOT, PLT, copy relocations, etc. - // - // The current code is a bit wasteful because it scans relocations - // in non-SHF_ALLOC sections. Such sections are never mapped to - // memory at runtime. Debug section is an example. Relocations in - // non-alloc sections are much easier to handle because it will - // never need complex treatement such as GOT or PLT (because at - // runtime no one refers them). We probably should skip non-alloc - // sections here and directly handle non-alloc relocations in - // writeTo function. - for (const Elf_Shdr *RelSec : C.RelocSections) - scanRelocs(C, *RelSec); + // Note that relocations for non-alloc sections are directly + // processed by InputSection::relocateNative. + if (C.getSectionHdr()->sh_flags & SHF_ALLOC) + for (const Elf_Shdr *RelSec : C.RelocSections) + scanRelocs(C, *RelSec); } template diff --git a/lld/test/ELF/relocation-non-alloc.s b/lld/test/ELF/relocation-non-alloc.s index da6041db46a4..7dd850526ace 100644 --- a/lld/test/ELF/relocation-non-alloc.s +++ b/lld/test/ELF/relocation-non-alloc.s @@ -33,7 +33,7 @@ // CHECK-NEXT: AddressAlignment: 1 // CHECK-NEXT: EntrySize: 0 // CHECK-NEXT: SectionData ( -// CHECK-NEXT: 0000: 00100000 00000000 00000000 00000000 +// CHECK-NEXT: 0000: 00100000 00000000 00100000 00000000 // CHECK-NEXT: ) // CHECK: Relocations [