On 3/9/26 19:04, Max Chou wrote:
reloc_call splits a PC-relative offset into a signed 12-bit low immediate and an AUIPC contribution. When the low immediate carries into bit 31, the existing 32-bit arithmetic can accept an unencodable positive 0x80000000 AUIPC contribution.Keep the split in pointer-width arithmetic and reject it unless the rounded upper contribution is representable as signed 32-bit. Factor this validation into split_auipc_offset so reloc_call retains its existing failure contract. Fixes: dfa8e74f9463 ("tcg/riscv: Add the relocation functions") Signed-off-by: Max Chou <[email protected]> --- tcg/riscv64/tcg-target.c.inc | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tcg/riscv64/tcg-target.c.inc b/tcg/riscv64/tcg-target.c.inc index a439ba5c20e..1c41f8ffade 100644 --- a/tcg/riscv64/tcg-target.c.inc +++ b/tcg/riscv64/tcg-target.c.inc @@ -634,14 +634,31 @@ static bool reloc_jimm20(tcg_insn_unit *src_rw, const tcg_insn_unit *target) return false; }-static bool reloc_call(tcg_insn_unit *src_rw, const tcg_insn_unit *target)+static bool split_auipc_offset(tcg_insn_unit *src_rw, + const tcg_insn_unit *target, + intptr_t *hi, intptr_t *lo) { const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); intptr_t offset = (intptr_t)target - (intptr_t)src_rx; - int32_t lo = sextreg(offset, 0, 12); - int32_t hi = offset - lo; + intptr_t low = sextreg(offset, 0, 12); + intptr_t high = offset - low; + + /* AUIPC sign-extends its 20-bit immediate after shifting by 12. */ + if (high != sextreg(high, 0, 32)) { + return false; + } + + *hi = high; + *lo = low; + + return true; +} + +static bool reloc_call(tcg_insn_unit *src_rw, const tcg_insn_unit *target) +{ + intptr_t hi, lo;- if (offset == hi + lo) {+ if (split_auipc_offset(src_rw, target, &hi, &lo)) { src_rw[0] |= encode_uimm20(hi); src_rw[1] |= encode_imm12(lo);
I'm a bit confused by these encode_*imm() taking uint32_t arguments, otherwise your change LGTM: Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
