From: Simon Glass <simon.glass@canonical.com> GNU ld includes DT_PLTRELSZ in DT_RELASZ, so the EFI self-relocation code processes R_RISCV_JUMP_SLOT entries from .rela.plt alongside the expected R_RISCV_RELATIVE entries from .rela.dyn. JUMP_SLOT entries have a different format and cause incorrect fixups. Subtract DT_PLTRELSZ from the total relocation size so that only R_RISCV_RELATIVE entries are processed. Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- arch/riscv/lib/reloc_riscv_efi.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/riscv/lib/reloc_riscv_efi.c b/arch/riscv/lib/reloc_riscv_efi.c index c1039dd165d..da448bfdf96 100644 --- a/arch/riscv/lib/reloc_riscv_efi.c +++ b/arch/riscv/lib/reloc_riscv_efi.c @@ -52,7 +52,7 @@ efi_status_t EFIAPI _relocate(long ldbase, Elf_Dyn *dyn) { - long relsz = 0, relent = 0; + long relsz = 0, relent = 0, pltrelsz = 0; Elf_Rela *rel = 0; unsigned long *addr; int i; @@ -68,11 +68,21 @@ efi_status_t EFIAPI _relocate(long ldbase, Elf_Dyn *dyn) case DT_RELAENT: relent = dyn[i].d_un.d_val; break; + case DT_PLTRELSZ: + pltrelsz = dyn[i].d_un.d_val; + break; default: break; } } + /* + * GNU ld includes DT_PLTRELSZ in DT_RELASZ. Subtract it so + * we only process R_RISCV_RELATIVE entries from .rela.dyn and + * do not run into R_RISCV_JUMP_SLOT entries from .rela.plt. + */ + relsz -= pltrelsz; + if (!rel && relent == 0) return EFI_SUCCESS; -- 2.43.0