Author: hev Date: 2026-01-22T08:27:36Z New Revision: 43299d52234bd98ca649329c49d513351c586b44
URL: https://github.com/llvm/llvm-project/commit/43299d52234bd98ca649329c49d513351c586b44 DIFF: https://github.com/llvm/llvm-project/commit/43299d52234bd98ca649329c49d513351c586b44.diff LOG: [lld][ELF] Deduplicate PC-relative indirect relocation logic for RISC-V and LoongArch (#176312) (cherry picked from commit 3af2e51eb91a96232efc4497059d5c6360cc094b) Added: Modified: lld/ELF/InputSection.cpp Removed: ################################################################################ diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index a9afd3449ebb2..7402c8454c023 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -661,68 +661,41 @@ 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; - - 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; +struct RISCVPCRel { + static constexpr const char *loReloc = "R_RISCV_PCREL_LO12"; + static constexpr const char *hiReloc = "R_RISCV_PCREL_HI20"; + + static bool isHiReloc(uint32_t type) { + return is_contained({R_RISCV_PCREL_HI20, R_RISCV_GOT_HI20, + R_RISCV_TLS_GD_HI20, R_RISCV_TLS_GOT_HI20}, + type); } - 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 diff erent 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 is_contained({R_LARCH_PCADD_HI20, R_LARCH_GOT_PCADD_HI20, + R_LARCH_TLS_IE_PCADD_HI20, R_LARCH_TLS_LD_PCADD_HI20, + R_LARCH_TLS_GD_PCADD_HI20, + R_LARCH_TLS_DESC_PCADD_HI20}, + type); + } +}; -// 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 +706,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 diff erent section '" << hiSec->name - << "'"; + Err(ctx) << loSec->getLocation(loReloc.offset) << ": " << PCRel::loReloc + << " relocation points to a symbol '" << sym->getName() + << "' in a diff erent 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 +735,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 +919,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; } _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
