[RFC 4/4] ld: bfd: sframe: fix incorrect r_addend in RELA entries
Jens Remus
jremus@linux.ibm.com
Mon Mar 10 13:16:52 GMT 2025
On 08.03.2025 08:38, Indu Bhagat wrote:
> 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.
> diff --git 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
Nit: s/reloc/relocs/
> + 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.
Maybe it would help to use the function symbols foo and bar in the example:
relocation at RELOC_INDEX. E.g., for the following annotated relocs for the SFrame
FDE function start address of 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)));
IIUC this is only valid as long as reloc_index == fde_index.
> +}
> +
> /* 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..6bce2966359 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++)
The introduction of num_reloc could be omitted. See below.
> {
> 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)
> + {
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
> {
Regards,
Jens
--
Jens Remus
Linux on Z Development (D3303)
+49-7031-16-1128 Office
jremus@de.ibm.com
IBM
IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Böblingen; Registergericht: Amtsgericht Stuttgart, HRB 243294
IBM Data Privacy Statement: https://www.ibm.com/privacy/
More information about the Binutils
mailing list