Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -218,6 +218,9 @@ // Size of chunk with thunks code. uint64_t getThunksSize() const; + template + void relocateNative(uint8_t *Buf, llvm::ArrayRef Rels); + private: template void copyRelocations(uint8_t *Buf, llvm::ArrayRef Rels); Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ 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 section is +// 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::relocateNative(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->relocateNative(Buf, IS->File->getObj().relas(RelSec)); + else + IS->relocateNative(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: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -744,17 +744,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: test/ELF/relocation-non-alloc.s =================================================================== --- test/ELF/relocation-non-alloc.s +++ 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 [