diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 27e77e943c197..2a97df4785ecb 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -82,7 +82,7 @@ class AArch64 : public TargetInfo { void relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const override; RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override; - void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override; + void relocateAlloc(InputSection &sec, uint8_t *buf) const override; void applyBranchToBranchOpt() const override; private: @@ -939,12 +939,8 @@ static bool needsGotForMemtag(const Relocation &rel) { return rel.sym->isTagged() && needsGot(rel.expr); } -void AArch64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { - uint64_t secAddr = sec.getOutputSection()->addr; - if (auto *s = dyn_cast(&sec)) - secAddr += s->outSecOff; - else if (auto *ehIn = dyn_cast(&sec)) - secAddr += ehIn->getParent()->outSecOff; +void AArch64::relocateAlloc(InputSection &sec, uint8_t *buf) const { + uint64_t secAddr = sec.getOutputSection()->addr + sec.outSecOff; AArch64Relaxer relaxer(ctx, sec.relocs()); for (size_t i = 0, size = sec.relocs().size(); i != size; ++i) { const Relocation &rel = sec.relocs()[i]; diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp index db2c71c3b42b9..c6cdf05547d3f 100644 --- a/lld/ELF/Arch/LoongArch.cpp +++ b/lld/ELF/Arch/LoongArch.cpp @@ -41,7 +41,7 @@ class LoongArch final : public TargetInfo { bool relaxOnce(int pass) const override; bool synthesizeAlign(uint64_t &dot, InputSection *sec) override; RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override; - void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override; + void relocateAlloc(InputSection &sec, uint8_t *buf) const override; void finalizeRelax(int passes) const override; private: @@ -1395,13 +1395,9 @@ static bool pairForGotRels(ArrayRef relocs) { return i == size; } -void LoongArch::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { +void LoongArch::relocateAlloc(InputSection &sec, uint8_t *buf) const { const unsigned bits = ctx.arg.is64 ? 64 : 32; - uint64_t secAddr = sec.getOutputSection()->addr; - if (auto *s = dyn_cast(&sec)) - secAddr += s->outSecOff; - else if (auto *ehIn = dyn_cast(&sec)) - secAddr += ehIn->getParent()->outSecOff; + uint64_t secAddr = sec.getOutputSection()->addr + sec.outSecOff; bool isExtreme = false, isRelax = false; const MutableArrayRef relocs = sec.relocs(); const bool isPairForGotRels = pairForGotRels(relocs); diff --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp index 60a0a38d5f23a..5972698b34a2c 100644 --- a/lld/ELF/Arch/PPC.cpp +++ b/lld/ELF/Arch/PPC.cpp @@ -49,7 +49,7 @@ class PPC final : public TargetInfo { uint64_t val) const override; RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override; int getTlsGdRelaxSkip(RelType type) const override; - void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override; + void relocateAlloc(InputSection &sec, uint8_t *buf) const override; private: void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) const; @@ -496,10 +496,8 @@ void PPC::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, } } -void PPC::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { - uint64_t secAddr = sec.getOutputSection()->addr; - if (auto *s = dyn_cast(&sec)) - secAddr += s->outSecOff; +void PPC::relocateAlloc(InputSection &sec, uint8_t *buf) const { + uint64_t secAddr = sec.getOutputSection()->addr + sec.outSecOff; for (const Relocation &rel : sec.relocs()) { uint8_t *loc = buf + rel.offset; const uint64_t val = diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index 3cd4a6294e2a8..550c091624bb5 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -190,7 +190,7 @@ class PPC64 final : public TargetInfo { RelExpr adjustGotPcExpr(RelType type, int64_t addend, const uint8_t *loc) const override; void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) const; - void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override; + void relocateAlloc(InputSection &sec, uint8_t *buf) const override; bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end, uint8_t stOther) const override; @@ -1561,12 +1561,8 @@ void PPC64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, } } -void PPC64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { - uint64_t secAddr = sec.getOutputSection()->addr; - if (auto *s = dyn_cast(&sec)) - secAddr += s->outSecOff; - else if (auto *ehIn = dyn_cast(&sec)) - secAddr += ehIn->getParent()->outSecOff; +void PPC64::relocateAlloc(InputSection &sec, uint8_t *buf) const { + uint64_t secAddr = sec.getOutputSection()->addr + sec.outSecOff; uint64_t lastPPCRelaxedRelocOff = -1; for (const Relocation &rel : sec.relocs()) { uint8_t *loc = buf + rel.offset; diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp index 7f2bfefa5578a..dc2ab97e9d9be 100644 --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -43,7 +43,7 @@ class RISCV final : public TargetInfo { const uint8_t *loc) const override; void relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const override; - void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override; + void relocateAlloc(InputSection &sec, uint8_t *buf) const override; bool relaxOnce(int pass) const override; template bool synthesizeAlignForInput(uint64_t &dot, InputSection *sec, @@ -603,12 +603,8 @@ static void tlsdescToLe(uint8_t *loc, const Relocation &rel, uint64_t val) { } } -void RISCV::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { - uint64_t secAddr = sec.getOutputSection()->addr; - if (auto *s = dyn_cast(&sec)) - secAddr += s->outSecOff; - else if (auto *ehIn = dyn_cast(&sec)) - secAddr += ehIn->getParent()->outSecOff; +void RISCV::relocateAlloc(InputSection &sec, uint8_t *buf) const { + uint64_t secAddr = sec.getOutputSection()->addr + sec.outSecOff; uint64_t tlsdescVal = 0; bool tlsdescRelax = false, isToLe = false; const ArrayRef relocs = sec.relocs(); diff --git a/lld/ELF/Arch/X86.cpp b/lld/ELF/Arch/X86.cpp index c1980d6e0538f..904741fd72b0a 100644 --- a/lld/ELF/Arch/X86.cpp +++ b/lld/ELF/Arch/X86.cpp @@ -37,7 +37,7 @@ class X86 : public TargetInfo { uint64_t val) const override; RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override; - void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override; + void relocateAlloc(InputSection &sec, uint8_t *buf) const override; private: void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const; @@ -491,10 +491,8 @@ void X86::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, memcpy(loc - 2, inst, sizeof(inst)); } -void X86::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { - uint64_t secAddr = sec.getOutputSection()->addr; - if (auto *s = dyn_cast(&sec)) - secAddr += s->outSecOff; +void X86::relocateAlloc(InputSection &sec, uint8_t *buf) const { + uint64_t secAddr = sec.getOutputSection()->addr + sec.outSecOff; for (const Relocation &rel : sec.relocs()) { uint8_t *loc = buf + rel.offset; const uint64_t val = diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp index 488f4803b2cb4..9083b5b9ff250 100644 --- a/lld/ELF/Arch/X86_64.cpp +++ b/lld/ELF/Arch/X86_64.cpp @@ -44,7 +44,7 @@ class X86_64 : public TargetInfo { unsigned size) const override; RelExpr adjustGotPcExpr(RelType type, int64_t addend, const uint8_t *loc) const override; - void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override; + void relocateAlloc(InputSection &sec, uint8_t *buf) const override; bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end, uint8_t stOther) const override; bool deleteFallThruJmpInsn(InputSection &is, InputFile *file, @@ -1146,12 +1146,8 @@ bool X86_64::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end, return false; } -void X86_64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { - uint64_t secAddr = sec.getOutputSection()->addr; - if (auto *s = dyn_cast(&sec)) - secAddr += s->outSecOff; - else if (auto *ehIn = dyn_cast(&sec)) - secAddr += ehIn->getParent()->outSecOff; +void X86_64::relocateAlloc(InputSection &sec, uint8_t *buf) const { + uint64_t secAddr = sec.getOutputSection()->addr + sec.outSecOff; for (const Relocation &rel : sec.relocs()) { if (rel.expr == R_NONE) // See deleteFallThruJmpInsn continue; diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index ea6bcc5bb272b..98267d1e081db 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -1171,7 +1171,7 @@ void InputSection::relocateNonAlloc(Ctx &ctx, uint8_t *buf, } template -void InputSectionBase::relocate(Ctx &ctx, uint8_t *buf, uint8_t *bufEnd) { +void InputSection::relocate(Ctx &ctx, uint8_t *buf, uint8_t *bufEnd) { if ((flags & SHF_EXECINSTR) && LLVM_UNLIKELY(getFile()->splitStack)) adjustSplitStackFunctionPrologues(ctx, buf, bufEnd); diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 98e7d5d4ff0cd..8462f03bdb77e 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -262,10 +262,6 @@ class InputSectionBase : public SectionBase { return {*this, sym, offset}; } - // Each section knows how to relocate itself. These functions apply - // relocations, assuming that Buf points to this section's copy in - // the mmap'ed output buffer. - template void relocate(Ctx &, uint8_t *buf, uint8_t *bufEnd); uint64_t getRelocTargetVA(Ctx &, const Relocation &r, uint64_t p) const; // The native ELF reloc data type is not very convenient to handle. @@ -443,8 +439,12 @@ class InputSection : public InputSectionBase { InputSectionBase *getRelocatedSection() const; + // Each section knows how to relocate itself. These functions apply + // relocations, assuming that `buf` points to this section's copy in + // the mmap'ed output buffer. template void relocateNonAlloc(Ctx &, uint8_t *buf, Relocs rels); + template void relocate(Ctx &, uint8_t *buf, uint8_t *bufEnd); // Points to the canonical section. If ICF folds two sections, repl pointer of // one section points to the other. diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 6f55bac2ecf16..bd96c051d160d 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1549,7 +1549,7 @@ void RelocationScanner::scanOne(typename Relocs::const_iterator &i) { sec->file->ppc64SmallCodeModelTocRelocs = true; // Record the TOC entry (.toc + addend) as not relaxable. See the comment in - // InputSectionBase::relocateAlloc(). + // PPC64::relocateAlloc(). if (type == R_PPC64_TOC16_LO && sym.isSection() && isa(sym) && cast(sym).section->name == ".toc") ctx.ppc64noTocRelax.insert({&sym, addend}); diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 0d87f9a66071a..0e96e37ecb9c1 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -662,7 +662,7 @@ void EhFrameSection::writeTo(uint8_t *buf) { // in the output buffer, but relocateAlloc() still works because // getOffset() takes care of discontiguous section pieces. for (EhInputSection *s : sections) - ctx.target->relocateAlloc(*s, buf); + ctx.target->relocateEh(*s, buf); if (getPartition(ctx).ehFrameHdr && getPartition(ctx).ehFrameHdr->getParent()) getPartition(ctx).ehFrameHdr->write(); diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 4946484074d05..fb79ee911273a 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -148,22 +148,30 @@ RelExpr TargetInfo::adjustGotPcExpr(RelType type, int64_t addend, return R_GOT_PC; } -void TargetInfo::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { +static void relocateImpl(const TargetInfo &target, InputSectionBase &sec, + uint64_t secAddr, uint8_t *buf) { + auto &ctx = target.ctx; const unsigned bits = ctx.arg.is64 ? 64 : 32; - uint64_t secAddr = sec.getOutputSection()->addr; - if (auto *s = dyn_cast(&sec)) - secAddr += s->outSecOff; - else if (auto *ehIn = dyn_cast(&sec)) - secAddr += ehIn->getParent()->outSecOff; for (const Relocation &rel : sec.relocs()) { uint8_t *loc = buf + rel.offset; const uint64_t val = SignExtend64( sec.getRelocTargetVA(ctx, rel, secAddr + rel.offset), bits); if (rel.expr != R_RELAX_HINT) - relocate(loc, rel, val); + target.relocate(loc, rel, val); } } +void TargetInfo::relocateAlloc(InputSection &sec, uint8_t *buf) const { + uint64_t secAddr = sec.getOutputSection()->addr + sec.outSecOff; + relocateImpl(*this, sec, secAddr, buf); +} + +// A variant of relocateAlloc that processes an EhInputSection. +void TargetInfo::relocateEh(EhInputSection &sec, uint8_t *buf) const { + uint64_t secAddr = sec.getOutputSection()->addr + sec.getParent()->outSecOff; + relocateImpl(*this, sec, secAddr, buf); +} + uint64_t TargetInfo::getImageBase() const { // Use --image-base if set. Fall back to the target default if not. if (ctx.arg.imageBase) diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index bb8c24f052aa2..9f0605138a4fb 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -92,7 +92,8 @@ class TargetInfo { void relocateNoSym(uint8_t *loc, RelType type, uint64_t val) const { relocate(loc, Relocation{R_NONE, type, 0, 0, nullptr}, val); } - virtual void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const; + virtual void relocateAlloc(InputSection &sec, uint8_t *buf) const; + void relocateEh(EhInputSection &sec, uint8_t *buf) const; // Do a linker relaxation pass and return true if we changed something. virtual bool relaxOnce(int pass) const { return false; }