[lld] ELF: Split relocateAlloc to relocateAlloc and relocateEh. NFC (PR #160031)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Sep 21 22:08:03 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: Fangrui Song (MaskRay)
<details>
<summary>Changes</summary>
relocateAlloc can be called with either InputSection (including
SyntheticSection like GotSection) or EhInputSection.
Introduce relocateEh so that we can remove some boilerplate and replace
relocateAlloc's parameter type with `InputSection`.
---
Full diff: https://github.com/llvm/llvm-project/pull/160031.diff
13 Files Affected:
- (modified) lld/ELF/Arch/AArch64.cpp (+3-7)
- (modified) lld/ELF/Arch/LoongArch.cpp (+3-7)
- (modified) lld/ELF/Arch/PPC.cpp (+3-5)
- (modified) lld/ELF/Arch/PPC64.cpp (+3-7)
- (modified) lld/ELF/Arch/RISCV.cpp (+3-7)
- (modified) lld/ELF/Arch/X86.cpp (+3-5)
- (modified) lld/ELF/Arch/X86_64.cpp (+3-7)
- (modified) lld/ELF/InputSection.cpp (+1-1)
- (modified) lld/ELF/InputSection.h (+4-4)
- (modified) lld/ELF/Relocations.cpp (+1-1)
- (modified) lld/ELF/SyntheticSections.cpp (+1-1)
- (modified) lld/ELF/Target.cpp (+15-6)
- (modified) lld/ELF/Target.h (+2-1)
``````````diff
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<InputSection>(&sec))
- secAddr += s->outSecOff;
- else if (auto *ehIn = dyn_cast<EhInputSection>(&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<Relocation> 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<InputSection>(&sec))
- secAddr += s->outSecOff;
- else if (auto *ehIn = dyn_cast<EhInputSection>(&sec))
- secAddr += ehIn->getParent()->outSecOff;
+ uint64_t secAddr = sec.getOutputSection()->addr + sec.outSecOff;
bool isExtreme = false, isRelax = false;
const MutableArrayRef<Relocation> 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<InputSection>(&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<InputSection>(&sec))
- secAddr += s->outSecOff;
- else if (auto *ehIn = dyn_cast<EhInputSection>(&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 <class ELFT, class RelTy>
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<InputSection>(&sec))
- secAddr += s->outSecOff;
- else if (auto *ehIn = dyn_cast<EhInputSection>(&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<Relocation> 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<InputSection>(&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<InputSection>(&sec))
- secAddr += s->outSecOff;
- else if (auto *ehIn = dyn_cast<EhInputSection>(&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 <class ELFT>
-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<ELFT>()->splitStack))
adjustSplitStackFunctionPrologues<ELFT>(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 <class ELFT> 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 <class ELFT, class RelTy>
void relocateNonAlloc(Ctx &, uint8_t *buf, Relocs<RelTy> rels);
+ template <class ELFT> 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..62f2844e72cf6 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1549,7 +1549,7 @@ void RelocationScanner::scanOne(typename Relocs<RelTy>::const_iterator &i) {
sec->file->ppc64SmallCodeModelTocRelocs = true;
// Record the TOC entry (.toc + addend) as not relaxable. See the comment in
- // InputSectionBase::relocateAlloc().
+ // InputSection::relocateAlloc().
if (type == R_PPC64_TOC16_LO && sym.isSection() && isa<Defined>(sym) &&
cast<Defined>(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..bff34a6eabf8f 100644
--- a/lld/ELF/Target.cpp
+++ b/lld/ELF/Target.cpp
@@ -148,13 +148,22 @@ RelExpr TargetInfo::adjustGotPcExpr(RelType type, int64_t addend,
return R_GOT_PC;
}
-void TargetInfo::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
+void TargetInfo::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<InputSection>(&sec))
- secAddr += s->outSecOff;
- else if (auto *ehIn = dyn_cast<EhInputSection>(&sec))
- secAddr += ehIn->getParent()->outSecOff;
+ uint64_t secAddr = sec.getOutputSection()->addr + sec.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);
+ }
+}
+
+// A variant of relocateAlloc that processes an EhInputSection.
+void TargetInfo::relocateEh(EhInputSection &sec, uint8_t *buf) const {
+ const unsigned bits = ctx.arg.is64 ? 64 : 32;
+ uint64_t secAddr = sec.getOutputSection()->addr + sec.getParent()->outSecOff;
for (const Relocation &rel : sec.relocs()) {
uint8_t *loc = buf + rel.offset;
const uint64_t val = SignExtend64(
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; }
``````````
</details>
https://github.com/llvm/llvm-project/pull/160031
More information about the llvm-commits
mailing list