(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 *);
+ 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. */
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;
}
}
- /* 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
{