aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIndu Bhagat <indu.bhagat@oracle.com>2025-03-02 07:45:08 -0800
committerIndu Bhagat <indu.bhagat@oracle.com>2025-03-07 20:46:43 -0800
commit7af1304c2d7de050f2462e9e3c3b766dde036348 (patch)
tree0c97a5d4f43cbe98832a42d2acd712df1b3b8ac8
parent141e6079582d2f8834674c76c5db7c762ab2ad1b (diff)
downloadgdb-users/ibhagat/try-sframe-reloc-link-v1.zip
gdb-users/ibhagat/try-sframe-reloc-link-v1.tar.gz
gdb-users/ibhagat/try-sframe-reloc-link-v1.tar.bz2
ld: bfd: sframe: fix incorrect r_addend in RELA entriesusers/ibhagat/try-sframe-reloc-link-v1
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.
-rw-r--r--bfd/elf-bfd.h2
-rw-r--r--bfd/elf-sframe.c31
-rw-r--r--bfd/elflink.c24
3 files changed, 53 insertions, 4 deletions
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index f625709..fd30163 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 9c7bf09..c893d40 100644
--- a/bfd/elf-sframe.c
+++ b/bfd/elf-sframe.c
@@ -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. */
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 895fbb0..6bce296 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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
{