[RFC 4/4] ld: bfd: sframe: fix incorrect r_addend in RELA entries

Indu Bhagat indu.bhagat@oracle.com
Mon Mar 24 18:11:20 GMT 2025


On 3/10/25 6:16 AM, Jens Remus wrote:
> 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/
> 

Done.

>> +   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.
> 

Amended.

>> +
>> +   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.
> 

Yes, and reloc_index should be the fde_index for input sections.  Do you 
see any issue ?  I can add a comment around the same.

>> +}
>> +
>>   /* 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.
> 

Done.

And thanks for reviewing.

>>           {
>>             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



More information about the Binutils mailing list