diff options
-rw-r--r-- | bfd/elf64-x86-64.c | 42 | ||||
-rw-r--r-- | bfd/elfxx-x86.c | 86 | ||||
-rw-r--r-- | bfd/elfxx-x86.h | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/sframe-pltgot-1.d | 28 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/sframe-pltgot-1.s | 15 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/sframe-pltgot-2.d | 28 | ||||
-rw-r--r-- | ld/testsuite/ld-x86-64/x86-64.exp | 2 |
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*"] { |