aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/elf-bfd.h2
-rw-r--r--bfd/elf-sframe.c50
-rw-r--r--bfd/elf.c3
-rw-r--r--bfd/elflink.c3
-rw-r--r--ld/testsuite/ld-x86-64/sframe-reloc-1.d34
-rw-r--r--ld/testsuite/ld-x86-64/x86-64.exp1
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. */
diff --git a/bfd/elf.c b/bfd/elf.c
index 3f8bc83..3d65486 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -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"