diff options
-rw-r--r-- | bfd/elf-bfd.h | 2 | ||||
-rw-r--r-- | bfd/elf-sframe.c | 31 | ||||
-rw-r--r-- | bfd/elflink.c | 24 |
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 { |