aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-bpf.c
diff options
context:
space:
mode:
authorDavid Faust <david.faust@oracle.com>2024-01-10 15:05:36 -0800
committerDavid Faust <david.faust@oracle.com>2024-01-12 08:22:23 -0800
commitba7c1e37cfb498263a4e309700c27696fa5ff1ad (patch)
treecdd71668ca7941a1e1b173a867b09eab02cfd62d /bfd/elf64-bpf.c
parent98138c62cd7f721af132f9b24f274332fd8bf079 (diff)
downloadfsf-binutils-gdb-ba7c1e37cfb498263a4e309700c27696fa5ff1ad.zip
fsf-binutils-gdb-ba7c1e37cfb498263a4e309700c27696fa5ff1ad.tar.gz
fsf-binutils-gdb-ba7c1e37cfb498263a4e309700c27696fa5ff1ad.tar.bz2
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.
Diffstat (limited to 'bfd/elf64-bpf.c')
-rw-r--r--bfd/elf64-bpf.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/bfd/elf64-bpf.c b/bfd/elf64-bpf.c
index 0bffe2c..c922a3e 100644
--- a/bfd/elf64-bpf.c
+++ b/bfd/elf64-bpf.c
@@ -385,8 +385,7 @@ elf64_bpf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
static bfd_reloc_status_type
bpf_elf_generic_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
- void *data, asection *input_section,
- bfd *output_bfd ATTRIBUTE_UNUSED,
+ void *data, asection *input_section, bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
{
@@ -394,6 +393,22 @@ bpf_elf_generic_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
bfd_reloc_status_type status;
bfd_byte *where;
+ /* From bfd_elf_generic_reloc. */
+ if (output_bfd != NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && (! reloc_entry->howto->partial_inplace
+ || reloc_entry->addend == 0))
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ if (output_bfd == NULL
+ && !reloc_entry->howto->pc_relative
+ && (symbol->section->flags & SEC_DEBUGGING) != 0
+ && (input_section->flags & SEC_DEBUGGING) != 0)
+ reloc_entry->addend -= symbol->section->output_section->vma;
+
/* Sanity check that the address is in range. */
bfd_size_type end = bfd_get_section_limit_octets (abfd, input_section);
bfd_size_type reloc_size;
@@ -407,18 +422,15 @@ bpf_elf_generic_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
|| end - reloc_entry->address < reloc_size)
return bfd_reloc_outofrange;
- /* Get the symbol value. */
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
+ /* Behave similarly to bfd_install_relocation with install_addend set.
+ That is, just install the addend and do not include the value of
+ the symbol. */
+ relocation = reloc_entry->addend;
if (symbol->flags & BSF_SECTION_SYM)
/* Relocation against a section symbol: add in the section base address. */
relocation += BASEADDR (symbol->section);
- relocation += reloc_entry->addend;
-
where = (bfd_byte *) data + reloc_entry->address;
status = bfd_check_overflow (reloc_entry->howto->complain_on_overflow,
@@ -449,8 +461,8 @@ bpf_elf_generic_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
where + reloc_entry->howto->bitpos / 8);
}
- reloc_entry->addend = relocation;
- reloc_entry->address += input_section->output_offset;
+ if (output_bfd != NULL)
+ reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}