]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elf64-bpf.c
bpf: fix relocation addend incorrect symbol value
[thirdparty/binutils-gdb.git] / bfd / elf64-bpf.c
index 0bffe2c5717c00cef8875729bdc847393d510fc7..c922a3eb48e188e2032b14b80635333cde29d1a3 100644 (file)
@@ -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;
 }