binutils-gdb/bfd/bpf-reloc.def
David Faust ba7c1e37cf bpf: fix relocation addend incorrect symbol value
Relocations installed by the BPF ELF backend were sometimes incorrectly
adding the symbol value to the relocation entry addend, when the correct
relocation value was already stored in the addend. This could lead to a
relocation effectively adding the symbol value twice.

Fix that by making bpf_elf_generic_reloc () more similar to the flow of
bfd_install_relocation in the case where howto->install_addend is set,
which is how it ought to behave.

bfd/
	* bpf-reloc.def (R_BPF_64_ABS32, R_BPF_64_ABS64)
	(R_BPF_64_NODYLD32): Set partial_inplace to true.
	* elf64-bpf.c (bpf_elf_generic_reloc): Do not include the value
	of the symbol when installing relocation. Copy some additional
	logic from bfd_elf_generic_reloc.

gas/
	* testsuite/gas/bpf/bpf.exp: Run new test.
	* testsuite/gas/bpf/elf-relo-1.d: New.
	* testsuite/gas/bpf/elf-relo-1.s: New.
2024-01-12 08:22:23 -08:00

110 lines
3.8 KiB
Modula-2

/* This reloc does nothing. */
BPF_HOWTO (R_BPF_NONE, /* type */
0, /* rightshift */
0, /* size */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bpf_elf_generic_reloc, /* special_function */
"R_BPF_NONE", /* name */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false) /* pcrel_offset */
/* 64-immediate in LDDW instruction. */
BPF_HOWTO (R_BPF_64_64, /* type */
0, /* rightshift */
8, /* size */
64, /* bitsize */
false, /* pc_relative */
32, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bpf_elf_generic_reloc, /* special_function */
"R_BPF_64_64", /* name */
true, /* partial_inplace */
MINUS_ONE, /* src_mask */
MINUS_ONE, /* dst_mask */
true) /* pcrel_offset */
/* 32-bit data. */
BPF_HOWTO (R_BPF_64_ABS32, /* type */
0, /* rightshift */
4, /* size */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bpf_elf_generic_reloc, /* special_function */
"R_BPF_64_ABS32", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
true) /* pcrel_offset */
/* 64-bit data. */
BPF_HOWTO (R_BPF_64_ABS64, /* type */
0, /* rightshift */
8, /* size */
64, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bpf_elf_generic_reloc, /* special_function */
"R_BPF_64_ABS64", /* name */
true, /* partial_inplace */
0, /* src_mask */
MINUS_ONE, /* dst_mask */
true) /* pcrel_offset */
/* 32-bit PC-relative address in call instructions. */
BPF_HOWTO (R_BPF_64_32, /* type */
0, /* rightshift */
4, /* size */
32, /* bitsize */
true, /* pc_relative */
32, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bpf_elf_generic_reloc, /* special_function */
"R_BPF_64_32", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
true) /* pcrel_offset */
/* 16-bit PC-relative address in load instructions. */
BPF_HOWTO (R_BPF_GNU_64_16, /* type */
0, /* rightshift */
2, /* size */
16, /* bitsize */
true, /* pc_relative */
16, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bpf_elf_generic_reloc, /* special_function */
"R_BPF_GNU_64_16", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
true) /* pcrel_offset */
/* R_BPF_64_NODYLD32 is not used by GNU tools - but it is generated by LLVM.
We provide an entry here so that tools like strip can safely handle BPF
binaries generated by other tools.
R_BPF_64_NODYLD32 should be fixed at linker like a R_BPF_64_ABS32.
The difference to ABS32 is that LLVM execution engine does not resolve
R_BPF_64_NODYLD32 relocations. */
BPF_HOWTO (R_BPF_64_NODYLD32, /* type */
0, /* rightshift */
4, /* size */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bpf_elf_generic_reloc, /* special_function */
"R_BPF_64_NODYLD32", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
true) /* pcrel_offset */