[lld][ELF] Deduplicate PC-relative indirect relocation logic for RISC-V and LoongArch#176312
Merged
Conversation
Member
|
@llvm/pr-subscribers-lld @llvm/pr-subscribers-lld-elf Author: hev (heiher) ChangesFull diff: https://github.com/llvm/llvm-project/pull/176312.diff 1 Files Affected:
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index a9afd3449ebb2..e2d2a8a49a47c 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -661,68 +661,40 @@ static uint64_t getARMStaticBase(const Symbol &sym) {
return os->ptLoad->firstSec->addr;
}
-// For RE_RISCV_PC_INDIRECT (R_RISCV_PCREL_LO12_{I,S}), the symbol actually
-// points the corresponding R_RISCV_PCREL_HI20 relocation, and the target VA
-// is calculated using PCREL_HI20's symbol.
-//
-// This function returns the R_RISCV_PCREL_HI20 relocation from the
-// R_RISCV_PCREL_LO12 relocation.
-static Relocation *getRISCVPCRelHi20(Ctx &ctx, const InputSectionBase *loSec,
- const Relocation &loReloc) {
- uint64_t addend = loReloc.addend;
- Symbol *sym = loReloc.sym;
+struct RISCVPCRel {
+ static constexpr const char *loReloc = "R_RISCV_PCREL_LO12";
+ static constexpr const char *hiReloc = "R_RISCV_PCREL_HI20";
- const Defined *d = cast<Defined>(sym);
- if (!d->section) {
- Err(ctx) << loSec->getLocation(loReloc.offset)
- << ": R_RISCV_PCREL_LO12 relocation points to an absolute symbol: "
- << sym->getName();
- return nullptr;
+ static bool isHiReloc(uint32_t type) {
+ return type == R_RISCV_PCREL_HI20 || type == R_RISCV_GOT_HI20 ||
+ type == R_RISCV_TLS_GD_HI20 || type == R_RISCV_TLS_GOT_HI20;
}
- InputSection *hiSec = cast<InputSection>(d->section);
-
- if (hiSec != loSec)
- Err(ctx) << loSec->getLocation(loReloc.offset)
- << ": R_RISCV_PCREL_LO12 relocation points to a symbol '"
- << sym->getName() << "' in a different section '" << hiSec->name
- << "'";
-
- if (addend != 0)
- Warn(ctx) << loSec->getLocation(loReloc.offset)
- << ": non-zero addend in R_RISCV_PCREL_LO12 relocation to "
- << hiSec->getObjMsg(d->value) << " is ignored";
-
- // Relocations are sorted by offset, so we can use std::equal_range to do
- // binary search.
- Relocation hiReloc;
- hiReloc.offset = d->value;
- auto range =
- std::equal_range(hiSec->relocs().begin(), hiSec->relocs().end(), hiReloc,
- [](const Relocation &lhs, const Relocation &rhs) {
- return lhs.offset < rhs.offset;
- });
-
- for (auto it = range.first; it != range.second; ++it)
- if (it->type == R_RISCV_PCREL_HI20 || it->type == R_RISCV_GOT_HI20 ||
- it->type == R_RISCV_TLS_GD_HI20 || it->type == R_RISCV_TLS_GOT_HI20)
- return &*it;
-
- Err(ctx) << loSec->getLocation(loReloc.offset)
- << ": R_RISCV_PCREL_LO12 relocation points to "
- << hiSec->getObjMsg(d->value)
- << " without an associated R_RISCV_PCREL_HI20 relocation";
- return nullptr;
-}
+};
+
+struct LoongArchPCAdd {
+ static constexpr const char *loReloc = "R_LARCH_*PCADD_LO12";
+ static constexpr const char *hiReloc = "R_LARCH_*PCADD_HI20";
+
+ static bool isHiReloc(uint32_t type) {
+ return type == R_LARCH_PCADD_HI20 || type == R_LARCH_GOT_PCADD_HI20 ||
+ type == R_LARCH_TLS_IE_PCADD_HI20 ||
+ type == R_LARCH_TLS_LD_PCADD_HI20 ||
+ type == R_LARCH_TLS_GD_PCADD_HI20 ||
+ type == R_LARCH_TLS_DESC_PCADD_HI20;
+ }
+};
-// For RE_LARCH_PC_INDIRECT (R_LARCH_*PCADD_LO12), the symbol actually points
-// the corresponding R_LARCH_*PCADD_HI20 relocation, and the target VA is
-// calculated using PCADD_HI20's symbol.
+// For PC-relative indirect relocations (e.g. R_RISCV_PCREL_LO12_* and
+// R_LARCH_*PCADD_LO12), the symbol referenced by the LO12 relocation does not
+// directly represent the final target address. Instead, it points to the
+// corresponding HI20 relocation, and the target VA is computed using the
+// symbol associated with that HI20 relocation.
//
-// This function returns the R_LARCH_*PCADD_HI20 relocation from the
-// R_LARCH_*PCADD_LO12 relocation.
-static Relocation *getLoongArchPCAddHi20(Ctx &ctx,
- const InputSectionBase *loSec,
- const Relocation &loReloc) {
+// This helper locates and returns the matching HI20 relocation corresponding
+// to a given LO12 relocation.
+template <typename PCRel>
+static Relocation *getPCRelHi20(Ctx &ctx, const InputSectionBase *loSec,
+ const Relocation &loReloc) {
int64_t addend = loReloc.addend;
Symbol *sym = loReloc.sym;
@@ -733,25 +705,22 @@ static Relocation *getLoongArchPCAddHi20(Ctx &ctx,
return nullptr;
}
if (!d->section) {
- Err(ctx)
- << loSec->getLocation(loReloc.offset)
- << ": R_LARCH_*PCADD_LO12 relocation points to an absolute symbol: "
- << sym->getName();
+ Err(ctx) << loSec->getLocation(loReloc.offset) << ": " << PCRel::loReloc
+ << " relocation points to an absolute symbol: " << sym->getName();
return nullptr;
}
InputSection *hiSec = cast<InputSection>(d->section);
if (hiSec != loSec) {
- Err(ctx) << loSec->getLocation(loReloc.offset)
- << ": R_LARCH_*PCADD_LO12 relocation points to a symbol '"
- << sym->getName() << "' in a different section '" << hiSec->name
- << "'";
+ Err(ctx) << loSec->getLocation(loReloc.offset) << ": " << PCRel::loReloc
+ << " relocation points to a symbol '" << sym->getName()
+ << "' in a different section '" << hiSec->name << "'";
return nullptr;
}
if (addend != 0)
- Warn(ctx) << loSec->getLocation(loReloc.offset)
- << ": non-zero addend in R_LARCH_*PCADD_LO12 relocation to "
+ Warn(ctx) << loSec->getLocation(loReloc.offset) << ": non-zero addend in "
+ << PCRel::loReloc << " relocation to "
<< hiSec->getObjMsg(d->value) << " is ignored";
// Relocations are sorted by offset, so we can use std::equal_range to do
@@ -765,17 +734,12 @@ static Relocation *getLoongArchPCAddHi20(Ctx &ctx,
});
for (auto it = range.first; it != range.second; ++it)
- if (it->type == R_LARCH_PCADD_HI20 || it->type == R_LARCH_GOT_PCADD_HI20 ||
- it->type == R_LARCH_TLS_IE_PCADD_HI20 ||
- it->type == R_LARCH_TLS_LD_PCADD_HI20 ||
- it->type == R_LARCH_TLS_GD_PCADD_HI20 ||
- it->type == R_LARCH_TLS_DESC_PCADD_HI20)
+ if (PCRel::isHiReloc(it->type))
return &*it;
- Err(ctx) << loSec->getLocation(loReloc.offset)
- << ": R_LARCH_*PCADD_LO12 relocation points to "
- << hiSec->getObjMsg(d->value)
- << " without an associated R_LARCH_*PCADD_HI20 relocation";
+ Err(ctx) << loSec->getLocation(loReloc.offset) << ": " << PCRel::loReloc
+ << " relocation points to " << hiSec->getObjMsg(d->value)
+ << " without an associated " << PCRel::hiReloc << " relocation";
return nullptr;
}
@@ -954,12 +918,12 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
return getAArch64Page(val) - getAArch64Page(p);
}
case RE_RISCV_PC_INDIRECT: {
- if (const Relocation *hiRel = getRISCVPCRelHi20(ctx, this, r))
+ if (const Relocation *hiRel = getPCRelHi20<RISCVPCRel>(ctx, this, r))
return getRelocTargetVA(ctx, *hiRel, r.sym->getVA(ctx));
return 0;
}
case RE_LOONGARCH_PC_INDIRECT: {
- if (const Relocation *hiRel = getLoongArchPCAddHi20(ctx, this, r))
+ if (const Relocation *hiRel = getPCRelHi20<LoongArchPCAdd>(ctx, this, r))
return getRelocTargetVA(ctx, *hiRel, r.sym->getVA(ctx, a));
return 0;
}
|
MaskRay
approved these changes
Jan 16, 2026
kkwli
pushed a commit
to kkwli/llvm-project
that referenced
this pull request
Jan 16, 2026
…-V and LoongArch (llvm#176312)
Priyanshu3820
pushed a commit
to Priyanshu3820/llvm-project
that referenced
this pull request
Jan 18, 2026
…-V and LoongArch (llvm#176312)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.