[lld] [ELF] Add target-specific relocation scanning for RISC-V (PR #181332)
Jessica Clarke via llvm-commits
llvm-commits at lists.llvm.org
Sun Feb 15 18:37:31 PST 2026
================
@@ -361,24 +325,148 @@ void RISCV::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
RelType type = it->getType(false);
uint32_t symIndex = it->getSymbol(false);
Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIndex);
- const uint8_t *loc = sec.content().data() + it->r_offset;
+ uint64_t offset = it->r_offset;
if (type == R_RISCV_VENDOR) {
if (!rvVendor.empty())
- Err(ctx) << getErrorLoc(ctx, loc)
+ Err(ctx) << getErrorLoc(ctx, sec.content().data() + offset)
<< "malformed consecutive R_RISCV_VENDOR relocations";
rvVendor = sym.getName();
continue;
} else if (!rvVendor.empty()) {
- Err(ctx) << getErrorLoc(ctx, loc)
+ Err(ctx) << getErrorLoc(ctx, sec.content().data() + offset)
<< "unknown vendor-specific relocation (" << type.v
<< ") in namespace '" << rvVendor << "' against symbol '" << &sym
<< "'";
rvVendor = "";
continue;
}
- rs.scan<ELFT, RelTy>(it, type, rs.getAddend<ELFT>(*it, type));
+ if (sym.isUndefined() && symIndex != 0 &&
+ rs.maybeReportUndefined(cast<Undefined>(sym), offset))
+ continue;
+ int64_t addend = rs.getAddend<ELFT>(*it, type);
+ RelExpr expr;
+ // Relocation types that only need a RelExpr set `expr` and break out of
+ // the switch to reach rs.process(). Types that need special handling
+ // (fast-path helpers, TLS) call a handler and use `continue`.
+ switch (type) {
+ case R_RISCV_NONE:
+ continue;
+
+ // Absolute relocations:
+ case R_RISCV_32:
+ case R_RISCV_64:
+ case R_RISCV_HI20:
+ case R_RISCV_LO12_I:
+ case R_RISCV_LO12_S:
+ expr = R_ABS;
+ break;
+
+ // ADD/SET/SUB:
+ case R_RISCV_ADD8:
+ case R_RISCV_ADD16:
+ case R_RISCV_ADD32:
+ case R_RISCV_ADD64:
+ case R_RISCV_SET6:
+ case R_RISCV_SET8:
+ case R_RISCV_SET16:
+ case R_RISCV_SET32:
+ case R_RISCV_SUB6:
+ case R_RISCV_SUB8:
+ case R_RISCV_SUB16:
+ case R_RISCV_SUB32:
+ case R_RISCV_SUB64:
+ expr = RE_RISCV_ADD;
+ break;
+
+ // PC-relative relocations:
+ case R_RISCV_JAL:
+ case R_RISCV_BRANCH:
+ case R_RISCV_PCREL_HI20:
+ case R_RISCV_RVC_BRANCH:
+ case R_RISCV_RVC_JUMP:
+ case R_RISCV_32_PCREL:
+ rs.processR_PC(type, offset, addend, sym);
+ continue;
+ case R_RISCV_PCREL_LO12_I:
+ case R_RISCV_PCREL_LO12_S:
+ expr = RE_RISCV_PC_INDIRECT;
+ break;
+
+ // GOT-generating relocations:
+ case R_RISCV_GOT_HI20:
+ case R_RISCV_GOT32_PCREL:
+ expr = R_GOT_PC;
+ break;
+
+ // PLT-generating relocations:
+ case R_RISCV_CALL:
+ case R_RISCV_CALL_PLT:
+ case R_RISCV_PLT32:
+ rs.processR_PLT_PC(type, offset, addend, sym);
+ continue;
+
+ // TLS relocations:
+ case R_RISCV_TPREL_HI20:
+ case R_RISCV_TPREL_LO12_I:
+ case R_RISCV_TPREL_LO12_S:
+ if (rs.checkTlsLe(offset, sym, type))
+ continue;
+ expr = R_TPREL;
+ break;
+ case R_RISCV_TLS_GOT_HI20:
+ // There is no IE to LE optimization.
+ ctx.hasTlsIe.store(true, std::memory_order_relaxed);
+ sym.setFlags(NEEDS_TLSIE);
+ sec.addReloc({R_GOT_PC, type, offset, addend, &sym});
+ continue;
+ case R_RISCV_TLS_GD_HI20:
+ // There is no GD to IE/LE optimization.
+ sym.setFlags(NEEDS_TLSGD);
+ sec.addReloc({R_TLSGD_PC, type, offset, addend, &sym});
+ continue;
+
+ // TLSDESC relocations:
+ case R_RISCV_TLSDESC_HI20:
+ rs.handleTlsDesc(R_TLSDESC_PC, R_GOT_PC, type, offset, addend, sym);
+ continue;
+ case R_RISCV_TLSDESC_LOAD_LO12:
+ case R_RISCV_TLSDESC_ADD_LO12:
+ // R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12,CALL} reference a label, not the
+ // TLS symbol, so we cannot use handleTlsDesc (which sets NEEDS_TLSDESC).
+ // For TLSDESC->IE, use R_TPREL as well, but relocateAlloc uses isToLe
+ // (from HI20) to select the correct transform.
+ sec.addReloc({ctx.arg.shared ? R_TLSDESC_PC : R_TPREL, type, offset,
----------------
jrtc27 wrote:
I haven't been following the recent changes there, but why is it more obfuscated now? It used to be much clearer with explicit relaxation markers, now it all seems to be rather implicit where you get the "wrong" RelExpr for the relocation and have to infer that means you're relaxing?
https://github.com/llvm/llvm-project/pull/181332
More information about the llvm-commits
mailing list