On Wed, Sep 25, 2024 at 05:01:04PM +0200, Ard Biesheuvel wrote: > + if (r_type == R_X86_64_GOTPCREL) { > + Elf_Shdr *s = &secs[sec->shdr.sh_info].shdr; > + unsigned file_off = offset - s->sh_addr + s->sh_offset; > + > + /* > + * GOTPCREL relocations refer to instructions that load > + * a 64-bit address via a 32-bit relative reference to > + * the GOT. In this case, it is the GOT entry that > + * needs to be fixed up, not the immediate offset in > + * the opcode. Note that the linker will have applied an > + * addend of -4 to compensate for the delta between the > + * relocation offset and the value of RIP when the > + * instruction executes, and this needs to be backed out > + * again. (Addends other than -4 are permitted in > + * principle, but make no sense in practice so they are > + * not supported.) > + */ > + if (rel->r_addend != -4) { > + die("invalid addend (%ld) for %s relocation: %s\n", > + rel->r_addend, rel_type(r_type), symname); > + break; > + } For x86 PC-relative addressing, the addend is <reloc offset> - <subsequent insn offset>. So a PC-relative addend can be something other than -4 when the relocation applies to the middle of an instruction, e.g.: 5b381: 66 81 3d 00 00 00 00 01 06 cmpw $0x601,0x0(%rip) # 5b38a <generic_validate_add_page+0x4a> 5b384: R_X86_64_PC32 boot_cpu_data-0x6 5f283: 81 3d 00 00 00 00 ff ff ff 00 cmpl $0xffffff,0x0(%rip) # 5f28d <x86_acpi_suspend_lowlevel+0x9d> 5f285: R_X86_64_PC32 smpboot_control-0x8 72f67: c6 05 00 00 00 00 01 movb $0x1,0x0(%rip) # 72f6e <sched_itmt_update_handler+0x6e> 72f69: R_X86_64_PC32 x86_topology_update-0x5 Presumably that could also happen with R_X86_64_GOTPCREL? -- Josh