aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/elf64-x86-64.c42
-rw-r--r--bfd/elfxx-x86.c86
-rw-r--r--bfd/elfxx-x86.h6
-rw-r--r--ld/testsuite/ld-x86-64/sframe-pltgot-1.d28
-rw-r--r--ld/testsuite/ld-x86-64/sframe-pltgot-1.s15
-rw-r--r--ld/testsuite/ld-x86-64/sframe-pltgot-2.d28
-rw-r--r--ld/testsuite/ld-x86-64/x86-64.exp2
7 files changed, 198 insertions, 9 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index abbebbe..a62fa62 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -922,7 +922,7 @@ static const sframe_frame_row_entry elf_x86_64_sframe_sec_pltn_fre1 =
SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */
};
-/* SFrame helper object for non-lazy PLT. Also used for IBT enabled PLT. */
+/* SFrame helper object for non-lazy PLT. */
static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_plt =
{
LAZY_PLT_ENTRY_SIZE,
@@ -935,7 +935,31 @@ static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_plt =
{ &elf_x86_64_sframe_sec_pltn_fre1, &elf_x86_64_sframe_null_fre },
0,
0, /* There is no second PLT necessary. */
- { &elf_x86_64_sframe_null_fre }
+ { &elf_x86_64_sframe_null_fre },
+ NON_LAZY_PLT_ENTRY_SIZE,
+ 1, /* Number of FREs for PLT GOT. */
+ /* Array of SFrame FREs for PLT GOT. */
+ { &elf_x86_64_sframe_null_fre },
+};
+
+/* SFrame helper object for non-lazy IBT enabled PLT. */
+static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_ibt_plt =
+{
+ LAZY_PLT_ENTRY_SIZE,
+ 2, /* Number of FREs for PLT0. */
+ /* Array of SFrame FREs for plt0. */
+ { &elf_x86_64_sframe_plt0_fre1, &elf_x86_64_sframe_plt0_fre2 },
+ LAZY_PLT_ENTRY_SIZE,
+ 1, /* Number of FREs for PLTn. */
+ /* Array of SFrame FREs for plt. */
+ { &elf_x86_64_sframe_sec_pltn_fre1, &elf_x86_64_sframe_null_fre },
+ 0,
+ 0, /* There is no second PLT necessary. */
+ { &elf_x86_64_sframe_null_fre },
+ LAZY_PLT_ENTRY_SIZE,
+ 1, /* Number of FREs for PLT GOT. */
+ /* Array of SFrame FREs for PLT GOT. */
+ { &elf_x86_64_sframe_null_fre },
};
/* SFrame helper object for lazy PLT. */
@@ -952,7 +976,11 @@ static const struct elf_x86_sframe_plt elf_x86_64_sframe_plt =
NON_LAZY_PLT_ENTRY_SIZE,
1, /* Number of FREs for second PLT. */
/* Array of SFrame FREs for second PLT. */
- { &elf_x86_64_sframe_sec_pltn_fre1 }
+ { &elf_x86_64_sframe_sec_pltn_fre1 },
+ NON_LAZY_PLT_ENTRY_SIZE,
+ 1, /* Number of FREs for PLT GOT. */
+ /* Array of SFrame FREs for PLT GOT. */
+ { &elf_x86_64_sframe_null_fre },
};
/* SFrame helper object for lazy PLT with IBT. */
@@ -969,7 +997,11 @@ static const struct elf_x86_sframe_plt elf_x86_64_sframe_ibt_plt =
LAZY_PLT_ENTRY_SIZE,
1, /* Number of FREs for second PLT. */
/* Array of SFrame FREs for second plt. */
- { &elf_x86_64_sframe_sec_pltn_fre1 }
+ { &elf_x86_64_sframe_sec_pltn_fre1 },
+ LAZY_PLT_ENTRY_SIZE,
+ 1, /* Number of FREs for PLT GOT. */
+ /* Array of SFrame FREs for PLT GOT. */
+ { &elf_x86_64_sframe_null_fre },
};
/* These are the standard parameters. */
@@ -5703,7 +5735,7 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
init_table.sframe_lazy_plt = &elf_x86_64_sframe_plt;
init_table.sframe_non_lazy_plt = &elf_x86_64_sframe_non_lazy_plt;
init_table.sframe_lazy_ibt_plt = &elf_x86_64_sframe_ibt_plt;
- init_table.sframe_non_lazy_ibt_plt = &elf_x86_64_sframe_non_lazy_plt;
+ init_table.sframe_non_lazy_ibt_plt = &elf_x86_64_sframe_non_lazy_ibt_plt;
}
else
{
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index cb90f68..0843803 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -1817,7 +1817,8 @@ elf_x86_relative_reloc_compare (const void *pa, const void *pb)
enum dynobj_sframe_plt_type
{
SFRAME_PLT = 1,
- SFRAME_PLT_SEC = 2
+ SFRAME_PLT_SEC = 2,
+ SFRAME_PLT_GOT = 3,
};
/* Create SFrame stack trace info for the plt entries in the .plt section
@@ -1880,6 +1881,21 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd,
break;
}
+ case SFRAME_PLT_GOT:
+ {
+ ectx = &htab->plt_got_cfe_ctx;
+ dpltsec = htab->plt_got;
+
+ plt0_entry_size = 0;
+
+ plt_entry_size = htab->sframe_plt->plt_got_entry_size;
+ pltn_fres = htab->sframe_plt->plt_got_fres;
+ num_pltn_fres = htab->sframe_plt->plt_got_num_fres;
+ num_pltn_entries = dpltsec->size / plt_entry_size;
+
+ break;
+ }
+
default:
/* No other value is possible. */
return false;
@@ -1984,6 +2000,10 @@ _bfd_x86_elf_write_sframe_plt (bfd *output_bfd,
ectx = htab->plt_second_cfe_ctx;
sec = htab->plt_second_sframe;
break;
+ case SFRAME_PLT_GOT:
+ ectx = htab->plt_got_cfe_ctx;
+ sec = htab->plt_got_sframe;
+ break;
default:
/* No other value is possible. */
return false;
@@ -2511,7 +2531,18 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
htab->plt_sframe->size = sizeof (sframe_header) + 1;
}
- /* FIXME - generate for .plt.got ? */
+ if (htab->plt_got_sframe != NULL
+ && htab->plt_got != NULL
+ && htab->plt_got->size != 0
+ && !bfd_is_abs_section (htab->plt_got->output_section))
+ {
+ _bfd_x86_elf_create_sframe_plt (output_bfd, info, SFRAME_PLT_GOT);
+ /* FIXME - Dirty Hack. Set the size to something non-zero for now,
+ so that the section does not get stripped out below. The precise
+ size of this section is known only when the contents are
+ serialized in _bfd_x86_elf_write_sframe_plt. */
+ htab->plt_got_sframe->size = sizeof (sframe_header) + 1;
+ }
if (htab->plt_second_sframe != NULL
&& htab->plt_second != NULL
@@ -2578,6 +2609,7 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
|| s == htab->plt_second_eh_frame
|| s == htab->plt_sframe
|| s == htab->plt_second_sframe
+ || s == htab->plt_got_sframe
|| s == htab->elf.sdynbss
|| s == htab->elf.sdynrelro)
{
@@ -2622,7 +2654,8 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
/* Skip allocating contents for .sframe section as it is written
out differently. See below. */
- if ((s == htab->plt_sframe) || (s == htab->plt_second_sframe))
+ if ((s == htab->plt_sframe) || (s == htab->plt_second_sframe)
+ || (s == htab->plt_got_sframe))
continue;
/* NB: Initially, the iplt section has minimal alignment to
@@ -2687,6 +2720,12 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
&& htab->plt_second->size != 0
&& htab->plt_second_sframe->contents == NULL)
_bfd_x86_elf_write_sframe_plt (output_bfd, info, SFRAME_PLT_SEC);
+
+ if (htab->plt_got_sframe != NULL
+ && htab->plt_got != NULL
+ && htab->plt_got->size != 0
+ && htab->plt_got_sframe->contents == NULL)
+ _bfd_x86_elf_write_sframe_plt (output_bfd, info, SFRAME_PLT_GOT);
}
if (resolved_plt != NULL
@@ -2997,6 +3036,34 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
return NULL;
}
}
+
+ if (htab->plt_got_sframe != NULL
+ && htab->plt_got_sframe->contents != NULL)
+ {
+ if (htab->plt_got != NULL
+ && htab->plt_got->size != 0
+ && (htab->plt_got->flags & SEC_EXCLUDE) == 0
+ && htab->plt_got->output_section != NULL
+ && htab->plt_got_sframe->output_section != NULL)
+ {
+ bfd_vma plt_start = htab->plt_got->output_section->vma;
+ bfd_vma sframe_start
+ = (htab->plt_got_sframe->output_section->vma
+ + htab->plt_got_sframe->output_offset
+ + PLT_SFRAME_FDE_START_OFFSET);
+ bfd_put_signed_32 (dynobj, plt_start - sframe_start,
+ htab->plt_got_sframe->contents
+ + PLT_SFRAME_FDE_START_OFFSET);
+ }
+ if (htab->plt_got_sframe->sec_info_type == SEC_INFO_TYPE_SFRAME)
+ {
+ if (! _bfd_elf_merge_section_sframe (output_bfd, info,
+ htab->plt_got_sframe,
+ htab->plt_got_sframe->contents))
+ return NULL;
+ }
+ }
+
if (htab->elf.sgot && htab->elf.sgot->size > 0)
elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize
= htab->got_entry_size;
@@ -4764,7 +4831,18 @@ _bfd_x86_elf_link_setup_gnu_properties
htab->plt_second_sframe = sec;
}
- /* FIXME - add later for plt_got. */
+
+ /* .plt.got. */
+ if (htab->plt_got != NULL)
+ {
+ sec = bfd_make_section_anyway_with_flags (dynobj,
+ ".sframe",
+ flags);
+ if (sec == NULL)
+ info->callbacks->einfo (_("%F%P: failed to create PLT GOT .sframe section\n"));
+
+ htab->plt_got_sframe = sec;
+ }
}
}
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index b042d45..cd26e8f 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -401,6 +401,10 @@ struct elf_x86_sframe_plt
unsigned int sec_pltn_entry_size;
unsigned int sec_pltn_num_fres;
const sframe_frame_row_entry *sec_pltn_fres[SFRAME_PLTN_MAX_NUM_FRES];
+
+ unsigned int plt_got_entry_size;
+ unsigned int plt_got_num_fres;
+ const sframe_frame_row_entry *plt_got_fres[SFRAME_PLTN_MAX_NUM_FRES];
};
struct elf_x86_lazy_plt_layout
@@ -606,6 +610,8 @@ struct elf_x86_link_hash_table
asection *plt_sframe;
sframe_encoder_ctx *plt_second_cfe_ctx;
asection *plt_second_sframe;
+ sframe_encoder_ctx *plt_got_cfe_ctx;
+ asection *plt_got_sframe;
/* Parameters describing PLT generation, lazy or non-lazy. */
struct elf_x86_plt_layout plt;
diff --git a/ld/testsuite/ld-x86-64/sframe-pltgot-1.d b/ld/testsuite/ld-x86-64/sframe-pltgot-1.d
new file mode 100644
index 0000000..23ff5d5
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/sframe-pltgot-1.d
@@ -0,0 +1,28 @@
+#as: --gsframe
+#source: sframe-pltgot-1.s
+#objdump: --sframe=.sframe
+#ld: -shared -z ibtplt --no-rosegment
+#name: SFrame for IBT .plt.got
+
+.*: +file format .*
+
+Contents of the SFrame section .sframe:
+ Header :
+
+ Version: SFRAME_VERSION_2
+ Flags: SFRAME_F_FDE_SORTED
+ CFA fixed RA offset: \-8
+#...
+
+ Function Index :
+
+ func idx \[0\]: pc = 0x1000, size = 16 bytes
+ STARTPC +CFA +FP +RA +
+ 0+1000 +sp\+16 +u +f +
+ 0+1006 +sp\+24 +u +f +
+
+ func idx \[1\]: pc = 0x1010, size = 64 bytes
+ STARTPC\[m\] +CFA +FP +RA +
+ 0+0000 +sp\+16 +u +f +
+
+#...
diff --git a/ld/testsuite/ld-x86-64/sframe-pltgot-1.s b/ld/testsuite/ld-x86-64/sframe-pltgot-1.s
new file mode 100644
index 0000000..e596e84
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/sframe-pltgot-1.s
@@ -0,0 +1,15 @@
+ .text
+ .globl foo
+ .type foo, @function
+foo:
+ .cfi_startproc
+ call func1@plt
+ movq func1@GOTPCREL(%rip), %rax
+ call func2@plt
+ movq func2@GOTPCREL(%rip), %rax
+ call func3@plt
+ movq func3@GOTPCREL(%rip), %rax
+ call func4@plt
+ movq func4@GOTPCREL(%rip), %rax
+ .cfi_endproc
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/sframe-pltgot-2.d b/ld/testsuite/ld-x86-64/sframe-pltgot-2.d
new file mode 100644
index 0000000..7a99d12
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/sframe-pltgot-2.d
@@ -0,0 +1,28 @@
+#as: --gsframe
+#source: sframe-pltgot-1.s
+#objdump: --sframe=.sframe
+#ld: -shared --no-rosegment
+#name: SFrame for .plt.got
+
+.*: +file format .*
+
+Contents of the SFrame section .sframe:
+ Header :
+
+ Version: SFRAME_VERSION_2
+ Flags: SFRAME_F_FDE_SORTED
+ CFA fixed RA offset: \-8
+#...
+
+ Function Index :
+
+ func idx \[0\]: pc = 0x1000, size = 16 bytes
+ STARTPC +CFA +FP +RA +
+ 0+1000 +sp\+16 +u +f +
+ 0+1006 +sp\+24 +u +f +
+
+ func idx \[1\]: pc = 0x1010, size = 32 bytes
+ STARTPC\[m\] +CFA +FP +RA +
+ 0+0000 +sp\+16 +u +f +
+
+#...
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 0632397..a66d28e 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -548,6 +548,8 @@ if { ![skip_sframe_tests] } {
run_dump_test "sframe-simple-1"
run_dump_test "sframe-plt-1"
run_dump_test "sframe-ibt-plt-1"
+ run_dump_test "sframe-pltgot-1"
+ run_dump_test "sframe-pltgot-2"
}
if ![istarget "x86_64-*-linux*"] {