[PATCH 4/4] ld: bfd: sframe: fix incorrect r_addend in RELA entries
Indu Bhagat
indu.bhagat@oracle.com
Mon Mar 31 18:52:05 GMT 2025
PR/32666 Incorrect .rela.sframe when using ld -r
With the fix in GAS, we now use the available PC-relative RELAs for the
'SFrame FDE function start address' to be 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.
---
[Changes from RFC]
- Incorporate Jens' review comments
- Fix formatting issues in _bfd_elf_sframe_section_addend
[End of changes from RFC]
---
bfd/elf-bfd.h | 2 ++
bfd/elf-sframe.c | 35 +++++++++++++++++++++++++++++++++++
bfd/elflink.c | 21 ++++++++++++++++++---
3 files changed, 55 insertions(+), 3 deletions(-)
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index f62570919d5..fd301638baa 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -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 *);
diff --git a/bfd/elf-sframe.c b/bfd/elf-sframe.c
index 7ce54ba8f33..bd8f8428a8c 100644
--- a/bfd/elf-sframe.c
+++ b/bfd/elf-sframe.c
@@ -576,6 +576,41 @@ _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 annotated relocs for
+ the SFrame FDE function start address in FDE[0] and FDE[1] (for functions
+ foo and bar):
+ Offset Type Sym. Name + Addend
+ 00000000001c R_X86_64_PC32 .text + 1c // FDE[0] for foo at .text + 0
+ 000000000030 R_X86_64_PC32 .text + 3b // FDE[1] for bar at .text + b
+ With:
+ 1c = 0 + sizeof (sframe_header) + 0 * sizeof (sframe_fde)
+ 3b = b + sizeof (sframe_header) + 1 * sizeof (sframe_fde)
+ 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. */
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 895fbb0206e..de33edc16a0 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -12070,10 +12070,25 @@ 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)
+ {
+ unsigned int num_reloc = irela - internal_relocs;
+ 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
{
--
2.43.0
More information about the Binutils
mailing list