Index: lld/trunk/ELF/InputSection.h =================================================================== --- lld/trunk/ELF/InputSection.h +++ lld/trunk/ELF/InputSection.h @@ -218,6 +218,9 @@ // 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); Index: lld/trunk/ELF/InputSection.cpp =================================================================== --- lld/trunk/ELF/InputSection.cpp +++ lld/trunk/ELF/InputSection.cpp @@ -226,8 +226,50 @@ 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; Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -532,12 +532,10 @@ 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 @@ // 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 @@ 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 @@ // 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 Index: lld/trunk/test/ELF/relocation-non-alloc.s =================================================================== --- lld/trunk/test/ELF/relocation-non-alloc.s +++ lld/trunk/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 [