diff options
-rw-r--r-- | bfd/elf-bfd.h | 2 | ||||
-rw-r--r-- | bfd/elf-sframe.c | 50 | ||||
-rw-r--r-- | bfd/elf.c | 3 | ||||
-rw-r--r-- | bfd/elflink.c | 3 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/sframe-reloc-1.d | 34 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/x86-64.exp | 1 |
6 files changed, 92 insertions, 1 deletions
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index d2bf8e5..f5b253a 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -2535,6 +2535,8 @@ extern bool _bfd_elf_discard_section_sframe (asection *, bool (*) (bfd_vma, void *), struct elf_reloc_cookie *); 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 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 67ed874..9224579 100644 --- a/bfd/elf-sframe.c +++ b/bfd/elf-sframe.c @@ -515,6 +515,56 @@ _bfd_elf_merge_section_sframe (bfd *abfd, return true; } +/* Adjust an address in the .sframe section. Given OFFSET within + SEC, this returns the new offset in the merged .sframe section, + or -1 if the address refers to an FDE which has been removed. + + PS: This function assumes that _bfd_elf_merge_section_sframe has not been + called on the input section SEC yet. */ + +bfd_vma +_bfd_elf_sframe_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info, + asection *sec, + bfd_vma offset) +{ + struct sframe_dec_info *sfd_info; + struct sframe_enc_info *sfe_info; + sframe_decoder_ctx *sfd_ctx; + sframe_encoder_ctx *sfe_ctx; + struct elf_link_hash_table *htab; + + unsigned int sec_fde_idx, out_fde_idx = 0; + unsigned int i, sfe_num_fdes; + + if (sec->sec_info_type != SEC_INFO_TYPE_SFRAME) + return offset; + + sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info; + sfd_ctx = sfd_info->sfd_ctx; + + htab = elf_hash_table (info); + sfe_info = &(htab->sfe_info); + sfe_ctx = sfe_info->sfe_ctx; + + sfe_num_fdes = sframe_encoder_get_num_fidx (sfe_ctx); + /* Identify the index of the FDE (at OFFSET) in the input section. */ + sec_fde_idx = ((offset - sframe_decoder_get_hdr_size (sfd_ctx)) + / sizeof (sframe_func_desc_entry)); + /* The index of this FDE in the output section depends on number of deleted + functions, if any. */ + for (i = 0; i < sec_fde_idx; i++) + { + if (!sframe_decoder_func_deleted_p (sfd_info, i)) + out_fde_idx++; + } + /* The actual index of the FDE in the output SFrame section. */ + out_fde_idx += sfe_num_fdes; + + return (sframe_decoder_get_hdr_size (sfd_ctx) + + out_fde_idx * 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. */ @@ -13491,6 +13491,9 @@ _bfd_elf_section_offset (bfd *abfd, case SEC_INFO_TYPE_EH_FRAME: return _bfd_elf_eh_frame_section_offset (abfd, info, sec, offset); + case SEC_INFO_TYPE_SFRAME: + return _bfd_elf_sframe_section_offset (abfd, info, sec, offset); + default: if ((sec->flags & SEC_ELF_REVERSE_COPY) != 0) { diff --git a/bfd/elflink.c b/bfd/elflink.c index 0df1976..8e6711f 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -11974,7 +11974,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) continue; } - irela->r_offset += o->output_offset; + if (o->sec_info_type != SEC_INFO_TYPE_SFRAME) + irela->r_offset += o->output_offset; /* Relocs in an executable have to be virtual addresses. */ if (!bfd_link_relocatable (flinfo->info)) diff --git a/ld/testsuite/ld-x86-64/sframe-reloc-1.d b/ld/testsuite/ld-x86-64/sframe-reloc-1.d new file mode 100644 index 0000000..308f94b --- /dev/null +++ b/ld/testsuite/ld-x86-64/sframe-reloc-1.d @@ -0,0 +1,34 @@ +#as: --gsframe +#source: sframe-foo.s +#source: sframe-bar.s +#objdump: --sframe=.sframe +#ld: -r --no-rosegment +#name: SFrame simple link - relocatable + +.*: +file format .* + +Contents of the SFrame section .sframe: + Header : + + Version: SFRAME_VERSION_2 + Flags: SFRAME_F_FDE_SORTED + CFA fixed RA offset: \-8 + Num FDEs: 2 + Num FREs: 8 + + Function Index : + + + func idx \[0\]: pc = 0x0, size = 53 bytes + STARTPC +CFA +FP +RA + + 0+0000 +sp\+8 +u +f + + 0+0001 +sp\+16 +c-16 +f + + 0+0004 +fp\+16 +c-16 +f + + 0+0034 +sp\+8 +c-16 +f + + + func idx \[1\]: pc = 0x35, size = 37 bytes + STARTPC +CFA +FP +RA + + 0+0035 +sp\+8 +u +f + + 0+0036 +sp\+16 +c-16 +f + + 0+0039 +fp\+16 +c-16 +f + + 0+0059 +sp\+8 +c-16 +f + diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 01d6459..eed06af 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -566,6 +566,7 @@ run_dump_test "pr32591-4-x32" if { ![skip_sframe_tests] } { run_dump_test "sframe-simple-1" + run_dump_test "sframe-reloc-1" run_dump_test "sframe-plt-1" run_dump_test "sframe-ibt-plt-1" run_dump_test "sframe-pltgot-1" |