mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-11 12:16:07 +00:00
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
This commit is contained in:
parent
c5fce69031
commit
2b6fb80384
@ -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 <class ELFT>
|
||||
template <class RelTy>
|
||||
void InputSection<ELFT>::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> 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<Bits>(getSymVA<ELFT>(
|
||||
Type, getAddend<ELFT>(Rel), AddrLoc, Sym, BufLoc, *this->File, R_ABS));
|
||||
Target->relocateOne(BufLoc, Type, SymVA);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void InputSectionBase<ELFT>::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<InputSection<ELFT>>(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;
|
||||
|
@ -218,6 +218,9 @@ public:
|
||||
// Size of chunk with thunks code.
|
||||
uint64_t getThunksSize() const;
|
||||
|
||||
template <class RelTy>
|
||||
void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
|
||||
|
||||
private:
|
||||
template <class RelTy>
|
||||
void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
|
||||
|
@ -532,12 +532,10 @@ template <class ELFT>
|
||||
template <class RelTy>
|
||||
void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
|
||||
uintX_t Flags = C.getSectionHdr()->sh_flags;
|
||||
bool IsAlloc = Flags & SHF_ALLOC;
|
||||
bool IsWrite = Flags & SHF_WRITE;
|
||||
|
||||
auto AddDyn = [=](const DynamicReloc<ELFT> &Reloc) {
|
||||
if (IsAlloc)
|
||||
Out<ELFT>::RelaDyn->addReloc(Reloc);
|
||||
Out<ELFT>::RelaDyn->addReloc(Reloc);
|
||||
};
|
||||
|
||||
const elf::ObjectFile<ELFT> &File = *C.getFile();
|
||||
@ -593,7 +591,7 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
|
||||
// in a read-only section, we need to create a copy relocation for the
|
||||
// symbol.
|
||||
if (auto *B = dyn_cast<SharedSymbol<ELFT>>(&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<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
|
||||
|
||||
if (Target->UseLazyBinding) {
|
||||
Out<ELFT>::GotPlt->addEntry(Body);
|
||||
if (IsAlloc)
|
||||
Out<ELFT>::RelaPlt->addReloc({Rel, Out<ELFT>::GotPlt,
|
||||
Body.getGotPltOffset<ELFT>(),
|
||||
!Preemptible, &Body, 0});
|
||||
Out<ELFT>::RelaPlt->addReloc({Rel, Out<ELFT>::GotPlt,
|
||||
Body.getGotPltOffset<ELFT>(),
|
||||
!Preemptible, &Body, 0});
|
||||
} else {
|
||||
if (Body.isInGot())
|
||||
continue;
|
||||
@ -744,17 +741,11 @@ template <class ELFT> void Writer<ELFT>::scanRelocs(InputSection<ELFT> &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 <class ELFT>
|
||||
|
@ -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 [
|
||||
|
Loading…
x
Reference in New Issue
Block a user