]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
ld: bfd: sframe: fix incorrect r_addend in RELA entries users/ibhagat/try-sframe-reloc-link-v1
authorIndu Bhagat <indu.bhagat@oracle.com>
Sun, 2 Mar 2025 15:45:08 +0000 (07:45 -0800)
committerIndu Bhagat <indu.bhagat@oracle.com>
Sat, 8 Mar 2025 04:46:43 +0000 (20:46 -0800)
With the fix in GAS, we now use a different PC-relative RELA for
updating the SFrame FDE function start address: The value is the offset
of the start PC of the function from the start of the SFrame section.

When RELAs are output (e.g. for relocatable links), there is need to
adjust the r_addend.  This is because the r_addend values still have the
correct values for the _input_ SFrame section being linked / relocated.
The values must now be (before outputing the RELAs) with respect to the
_output_ SFrame section.

PS: This patch should be merged with the previous commits before final
commit (Otherwise the tests will fail).  It is currently a separate
patch as I would like to check if this is OK to do.  If such a "addend
fixup" is risky or wrong, it seems we will need a new type of RELOC for
SFrame sections.

bfd/
        * elf-bfd.h: New declaration.
        * elf-sframe.c (_bfd_elf_sframe_section_addend): New
definition.
        * elflink.c (elf_link_input_bfd): Fixup the r_addend of
SFrame RELAs.

bfd/elf-bfd.h
bfd/elf-sframe.c
bfd/elflink.c

index f62570919d540e89eaf1ffb47dab6c8f7e471b91..fd301638baa03d81036b7974b434fa2036a10863 100644 (file)
@@ -2551,6 +2551,8 @@ extern bool _bfd_elf_merge_section_sframe
   (bfd *, struct bfd_link_info *, asection *, bfd_byte *);
 extern bfd_vma _bfd_elf_sframe_section_offset
   (bfd *, struct bfd_link_info *, asection *, bfd_vma);
+extern bfd_vma _bfd_elf_sframe_section_addend
+  (bfd *, struct bfd_link_info *, asection *, unsigned int, bfd_vma);
 extern bool _bfd_elf_write_section_sframe
   (bfd *, struct bfd_link_info *);
 extern bool _bfd_elf_set_section_sframe (bfd *, struct bfd_link_info *);
index 9c7bf09964962342d6e5acc1ab10ee712fd76e63..c893d406ce85ecab37b74b9dc75aeb2165e5cc72 100644 (file)
@@ -574,6 +574,37 @@ _bfd_elf_sframe_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED,
          + out_fde_idx * sizeof (sframe_func_desc_entry));
 }
 
+/* Get the "canonicalized" addend for the symbol reference corresponding to the
+   relocation at RELOC_INDEX.  E.g.,  for the following reloc for the SFrame
+   FDE function start address:
+       Offset          Type          Sym. Name + Addend
+       00000000001c  R_X86_64_PC32   .text + 1c
+       000000000030  R_X86_64_PC32   .text + 3b
+   The canonicalized addend are 0 and b respectively as the relocs are for
+   symbols (.text + 0) and (.text + b) respectively.
+
+   This is used to manually adjust the RELA addends to ensure correct values
+   for relocatable links.  */
+
+bfd_vma
+_bfd_elf_sframe_section_addend (bfd *output_bfd ATTRIBUTE_UNUSED,
+                             struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                             asection *sec,
+                             unsigned int reloc_index,
+                             bfd_vma addend)
+{
+  struct sframe_dec_info *sfd_info;
+
+  if (sec->sec_info_type != SEC_INFO_TYPE_SFRAME)
+    return addend;
+
+  sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info;
+  BFD_ASSERT (sfd_info && sfd_info->sfd_ctx);
+
+  return (addend - (sframe_decoder_get_hdr_size (sfd_info->sfd_ctx)
+                   + reloc_index * sizeof (sframe_func_desc_entry)));
+}
+
 /* Write out the .sframe section.  This must be called after
    _bfd_elf_merge_section_sframe has been called on all input
    .sframe sections.  */
index 895fbb0206e1f4b41a3fd1166d59f90fd2f1e977..6bce2966359a08e286c14e9f86863515deb3071d 100644 (file)
@@ -11939,7 +11939,9 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
              last_offset = o->output_offset;
              if (!bfd_link_relocatable (flinfo->info))
                last_offset += o->output_section->vma;
-             for (next_erel = 0; irela < irelaend; irela++, next_erel++)
+             unsigned int num_reloc = 0;
+             for (next_erel = 0; irela < irelaend;
+                  irela++, next_erel++, num_reloc++)
                {
                  unsigned long r_symndx;
                  asection *sec;
@@ -12070,10 +12072,24 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                            }
                        }
 
-                     /* Adjust the addend according to where the
-                        section winds up in the output section.  */
                      if (rela_normal)
-                       irela->r_addend += sec->output_offset;
+                       {
+                         if (o->sec_info_type == SEC_INFO_TYPE_SFRAME)
+                           {
+                             bfd_vma addend
+                              = _bfd_elf_sframe_section_addend (output_bfd,
+                                                              flinfo->info, o,
+                                                              num_reloc,
+                                                              irela->r_addend);
+                             /* Adjust the addend in the output RELA.  The
+                                input SFrame section has already been
+                                relocated.  */
+                             irela->r_addend = addend + irela->r_offset;
+                           }
+                         /* Adjust the addend according to where the
+                            section winds up in the output section.  */
+                         irela->r_addend += sec->output_offset;
+                       }
                    }
                  else
                    {