From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7850) id 3716F3948811; Tue, 15 Nov 2022 23:57:47 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3716F3948811 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1668556667; bh=7N3Qcb3A/R5qMApnVFEGuyOPHvJc87uE6GwYA4kyn14=; h=From:To:Subject:Date:From; b=M17HLxBB/OIiWNrFOuGL4nkuii7OGU2c41dUDwCy3vzVKgeN2AOOKUy4aYkQFqoQV abgHUScNAxGUuavm0iChPNjnsExBwK4WITu8MmYDWimTcfr/sUtU6mwv5SdBwrr0sw lvVUb1w/CWw09G2BdCJZ0a0/ml2Z2XjhahHhDoTc= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Indu Bhagat To: bfd-cvs@sourceware.org, gdb-cvs@sourceware.org Subject: [binutils-gdb] bfd: linker: merge .sframe sections X-Act-Checkin: binutils-gdb X-Git-Author: Indu Bhagat X-Git-Refname: refs/heads/master X-Git-Oldrev: 19e559f1c91bfaedbd2f91d85ee161f3f03fda3c X-Git-Newrev: cf0e0a0ba91664b680dff1e310f24dbe6447bd4c Message-Id: <20221115235747.3716F3948811@sourceware.org> Date: Tue, 15 Nov 2022 23:57:47 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3Dcf0e0a0ba916= 64b680dff1e310f24dbe6447bd4c commit cf0e0a0ba91664b680dff1e310f24dbe6447bd4c Author: Indu Bhagat Date: Tue Nov 15 15:07:04 2022 -0800 bfd: linker: merge .sframe sections =20 The linker merges all the input .sframe sections. When merging, the linker verifies that all the input .sframe sections have the same abi/arch. =20 The linker uses libsframe library to perform key actions on the .sframe sections - decode, read, and create output data. This implies buildsystem changes to make and install libsframe before libbfd. =20 The linker places the output .sframe section in a new segment of its own: PT_GNU_SFRAME. A new segment is not added, however, if the generated .sframe section is empty. =20 When a section is discarded from the final link, the corresponding entries in the .sframe section for those functions are also deleted. =20 The linker sorts the SFrame FDEs on start address by default and sets the SFRAME_F_FDE_SORTED flag in the .sframe section. =20 This patch also adds support for generation of SFrame unwind information for the .plt* sections on x86_64. SFrame unwind info is generated for IBT enabled PLT, lazy/non-lazy PLT. =20 The existing linker option --no-ld-generated-unwind-info has been adapted to include the control of whether .sframe unwind information will be generated for the linker generated sections like PLT. =20 Changes to the linker script have been made as necessary. =20 ChangeLog: =20 * Makefile.def: Add install dependency on libsframe for libbfd. * Makefile.in: Regenerated. * bfd/Makefile.am: Add elf-sframe.c * bfd/Makefile.in: Regenerated. * bfd/bfd-in2.h (SEC_INFO_TYPE_SFRAME): Regenerated. * bfd/configure: Regenerate. * bfd/configure.ac: Add elf-sframe.lo. * bfd/elf-bfd.h (struct sframe_func_bfdinfo): New struct. (struct sframe_dec_info): Likewise. (struct sframe_enc_info): Likewise. (struct elf_link_hash_table): New member for encoded .sframe object. (struct output_elf_obj_tdata): New member. (elf_sframe): New access macro. (_bfd_elf_set_section_sframe): New declaration. * bfd/elf.c (get_segment_type): Handle new segment PT_GNU_SFRAME. (bfd_section_from_phdr): Likewise. (get_program_header_size): Likewise. (_bfd_elf_map_sections_to_segments): Likewise. * bfd/elf64-x86-64.c (elf_x86_64_link_setup_gnu_properties): Add contents to the .sframe sections or .plt* entries. * bfd/elflink.c (elf_section_ignore_discarded_relocs): Handle SEC_INFO_TYPE_SFRAME. (_bfd_elf_default_action_discarded): Handle .sframe section. (elf_link_input_bfd): Merge .sframe section. (bfd_elf_final_link): Write the output .sframe section. (bfd_elf_discard_info): Handle discarding .sframe section. * bfd/elfxx-x86.c (_bfd_x86_elf_size_dynamic_sections): Create .sframe section for .plt and .plt.sec. (_bfd_x86_elf_finish_dynamic_sections): Handle .sframe from .plt* sections. * bfd/elfxx-x86.h (PLT_SFRAME_FDE_START_OFFSET): New definition. (SFRAME_PLT0_MAX_NUM_FRES): Likewise. (SFRAME_PLTN_MAX_NUM_FRES): Likewise. (struct elf_x86_sframe_plt): New structure. (struct elf_x86_link_hash_table): New member. (struct elf_x86_init_table): New members for .sframe creation. * bfd/section.c: Add new definition SEC_INFO_TYPE_SFRAME. * binutils/readelf.c (get_segment_type): Handle new segment PT_GNU_SFRAME. * ld/ld.texi: Update documentation for --no-ld-generated-unwind-info. * ld/scripttempl/elf.sc: Support .sframe sections. * ld/Makefile.am (TESTSFRAMELIB): Use it. (check-DEJAGNU): Likewise. * ld/Makefile.in: Regenerated. * ld/configure.ac (TESTSFRAMELIB): Set to the .so or .a like TE= STBFDLIB. * ld/configure: Regenerated. * bfd/elf-sframe.c: New file. =20 include/ChangeLog: =20 * elf/common.h (PT_GNU_SFRAME): New definition. * elf/internal.h (struct elf_segment_map): Handle new segment type PT_GNU_SFRAME. =20 ld/testsuite/ChangeLog: =20 * ld/testsuite/ld-bootstrap/bootstrap.exp: Add SFRAMELIB. * ld/testsuite/ld-aarch64/aarch64-elf.exp: Add new test sframe-simple-1. * ld/testsuite/ld-aarch64/sframe-bar.s: New file. * ld/testsuite/ld-aarch64/sframe-foo.s: Likewise. * ld/testsuite/ld-aarch64/sframe-simple-1.d: Likewise. * ld/testsuite/ld-sframe/sframe-empty.d: New test. * ld/testsuite/ld-sframe/sframe-empty.s: New file. * ld/testsuite/ld-sframe/sframe.exp: New testsuite. * ld/testsuite/ld-x86-64/sframe-bar.s: New file. * ld/testsuite/ld-x86-64/sframe-foo.s: Likewise. * ld/testsuite/ld-x86-64/sframe-simple-1.d: Likewise. * ld/testsuite/ld-x86-64/sframe-plt-1.d: Likewise. * ld/testsuite/ld-x86-64/sframe-simple-1.d: Likewise. * ld/testsuite/ld-x86-64/x86-64.exp: Add new tests - sframe-simple-1, sframe-plt-1. * ld/testsuite/lib/ld-lib.exp: Add new proc to check if assembler supports SFrame section. * ld/testsuite/ld-sframe/discard.d: New file. * ld/testsuite/ld-sframe/discard.ld: Likewise. * ld/testsuite/ld-sframe/discard.s: Likewise. Diff: --- Makefile.def | 4 + Makefile.in | 11 + bfd/Makefile.am | 6 +- bfd/Makefile.in | 7 +- bfd/bfd-in2.h | 1 + bfd/configure | 2 +- bfd/configure.ac | 2 +- bfd/elf-bfd.h | 54 +++ bfd/elf-sframe.c | 544 ++++++++++++++++++++++++++= ++++ bfd/elf.c | 32 ++ bfd/elf64-x86-64.c | 97 +++++- bfd/elflink.c | 52 +++ bfd/elfxx-x86.c | 375 +++++++++++++++++++- bfd/elfxx-x86.h | 49 +++ bfd/section.c | 1 + binutils/readelf.c | 1 + include/elf/common.h | 1 + include/elf/internal.h | 1 + include/sframe-api.h | 2 +- ld/Makefile.am | 2 + ld/Makefile.in | 2 + ld/configure | 8 +- ld/configure.ac | 3 + ld/ld.texi | 4 +- ld/scripttempl/elf.sc | 2 + ld/testsuite/ld-aarch64/aarch64-elf.exp | 4 + ld/testsuite/ld-aarch64/sframe-bar.s | 7 + ld/testsuite/ld-aarch64/sframe-foo.s | 10 + ld/testsuite/ld-aarch64/sframe-simple-1.d | 26 ++ ld/testsuite/ld-bootstrap/bootstrap.exp | 8 +- ld/testsuite/ld-sframe/discard.d | 10 + ld/testsuite/ld-sframe/discard.ld | 9 + ld/testsuite/ld-sframe/discard.s | 13 + ld/testsuite/ld-sframe/sframe-empty.d | 10 + ld/testsuite/ld-sframe/sframe-empty.s | 2 + ld/testsuite/ld-sframe/sframe.exp | 47 +++ ld/testsuite/ld-x86-64/sframe-bar.s | 31 ++ ld/testsuite/ld-x86-64/sframe-foo.s | 37 ++ ld/testsuite/ld-x86-64/sframe-plt-1.d | 29 ++ ld/testsuite/ld-x86-64/sframe-simple-1.d | 35 ++ ld/testsuite/ld-x86-64/x86-64.exp | 5 + ld/testsuite/lib/ld-lib.exp | 45 +++ libsframe/sframe.c | 28 +- 43 files changed, 1595 insertions(+), 24 deletions(-) diff --git a/Makefile.def b/Makefile.def index 1b39c910447..f974565d8ca 100644 --- a/Makefile.def +++ b/Makefile.def @@ -458,11 +458,14 @@ dependencies =3D { module=3Dall-gdbsupport; on=3Dall-= gnulib; }; dependencies =3D { module=3Dall-gdbsupport; on=3Dall-intl; }; =20 // Host modules specific to binutils. +// build libsframe before bfd for encoder/decoder support for linking +// SFrame sections dependencies =3D { module=3Dconfigure-bfd; on=3Dconfigure-libiberty; hard= =3Dtrue; }; dependencies =3D { module=3Dconfigure-bfd; on=3Dconfigure-intl; }; dependencies =3D { module=3Dall-bfd; on=3Dall-libiberty; }; dependencies =3D { module=3Dall-bfd; on=3Dall-intl; }; dependencies =3D { module=3Dall-bfd; on=3Dall-zlib; }; +dependencies =3D { module=3Dall-bfd; on=3Dall-libsframe; }; dependencies =3D { module=3Dconfigure-opcodes; on=3Dconfigure-libiberty; h= ard=3Dtrue; }; dependencies =3D { module=3Dall-opcodes; on=3Dall-libiberty; }; =20 @@ -488,6 +491,7 @@ dependencies =3D { module=3Dinstall-binutils; on=3Dinst= all-opcodes; }; dependencies =3D { module=3Dinstall-strip-binutils; on=3Dinstall-strip-opc= odes; }; =20 // Likewise for ld, libctf, and bfd. +dependencies =3D { module=3Dinstall-bfd; on=3Dinstall-libsframe; }; dependencies =3D { module=3Dinstall-libctf; on=3Dinstall-bfd; }; dependencies =3D { module=3Dinstall-ld; on=3Dinstall-bfd; }; dependencies =3D { module=3Dinstall-ld; on=3Dinstall-libctf; }; diff --git a/Makefile.in b/Makefile.in index b26f778a94a..a425b54e094 100644 --- a/Makefile.in +++ b/Makefile.in @@ -64407,6 +64407,16 @@ all-stagetrain-bfd: maybe-all-stagetrain-zlib all-stagefeedback-bfd: maybe-all-stagefeedback-zlib all-stageautoprofile-bfd: maybe-all-stageautoprofile-zlib all-stageautofeedback-bfd: maybe-all-stageautofeedback-zlib +all-bfd: maybe-all-libsframe +all-stage1-bfd: maybe-all-stage1-libsframe +all-stage2-bfd: maybe-all-stage2-libsframe +all-stage3-bfd: maybe-all-stage3-libsframe +all-stage4-bfd: maybe-all-stage4-libsframe +all-stageprofile-bfd: maybe-all-stageprofile-libsframe +all-stagetrain-bfd: maybe-all-stagetrain-libsframe +all-stagefeedback-bfd: maybe-all-stagefeedback-libsframe +all-stageautoprofile-bfd: maybe-all-stageautoprofile-libsframe +all-stageautofeedback-bfd: maybe-all-stageautofeedback-libsframe configure-opcodes: configure-libiberty configure-stage1-opcodes: configure-stage1-libiberty configure-stage2-opcodes: configure-stage2-libiberty @@ -64539,6 +64549,7 @@ all-stageautoprofile-binutils: maybe-all-stageautop= rofile-libsframe all-stageautofeedback-binutils: maybe-all-stageautofeedback-libsframe install-binutils: maybe-install-opcodes install-strip-binutils: maybe-install-strip-opcodes +install-bfd: maybe-install-libsframe install-libctf: maybe-install-bfd install-ld: maybe-install-bfd install-ld: maybe-install-libctf diff --git a/bfd/Makefile.am b/bfd/Makefile.am index 93313778d42..a88c6a0034d 100644 --- a/bfd/Makefile.am +++ b/bfd/Makefile.am @@ -286,6 +286,7 @@ BFD32_BACKENDS =3D \ ecofflink.lo \ elf-attrs.lo \ elf-eh-frame.lo \ + elf-sframe.lo \ elf-ifunc.lo \ elf-m10200.lo \ elf-m10300.lo \ @@ -419,6 +420,7 @@ BFD32_BACKENDS_CFILES =3D \ ecofflink.c \ elf-attrs.c \ elf-eh-frame.c \ + elf-sframe.c \ elf-ifunc.c \ elf-m10200.c \ elf-m10300.c \ @@ -777,8 +779,8 @@ ofiles: stamp-ofiles ; @true # dependency tracking fragments are picked up in the Makefile. libbfd_la_SOURCES =3D $(BFD32_LIBS_CFILES) EXTRA_libbfd_la_SOURCES =3D $(CFILES) -libbfd_la_DEPENDENCIES =3D $(OFILES) ofiles -libbfd_la_LIBADD =3D `cat ofiles` @SHARED_LIBADD@ $(LIBDL) $(ZLIB) $(ZSTD_= LIBS) +libbfd_la_DEPENDENCIES =3D $(OFILES) ofiles ../libsframe/libsframe.la +libbfd_la_LIBADD =3D `cat ofiles` @SHARED_LIBADD@ $(LIBDL) $(ZLIB) $(ZSTD_= LIBS) ../libsframe/libsframe.la libbfd_la_LDFLAGS +=3D -release `cat libtool-soversion` @SHARED_LDFLAGS@ =20 # libtool will build .libs/libbfd.a. We create libbfd.a in the build diff --git a/bfd/Makefile.in b/bfd/Makefile.in index 85cae1f6f0f..d5cc5cb1e17 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -755,6 +755,7 @@ BFD32_BACKENDS =3D \ ecofflink.lo \ elf-attrs.lo \ elf-eh-frame.lo \ + elf-sframe.lo \ elf-ifunc.lo \ elf-m10200.lo \ elf-m10300.lo \ @@ -888,6 +889,7 @@ BFD32_BACKENDS_CFILES =3D \ ecofflink.c \ elf-attrs.c \ elf-eh-frame.c \ + elf-sframe.c \ elf-ifunc.c \ elf-m10200.c \ elf-m10300.c \ @@ -1207,8 +1209,8 @@ OFILES =3D $(BFD_BACKENDS) $(BFD_MACHINES) @COREFILE@= @bfd64_libs@ # dependency tracking fragments are picked up in the Makefile. libbfd_la_SOURCES =3D $(BFD32_LIBS_CFILES) EXTRA_libbfd_la_SOURCES =3D $(CFILES) -libbfd_la_DEPENDENCIES =3D $(OFILES) ofiles -libbfd_la_LIBADD =3D `cat ofiles` @SHARED_LIBADD@ $(LIBDL) $(ZLIB) $(ZSTD_= LIBS) +libbfd_la_DEPENDENCIES =3D $(OFILES) ofiles ../libsframe/libsframe.la +libbfd_la_LIBADD =3D `cat ofiles` @SHARED_LIBADD@ $(LIBDL) $(ZLIB) $(ZSTD_= LIBS) ../libsframe/libsframe.la =20 # libtool will build .libs/libbfd.a. We create libbfd.a in the build # directory so that we don't have to convert all the programs that use @@ -1574,6 +1576,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-m10300.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-nacl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-properties.Plo@am__qu= ote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-sframe.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-strtab.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-vxworks.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf.Plo@am__quote@ diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index e09259b7eae..0b071dda1e5 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -994,6 +994,7 @@ typedef struct bfd_section #define SEC_INFO_TYPE_JUST_SYMS 4 #define SEC_INFO_TYPE_TARGET 5 #define SEC_INFO_TYPE_EH_FRAME_ENTRY 6 +#define SEC_INFO_TYPE_SFRAME 7 =20 /* Nonzero if this section uses RELA relocations, rather than REL. */ unsigned int use_rela_p:1; diff --git a/bfd/configure b/bfd/configure index 5c6e3821a13..74bc5a18471 100755 --- a/bfd/configure +++ b/bfd/configure @@ -13582,7 +13582,7 @@ selarchs=3D"$f" tb=3D =20 elf=3D"elf.lo elflink.lo elf-attrs.lo elf-strtab.lo elf-eh-frame.lo - dwarf1.lo dwarf2.lo" + elf-sframe.lo dwarf1.lo dwarf2.lo" coffgen=3D"coffgen.lo dwarf2.lo" coff=3D"cofflink.lo $coffgen" ecoff=3D"ecofflink.lo $coffgen" diff --git a/bfd/configure.ac b/bfd/configure.ac index 74c0f072225..5d450a4ad25 100644 --- a/bfd/configure.ac +++ b/bfd/configure.ac @@ -383,7 +383,7 @@ selarchs=3D"$f" tb=3D =20 elf=3D"elf.lo elflink.lo elf-attrs.lo elf-strtab.lo elf-eh-frame.lo - dwarf1.lo dwarf2.lo" + elf-sframe.lo dwarf1.lo dwarf2.lo" coffgen=3D"coffgen.lo dwarf2.lo" coff=3D"cofflink.lo $coffgen" ecoff=3D"ecofflink.lo $coffgen" diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index fa4b9bcf193..fc32fbe51e9 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -490,6 +490,40 @@ struct eh_frame_hdr_info u; }; =20 +/* Additional information for each function (used at link time). */ +struct sframe_func_bfdinfo +{ + /* Whether the function has been discarded from the final output. */ + bool func_deleted_p; + /* Relocation offset. */ + unsigned int func_r_offset; + /* Relocation index. */ + unsigned int func_reloc_index; +}; + +/* SFrame decoder info. + Contains all information for a decoded .sframe section. */ +struct sframe_dec_info +{ + /* Decoder context. */ + struct sframe_decoder_ctx *sfd_ctx; + /* Number of function descriptor entries in this .sframe. */ + unsigned int sfd_fde_count; + /* Additional information for linking. */ + struct sframe_func_bfdinfo *sfd_func_bfdinfo; +}; + +/* SFrame encoder info. + Contains all information for an encoded .sframe section to be + written out. */ +struct sframe_enc_info +{ + /* Encoder context. */ + struct sframe_encoder_ctx *sfe_ctx; + /* Output section. */ + asection *sframe_section; +}; + /* Enum used to identify target specific extensions to the elf_obj_tdata and elf_link_hash_table structures. Note the enums deliberately start from 1 so that we can detect an uninitialized field. The generic value @@ -668,6 +702,9 @@ struct elf_link_hash_table /* Used by eh_frame code when editing .eh_frame. */ struct eh_frame_hdr_info eh_info; =20 + /* Used to link unwind data in .sframe sections. */ + struct sframe_enc_info sfe_info; + /* A linked list of local symbols to be added to .dynsym. */ struct elf_link_local_dynamic_entry *dynlocal; =20 @@ -1944,6 +1981,10 @@ struct output_elf_obj_tdata /* Segment flags for the PT_GNU_STACK segment. */ unsigned int stack_flags; =20 + /* Used to determine if PT_GNU_SFRAME segment header should be + created. */ + asection *sframe; + /* Used to determine if the e_flags field has been initialized */ bool flags_init; }; @@ -2125,6 +2166,7 @@ struct elf_obj_tdata #define elf_link_info(bfd) (elf_tdata(bfd) -> o->link_info) #define elf_next_file_pos(bfd) (elf_tdata(bfd) -> o->next_file_pos) #define elf_stack_flags(bfd) (elf_tdata(bfd) -> o->stack_flags) +#define elf_sframe(bfd) (elf_tdata(bfd) -> o->sframe) #define elf_shstrtab(bfd) (elf_tdata(bfd) -> o->strtab_ptr) #define elf_onesymtab(bfd) (elf_tdata(bfd) -> symtab_section) #define elf_symtab_shndx_list(bfd) (elf_tdata(bfd) -> symtab_shndx_list) @@ -2439,6 +2481,18 @@ extern bool _bfd_elf_eh_frame_entry_present extern bool _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *); =20 +extern bool _bfd_elf_sframe_present + (struct bfd_link_info *); +extern bool _bfd_elf_parse_sframe + (bfd *, struct bfd_link_info *, asection *, struct elf_reloc_cookie *); +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 bool _bfd_elf_write_section_sframe + (bfd *, struct bfd_link_info *); +extern bool _bfd_elf_set_section_sframe (bfd *, struct bfd_link_info *); + extern bool _bfd_elf_hash_symbol (struct elf_link_hash_entry *); =20 extern long _bfd_elf_link_lookup_local_dynindx diff --git a/bfd/elf-sframe.c b/bfd/elf-sframe.c new file mode 100644 index 00000000000..8055aa3ea3b --- /dev/null +++ b/bfd/elf-sframe.c @@ -0,0 +1,544 @@ +/* .sframe section processing. + Copyright (C) 2022 Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" +#include "bfd.h" +#include "libbfd.h" +#include "elf-bfd.h" +#include "sframe-api.h" + +/* Return TRUE if the function has been marked for deletion during the lin= king + process. */ + +static bool +sframe_decoder_func_deleted_p (struct sframe_dec_info *sfd_info, + unsigned int func_idx) +{ + if (func_idx < sfd_info->sfd_fde_count) + return sfd_info->sfd_func_bfdinfo[func_idx].func_deleted_p; + + return false; +} + +/* Mark the function in the decoder info for deletion. */ + +static void +sframe_decoder_mark_func_deleted (struct sframe_dec_info *sfd_info, + unsigned int func_idx) +{ + if (func_idx < sfd_info->sfd_fde_count) + sfd_info->sfd_func_bfdinfo[func_idx].func_deleted_p =3D true; +} + +/* Get the relocation offset from the decoder info for the given function.= */ + +static unsigned int +sframe_decoder_get_func_r_offset (struct sframe_dec_info *sfd_info, + unsigned int func_idx) +{ + BFD_ASSERT (func_idx < sfd_info->sfd_fde_count); + unsigned int func_r_offset + =3D sfd_info->sfd_func_bfdinfo[func_idx].func_r_offset; + /* There must have been a reloc. */ + BFD_ASSERT (func_r_offset); + return func_r_offset; +} + +/* Bookkeep the function relocation offset in the decoder info. */ + +static void +sframe_decoder_set_func_r_offset (struct sframe_dec_info *sfd_info, + unsigned int func_idx, + unsigned int r_offset) +{ + if (func_idx < sfd_info->sfd_fde_count) + sfd_info->sfd_func_bfdinfo[func_idx].func_r_offset =3D r_offset; +} + +/* Get the relocation index in the elf_reloc_cookie for the function. */ + +static unsigned int +sframe_decoder_get_func_reloc_index (struct sframe_dec_info *sfd_info, + unsigned int func_idx) +{ + BFD_ASSERT (func_idx < sfd_info->sfd_fde_count); + return sfd_info->sfd_func_bfdinfo[func_idx].func_reloc_index; +} + +/* Bookkeep the relocation index in the elf_reloc_cookie for the function.= */ + +static void +sframe_decoder_set_func_reloc_index (struct sframe_dec_info *sfd_info, + unsigned int func_idx, + unsigned int reloc_index) +{ + if (func_idx < sfd_info->sfd_fde_count) + sfd_info->sfd_func_bfdinfo[func_idx].func_reloc_index =3D reloc_index; +} + +/* Initialize the set of additional information in CFD_INFO, + needed for linking SEC. Returns TRUE if setup is done successfully. */ + +static bool +sframe_decoder_init_func_bfdinfo (asection *sec, + struct sframe_dec_info *sfd_info, + struct elf_reloc_cookie *cookie) +{ + unsigned int fde_count; + unsigned int func_bfdinfo_size, i; + + fde_count =3D sframe_decoder_get_num_fidx (sfd_info->sfd_ctx); + sfd_info->sfd_fde_count =3D fde_count; + + /* Allocate and clear the memory. */ + func_bfdinfo_size =3D (sizeof (struct sframe_func_bfdinfo)) * fde_count; + sfd_info->sfd_func_bfdinfo + =3D (struct sframe_func_bfdinfo*) bfd_malloc (func_bfdinfo_size); + if (sfd_info->sfd_func_bfdinfo =3D=3D NULL) + return false; + memset (sfd_info->sfd_func_bfdinfo, 0, func_bfdinfo_size); + + /* For linker generated .sframe sections, we have no relocs. Skip. */ + if ((sec->flags & SEC_LINKER_CREATED) && cookie->rels =3D=3D NULL) + return true; + + for (i =3D 0; i < fde_count; i++) + { + cookie->rel =3D cookie->rels + i; + BFD_ASSERT (cookie->rel < cookie->relend); + /* Bookkeep the relocation offset and relocation index of each funct= ion + for later use. */ + sframe_decoder_set_func_r_offset (sfd_info, i, cookie->rel->r_offset= ); + sframe_decoder_set_func_reloc_index (sfd_info, i, + (cookie->rel - cookie->rels)); + + cookie->rel++; + } + BFD_ASSERT (cookie->rel =3D=3D cookie->relend); + + return true; +} + +/* Read the value from CONTENTS at the specified OFFSET for the given ABFD= . */ + +static bfd_vma +sframe_read_value (bfd *abfd, bfd_byte *contents, unsigned int offset, + unsigned int width) +{ + BFD_ASSERT (contents && offset); + /* Supporting the usecase of reading only the 4-byte relocated + value (signed offset for func start addr) for now. */ + BFD_ASSERT (width =3D=3D 4); + /* FIXME endianness ?? */ + unsigned char *buf =3D contents + offset; + bfd_vma value =3D bfd_get_signed_32 (abfd, buf); + return value; +} + +/* Return true if there is at least one non-empty .sframe section in + input files. Can only be called after ld has mapped input to + output sections, and before sections are stripped. */ + +bool +_bfd_elf_sframe_present (struct bfd_link_info *info) +{ + asection *sframe =3D bfd_get_section_by_name (info->output_bfd, ".sframe= "); + + if (sframe =3D=3D NULL) + return false; + + /* Count only sections which have at least a single FDE. */ + for (sframe =3D sframe->map_head.s; sframe !=3D NULL; sframe =3D sframe-= >map_head.s) + /* Note that this may become an approximate check in the future when + some ABI/arch begin to use the sfh_auxhdr_len. When sfh_auxhdr_len= has + non-zero value, it will need to be accounted for in the calculation= of + the SFrame header size. */ + if (sframe->size > sizeof (sframe_header)) + return true; + return false; +} + +/* Try to parse .sframe section SEC, which belongs to ABFD. Store the + information in the section's sec_info field on success. COOKIE + describes the relocations in SEC. + + Returns TRUE if success, FALSE if any error or failure. */ + +bool +_bfd_elf_parse_sframe (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + asection *sec, struct elf_reloc_cookie *cookie) +{ + bfd_byte *sfbuf =3D NULL; + struct sframe_dec_info *sfd_info; + sframe_decoder_ctx *sfd_ctx; + bfd_size_type sf_size; + int decerr =3D 0; + + if (sec->size =3D=3D 0 + || sec->sec_info_type !=3D SEC_INFO_TYPE_NONE) + { + /* This file does not contain .sframe information. */ + return false; + } + + if (bfd_is_abs_section (sec->output_section)) + { + /* At least one of the sections is being discarded from the + link, so we should just ignore them. */ + return false; + } + + /* Read the SFrame unwind information from abfd. */ + if (!bfd_malloc_and_get_section (abfd, sec, &sfbuf)) + goto fail_no_free; + + /* Decode the buffer and keep decoded contents for later use. + Relocations are performed later, but are such that the section's + size is unaffected. */ + sfd_info =3D bfd_malloc (sizeof (struct sframe_dec_info)); + sf_size =3D sec->size; + + sfd_info->sfd_ctx =3D sframe_decode ((const char*)sfbuf, sf_size, &decer= r); + sfd_ctx =3D sfd_info->sfd_ctx; + if (!sfd_ctx) + /* Free'ing up any memory held by decoder context is done by + sframe_decode in case of error. */ + goto fail_no_free; + + if (!sframe_decoder_init_func_bfdinfo (sec, sfd_info, cookie)) + { + sframe_decoder_free (&sfd_ctx); + goto fail_no_free; + } + + elf_section_data (sec)->sec_info =3D sfd_info; + sec->sec_info_type =3D SEC_INFO_TYPE_SFRAME; + + goto success; + +fail_no_free: + _bfd_error_handler + (_("error in %pB(%pA); no .sframe will be created"), + abfd, sec); + return false; +success: + free (sfbuf); + return true; +} + +/* This function is called for each input file before the .sframe section + is relocated. It marks the SFrame FDE for the discarded functions for + deletion. + + The function returns TRUE iff any entries have been deleted. */ + +bool +_bfd_elf_discard_section_sframe + (asection *sec, + bool (*reloc_symbol_deleted_p) (bfd_vma, void *), + struct elf_reloc_cookie *cookie) +{ + bool changed; + bool keep; + unsigned int i; + unsigned int func_desc_offset; + unsigned int num_fidx; + struct sframe_dec_info *sfd_info; + + changed =3D false; + /* FIXME - if relocatable link and changed =3D true, how does the final + .rela.sframe get updated ?. */ + keep =3D false; + + sfd_info =3D (struct sframe_dec_info *) elf_section_data (sec)->sec_info; + + /* Skip checking for the linker created .sframe sections + (for PLT sections). */ + if ((sec->flags & SEC_LINKER_CREATED) =3D=3D 0 || cookie->rels !=3D NULL) + { + num_fidx =3D sframe_decoder_get_num_fidx (sfd_info->sfd_ctx); + for (i =3D 0; i < num_fidx; i++) + { + func_desc_offset =3D sframe_decoder_get_func_r_offset (sfd_info, i); + + cookie->rel =3D cookie->rels + + sframe_decoder_get_func_reloc_index (sfd_info, i); + keep =3D !(*reloc_symbol_deleted_p) (func_desc_offset, cookie); + + if (!keep) + { + sframe_decoder_mark_func_deleted (sfd_info, i); + changed =3D true; + } + } + } + return changed; +} + +/* Update the reference to the output .sframe section in the output ELF + BFD ABFD. Returns true if no error. */ + +bool +_bfd_elf_set_section_sframe (bfd *abfd, + struct bfd_link_info *info) +{ + asection *cfsec; + + cfsec =3D bfd_get_section_by_name (info->output_bfd, ".sframe"); + if (!cfsec) + return false; + + elf_sframe (abfd) =3D cfsec; + + return true; +} + +/* Merge .sframe section SEC. This is called with the relocated + CONTENTS. */ + +bool +_bfd_elf_merge_section_sframe (bfd *abfd, + struct bfd_link_info *info, + asection *sec, + bfd_byte *contents) +{ + struct sframe_dec_info *sfd_info; + struct sframe_enc_info *sfe_info; + sframe_decoder_ctx *sfd_ctx; + sframe_encoder_ctx *sfe_ctx; + unsigned char sfd_ctx_abi_arch; + int8_t sfd_ctx_fixed_fp_offset; + int8_t sfd_ctx_fixed_ra_offset; + int encerr =3D 0; + + struct elf_link_hash_table *htab; + asection *cfsec; + + /* Sanity check - handle SFrame sections only. */ + if (sec->sec_info_type !=3D SEC_INFO_TYPE_SFRAME) + return false; + + sfd_info =3D (struct sframe_dec_info *) elf_section_data (sec)->sec_info; + sfd_ctx =3D sfd_info->sfd_ctx; + + htab =3D elf_hash_table (info); + sfe_info =3D &(htab->sfe_info); + sfe_ctx =3D sfe_info->sfe_ctx; + + /* All input bfds are expected to have a valid SFrame section. Even if + the SFrame section is empty with only a header, there must be a valid + SFrame decoder context by now. The SFrame encoder context, however, + will get set later here, if this is the first call to the function. = */ + if (sfd_ctx =3D=3D NULL || sfe_info =3D=3D NULL) + return false; + + if (htab->sfe_info.sfe_ctx =3D=3D NULL) + { + sfd_ctx_abi_arch =3D sframe_decoder_get_abi_arch (sfd_ctx); + sfd_ctx_fixed_fp_offset =3D sframe_decoder_get_fixed_fp_offset (sfd_= ctx); + sfd_ctx_fixed_ra_offset =3D sframe_decoder_get_fixed_ra_offset (sfd_= ctx); + + /* Valid values are non-zero. */ + if (!sfd_ctx_abi_arch) + return false; + + htab->sfe_info.sfe_ctx =3D sframe_encode (SFRAME_VERSION_1, + 0, /* SFrame flags. */ + sfd_ctx_abi_arch, + sfd_ctx_fixed_fp_offset, + sfd_ctx_fixed_ra_offset, + &encerr); + /* Handle errors from sframe_encode. */ + if (htab->sfe_info.sfe_ctx =3D=3D NULL) + return false; + } + sfe_ctx =3D sfe_info->sfe_ctx; + + if (sfe_info->sframe_section =3D=3D NULL) + { + /* Make sure things are set for an eventual write. + Size of the output section is not known until + _bfd_elf_write_section_sframe is ready with the buffer + to write out. */ + cfsec =3D bfd_get_section_by_name (info->output_bfd, ".sframe"); + if (cfsec) + { + sfe_info->sframe_section =3D cfsec; + // elf_sframe (abfd) =3D cfsec; + } + else + return false; + } + + /* Check that all .sframe sections being linked have the same + ABI/arch. */ + if (sframe_decoder_get_abi_arch (sfd_ctx) + !=3D sframe_encoder_get_abi_arch (sfe_ctx)) + { + _bfd_error_handler + (_("input SFrame sections with different abi prevent .sframe" + " generation")); + return false; + } + + /* Iterate over the function descriptor entries and the FREs of the + function from the decoder context. Add each of them to the encoder + context, if suitable. */ + unsigned int i =3D 0, j =3D 0, cur_fidx =3D 0; + + unsigned int num_fidx =3D sframe_decoder_get_num_fidx (sfd_ctx); + unsigned int num_enc_fidx =3D sframe_encoder_get_num_fidx (sfe_ctx); + + for (i =3D 0; i < num_fidx; i++) + { + unsigned int num_fres =3D 0; + int32_t func_start_address; + bfd_vma address; + uint32_t func_size =3D 0; + unsigned char func_info =3D 0; + unsigned int r_offset =3D 0; + bool pltn_reloc_by_hand =3D false; + unsigned int pltn_r_offset =3D 0; + + if (!sframe_decoder_get_funcdesc (sfd_ctx, i, &num_fres, &func_size, + &func_start_address, &func_info)) + { + /* If function belongs to a deleted section, skip editing the + function descriptor entry. */ + if (sframe_decoder_func_deleted_p(sfd_info, i)) + continue; + + /* Don't edit function descriptor entries for relocatable link. */ + if (!bfd_link_relocatable (info)) + { + if (!(sec->flags & SEC_LINKER_CREATED)) + { + /* Get relocated contents by reading the value of the + relocated function start address at the beginning of the + function descriptor entry. */ + r_offset =3D sframe_decoder_get_func_r_offset (sfd_info, i); + } + else + { + /* Expected to land here for SFrame unwind info as created + for the .plt* sections. These sections can have upto two + FDE entries. Although the code should work for > 2, + leaving this assert here for safety. */ + BFD_ASSERT (num_fidx <=3D 2); + /* For the first entry, we know the offset of the SFrame FDE's + sfde_func_start_address. Side note: see how the value + of PLT_SFRAME_FDE_START_OFFSET is also set to the + same. */ + r_offset =3D sframe_decoder_get_hdr_size (sfd_ctx); + /* For any further SFrame FDEs, the generator has already put + in an offset in place of sfde_func_start_address of the + corresponding FDE. We will use it by hand to relocate. */ + if (i > 0) + { + pltn_r_offset + =3D r_offset + (i * sizeof (sframe_func_desc_entry)); + pltn_reloc_by_hand =3D true; + } + } + + /* Get the SFrame FDE function start address after relocation. */ + address =3D sframe_read_value (abfd, contents, r_offset, 4); + if (pltn_reloc_by_hand) + address +=3D sframe_read_value (abfd, contents, + pltn_r_offset, 4); + address +=3D (sec->output_offset + r_offset); + + /* FIXME For testing only. Cleanup later. */ + // address +=3D (sec->output_section->vma); + + func_start_address =3D address; + } + + /* Update the encoder context with updated content. */ + int err =3D sframe_encoder_add_funcdesc (sfe_ctx, func_start_address, + func_size, func_info, + num_fres); + cur_fidx++; + BFD_ASSERT (!err); + } + + for (j =3D 0; j < num_fres; j++) + { + sframe_frame_row_entry fre; + if (!sframe_decoder_get_fre (sfd_ctx, i, j, &fre)) + { + int err =3D sframe_encoder_add_fre (sfe_ctx, + cur_fidx-1+num_enc_fidx, + &fre); + BFD_ASSERT (!err); + } + } + } + /* Free the SFrame decoder context. */ + sframe_decoder_free (&sfd_ctx); + + return true; +} + +/* Write out the .sframe section. This must be called after + _bfd_elf_merge_section_sframe has been called on all input + .sframe sections. */ + +bool +_bfd_elf_write_section_sframe (bfd *abfd, struct bfd_link_info *info) +{ + bool retval =3D true; + + struct elf_link_hash_table *htab; + struct sframe_enc_info *sfe_info; + sframe_encoder_ctx *sfe_ctx; + asection *sec; + void *contents; + size_t sec_size; + int err =3D 0; + + htab =3D elf_hash_table (info); + sfe_info =3D &htab->sfe_info; + sec =3D sfe_info->sframe_section; + sfe_ctx =3D sfe_info->sfe_ctx; + + if (sec =3D=3D NULL) + return true; + + contents =3D sframe_encoder_write (sfe_ctx, &sec_size, &err); + sec->size =3D (bfd_size_type) sec_size; + + if (!bfd_set_section_contents (abfd, sec->output_section, contents, + (file_ptr) sec->output_offset, + sec->size)) + retval =3D false; + else if (!bfd_link_relocatable (info)) + { + Elf_Internal_Shdr *hdr =3D &elf_section_data (sec)->this_hdr; + hdr->sh_size =3D sec->size; + } + /* For relocatable links, do not update the section size as the section + contents have not been relocated. */ + + sframe_encoder_free (&sfe_ctx); + + return retval; +} diff --git a/bfd/elf.c b/bfd/elf.c index 81825b748d7..87ec1623313 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -1673,6 +1673,7 @@ get_segment_type (unsigned int p_type) case PT_GNU_EH_FRAME: pt =3D "EH_FRAME"; break; case PT_GNU_STACK: pt =3D "STACK"; break; case PT_GNU_RELRO: pt =3D "RELRO"; break; + case PT_GNU_SFRAME: pt =3D "SFRAME"; break; default: pt =3D NULL; break; } return pt; @@ -3081,6 +3082,10 @@ bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr = *hdr, int hdr_index) case PT_GNU_RELRO: return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "relro= "); =20 + case PT_GNU_SFRAME: + return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, + "sframe"); + default: /* Check for any processor-specific program segment types. */ bed =3D get_elf_backend_data (abfd); @@ -4450,6 +4455,12 @@ get_program_header_size (bfd *abfd, struct bfd_link_= info *info) ++segs; } =20 + if (elf_sframe (abfd)) + { + /* We need a PT_GNU_SFRAME segment. */ + ++segs; + } + s =3D bfd_get_section_by_name (abfd, NOTE_GNU_PROPERTY_SECTION_NAME); if (s !=3D NULL && s->size !=3D 0) @@ -4715,6 +4726,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, asection *first_tls =3D NULL; asection *first_mbind =3D NULL; asection *dynsec, *eh_frame_hdr; + asection *sframe; size_t amt; bfd_vma addr_mask, wrap_to =3D 0; /* Bytes. */ bfd_size_type phdr_size; /* Octets/bytes. */ @@ -5210,6 +5222,26 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, pm =3D &m->next; } =20 + /* If there is a .sframe section, throw in a PT_GNU_SFRAME + segment. */ + sframe =3D elf_sframe (abfd); + if (sframe !=3D NULL + && (sframe->output_section->flags & SEC_LOAD) !=3D 0 + && sframe->size !=3D 0) + { + amt =3D sizeof (struct elf_segment_map); + m =3D (struct elf_segment_map *) bfd_zalloc (abfd, amt); + if (m =3D=3D NULL) + goto error_return; + m->next =3D NULL; + m->p_type =3D PT_GNU_SFRAME; + m->count =3D 1; + m->sections[0] =3D sframe->output_section; + + *pm =3D m; + pm =3D &m->next; + } + if (elf_stack_flags (abfd)) { amt =3D sizeof (struct elf_segment_map); diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 2ae8dffba0f..fb872793d5f 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -22,6 +22,7 @@ #include "elfxx-x86.h" #include "dwarf2.h" #include "libiberty.h" +#include "sframe.h" =20 #include "opcode/i386.h" =20 @@ -818,6 +819,87 @@ static const bfd_byte elf_x86_64_eh_frame_non_lazy_plt= [] =3D DW_CFA_nop, DW_CFA_nop, DW_CFA_nop }; =20 +static const sframe_frame_row_entry elf_x86_64_sframe_null_fre =3D +{ + 0, + SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B), /* FRE= info. */ + {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */ +}; + +/* .sframe FRE covering the .plt section entry. */ +static const sframe_frame_row_entry elf_x86_64_sframe_plt0_fre1 =3D +{ + 0, /* SFrame FRE start address. */ + SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B), /* FRE= info. */ + {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */ +}; + +/* .sframe FRE covering the .plt section entry. */ +static const sframe_frame_row_entry elf_x86_64_sframe_plt0_fre2 =3D +{ + 6, /* SFrame FRE start address. */ + SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B), /* FRE= info. */ + {24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */ +}; + +/* .sframe FRE covering the .plt section entry. */ +static const sframe_frame_row_entry elf_x86_64_sframe_pltn_fre1 =3D +{ + 0, /* SFrame FRE start address. */ + SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B), /* FRE= info. */ + {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */ +}; + +/* .sframe FRE covering the .plt section entry. */ +static const sframe_frame_row_entry elf_x86_64_sframe_pltn_fre2 =3D +{ + 11, /* SFrame FRE start address. */ + SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B), /* FRE= info. */ + {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */ +}; + +/* .sframe FRE covering the second .plt section entry. */ +static const sframe_frame_row_entry elf_x86_64_sframe_sec_pltn_fre1 =3D +{ + 0, /* SFrame FRE start address. */ + SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B), /* FRE= info. */ + {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */ +}; + +/* SFrame helper object for non-lazy PLT. Also used for IBT enabled PLT. = */ +static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_plt =3D +{ + 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 } +}; + +/* SFrame helper object for lazy PLT. Also used for IBT enabled PLT. */ +static const struct elf_x86_sframe_plt elf_x86_64_sframe_plt =3D +{ + 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, + 2, /* Number of FREs for PLTn. */ + /* Array of SFrame FREs for plt. */ + { &elf_x86_64_sframe_pltn_fre1, &elf_x86_64_sframe_pltn_fre2 }, + NON_LAZY_PLT_ENTRY_SIZE, + 1, /* Number of FREs for PLTn for second PLT. */ + /* FREs for second plt ( unwind info for .plt.got is + identical). Used when IBT or non-lazy PLT is in effect. */ + { &elf_x86_64_sframe_sec_pltn_fre1 } +}; + /* These are the standard parameters. */ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_plt =3D { @@ -971,7 +1053,6 @@ static const struct elf_x86_non_lazy_plt_layout elf_x3= 2_non_lazy_ibt_plt =3D sizeof (elf_x86_64_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ }; =20 - static bool elf64_x86_64_elf_object_p (bfd *abfd) { @@ -5228,6 +5309,20 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_lin= k_info *info) init_table.non_lazy_ibt_plt =3D &elf_x32_non_lazy_ibt_plt; } =20 + if (ABI_64_P (info->output_bfd)) + { + init_table.sframe_lazy_plt =3D &elf_x86_64_sframe_plt; + init_table.sframe_non_lazy_plt =3D &elf_x86_64_sframe_non_lazy_plt; + init_table.sframe_lazy_ibt_plt =3D &elf_x86_64_sframe_plt; + init_table.sframe_non_lazy_ibt_plt =3D &elf_x86_64_sframe_non_lazy_p= lt; + } + else + { + /* SFrame is not supported for non AMD64. */ + init_table.sframe_lazy_plt =3D NULL; + init_table.sframe_non_lazy_plt =3D NULL; + } + if (ABI_64_P (info->output_bfd)) { init_table.r_info =3D elf64_r_info; diff --git a/bfd/elflink.c b/bfd/elflink.c index 4ef07394160..20cee4c76a4 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -10900,6 +10900,7 @@ elf_section_ignore_discarded_relocs (asection *sec) case SEC_INFO_TYPE_STABS: case SEC_INFO_TYPE_EH_FRAME: case SEC_INFO_TYPE_EH_FRAME_ENTRY: + case SEC_INFO_TYPE_SFRAME: return true; default: break; @@ -10938,6 +10939,9 @@ _bfd_elf_default_action_discarded (asection *sec) && strncmp (sec->name, ".eh_frame.", 10) =3D=3D 0) return 0; =20 + if (strcmp (".sframe", sec->name) =3D=3D 0) + return 0; + if (strcmp (".gcc_except_table", sec->name) =3D=3D 0) return 0; =20 @@ -11871,6 +11875,16 @@ elf_link_input_bfd (struct elf_final_link_info *fl= info, bfd *input_bfd) return false; } break; + case SEC_INFO_TYPE_SFRAME: + { + /* Merge .sframe sections into the ctf frame encoder + context of the output_bfd's section. The final .sframe + output section will be written out later. */ + if (!_bfd_elf_merge_section_sframe (output_bfd, flinfo->info, + o, contents)) + return false; + } + break; default: { if (! (o->flags & SEC_EXCLUDE)) @@ -13454,6 +13468,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info= *info) if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info)) goto error_return; =20 + if (! _bfd_elf_write_section_sframe (abfd, info)) + goto error_return; + if (info->callbacks->emit_ctf) info->callbacks->emit_ctf (); =20 @@ -14909,6 +14926,41 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_= link_info *info) _bfd_elf_adjust_eh_frame_global_symbol, NULL); } =20 + o =3D bfd_get_section_by_name (output_bfd, ".sframe"); + if (o !=3D NULL) + { + asection *i; + + for (i =3D o->map_head.s; i !=3D NULL; i =3D i->map_head.s) + { + if (i->size =3D=3D 0) + continue; + + abfd =3D i->owner; + if (bfd_get_flavour (abfd) !=3D bfd_target_elf_flavour) + continue; + + if (!init_reloc_cookie_for_section (&cookie, info, i)) + return -1; + + if (_bfd_elf_parse_sframe (abfd, info, i, &cookie)) + { + if (_bfd_elf_discard_section_sframe (i, + bfd_elf_reloc_symbol_deleted_p, + &cookie)) + { + if (i->size !=3D i->rawsize) + changed =3D 1; + } + } + fini_reloc_cookie_for_section (&cookie, i); + } + /* Update the reference to the output .sframe section. Used to + determine later if PT_GNU_SFRAME segment is to be generated. */ + if (!_bfd_elf_set_section_sframe (output_bfd, info)) + return -1; + } + for (abfd =3D info->input_bfds; abfd !=3D NULL; abfd =3D abfd->link.next) { const struct elf_backend_data *bed; diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index 7fb972752b3..c48d0385485 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -1777,6 +1777,191 @@ elf_x86_relative_reloc_compare (const void *pa, con= st void *pb) return 0; } =20 +enum dynobj_sframe_plt_type +{ + SFRAME_PLT =3D 1, + SFRAME_PLT_SEC =3D 2 +}; + +/* Create SFrame unwind info for the plt entries in the .plt section + of type PLT_SEC_TYPE. */ + +static bool +_bfd_x86_elf_create_sframe_plt (bfd *output_bfd, + struct bfd_link_info *info, + unsigned int plt_sec_type) +{ + struct elf_x86_link_hash_table *htab; + const struct elf_backend_data *bed; + + bool plt0_generated_p; + unsigned int plt0_entry_size; + unsigned char func_info; + unsigned int fre_type; + /* The dynamic plt section for which .sframe unwind information is being + created. */ + asection *dpltsec; + + int err =3D 0; + + sframe_encoder_ctx **ectx =3D NULL; + unsigned plt_entry_size =3D 0; + unsigned int num_pltn_fres =3D 0; + unsigned int num_pltn_entries =3D 0; + + bed =3D get_elf_backend_data (output_bfd); + htab =3D elf_x86_hash_table (info, bed->target_id); + /* Whether SFrame unwind info for plt0 is to be generated. */ + plt0_generated_p =3D htab->plt.has_plt0; + plt0_entry_size + =3D (plt0_generated_p) ? htab->sframe_plt->plt0_entry_size : 0; + + switch (plt_sec_type) + { + case SFRAME_PLT: + { + ectx =3D &htab->plt_cfe_ctx; + dpltsec =3D htab->elf.splt; + + plt_entry_size =3D htab->plt.plt_entry_size; + num_pltn_fres =3D htab->sframe_plt->pltn_num_fres; + num_pltn_entries + =3D (htab->elf.splt->size - plt0_entry_size) / plt_entry_size; + + break; + } + case SFRAME_PLT_SEC: + { + ectx =3D &htab->plt_second_cfe_ctx; + /* FIXME - this or htab->plt_second_sframe ? */ + dpltsec =3D htab->plt_second_eh_frame; + + plt_entry_size =3D htab->sframe_plt->sec_pltn_entry_size; + num_pltn_fres =3D htab->sframe_plt->sec_pltn_num_fres; + num_pltn_entries + =3D htab->plt_second_eh_frame->size / plt_entry_size; + break; + } + default: + /* No other value is possible. */ + return false; + break; + } + + *ectx =3D sframe_encode (SFRAME_VERSION_1, + 0, + SFRAME_ABI_AMD64_ENDIAN_LITTLE, + SFRAME_CFA_FIXED_FP_INVALID, + -8, /* Fixed RA offset. */ + &err); + + /* FRE type is dependent on the size of the function. */ + fre_type =3D sframe_calc_fre_type (dpltsec->size); + func_info =3D sframe_fde_func_info (fre_type, + SFRAME_FDE_TYPE_PCINC); + + /* Add SFrame FDE and the associated FREs for plt0 if plt0 has been + generated. */ + if (plt0_generated_p) + { + /* Add SFrame FDE for plt0, the function start address is updated la= ter + at _bfd_elf_merge_section_sframe time. */ + sframe_encoder_add_funcdesc (*ectx, + 0, /* func start addr. */ + plt0_entry_size, + func_info, + 0 /* Num FREs. */); + sframe_frame_row_entry plt0_fre; + unsigned int num_plt0_fres =3D htab->sframe_plt->plt0_num_fres; + for (unsigned int j =3D 0; j < num_plt0_fres; j++) + { + plt0_fre =3D *(htab->sframe_plt->plt0_fres[j]); + sframe_encoder_add_fre (*ectx, 0, &plt0_fre); + } + } + + + if (num_pltn_entries) + { + /* pltn entries use an SFrame FDE of type + SFRAME_FDE_TYPE_PCMASK to exploit the repetitive + pattern of the instructions in these entries. Using this SFrame FDE + type helps in keeping the unwind information for pltn entries + compact. */ + func_info =3D sframe_fde_func_info (fre_type, SFRAME_FDE_TYPE_PCMASK= ); + /* Add the SFrame FDE for all PCs starting at the first pltn entry (= hence, + function start address =3D plt0_entry_size. As usual, this will be + updated later at _bfd_elf_merge_section_sframe, by when the + sections are relocated. */ + sframe_encoder_add_funcdesc (*ectx, + plt0_entry_size, /* func start addr. */ + dpltsec->size - plt0_entry_size, + func_info, + 0 /* Num FREs. */); + + sframe_frame_row_entry pltn_fre; + /* Now add the FREs for pltn. Simply adding the two FREs suffices d= ue + to the usage of SFRAME_FDE_TYPE_PCMASK above. */ + for (unsigned int j =3D 0; j < num_pltn_fres; j++) + { + pltn_fre =3D *(htab->sframe_plt->pltn_fres[j]); + sframe_encoder_add_fre (*ectx, 1, &pltn_fre); + } + } + + return true; +} + +/* Put contents of the .sframe section corresponding to the specified + PLT_SEC_TYPE. */ + +static bool +_bfd_x86_elf_write_sframe_plt (bfd *output_bfd, + struct bfd_link_info *info, + unsigned int plt_sec_type) +{ + struct elf_x86_link_hash_table *htab; + const struct elf_backend_data *bed; + sframe_encoder_ctx *ectx; + size_t sec_size; + asection *sec; + bfd *dynobj; + + int err =3D 0; + + bed =3D get_elf_backend_data (output_bfd); + htab =3D elf_x86_hash_table (info, bed->target_id); + dynobj =3D htab->elf.dynobj; + + switch (plt_sec_type) + { + case SFRAME_PLT: + ectx =3D htab->plt_cfe_ctx; + sec =3D htab->plt_sframe; + break; + case SFRAME_PLT_SEC: + ectx =3D htab->plt_second_cfe_ctx; + sec =3D htab->plt_second_sframe; + break; + default: + /* No other value is possible. */ + return false; + break; + } + + BFD_ASSERT (ectx); + + void *contents =3D sframe_encoder_write (ectx, &sec_size, &err); + + sec->size =3D (bfd_size_type) sec_size; + sec->contents =3D (unsigned char *) bfd_zalloc (dynobj, sec->size); + memcpy (sec->contents, contents, sec_size); + + sframe_encoder_free (&ectx); + + return true; +} + bool _bfd_elf_x86_size_relative_relocs (struct bfd_link_info *info, bool *need_layout) @@ -2267,6 +2452,42 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, =3D htab->non_lazy_plt->eh_frame_plt_size; } =20 + /* No need to size the .sframe section explicitly because the write-out + mechanism is different. Simply prep up the FDE/FRE for the + .plt section. */ + if (_bfd_elf_sframe_present (info)) + { + if (htab->plt_sframe !=3D NULL + && htab->elf.splt !=3D NULL + && htab->elf.splt->size !=3D 0 + && !bfd_is_abs_section (htab->elf.splt->output_section)) + { + _bfd_x86_elf_create_sframe_plt (output_bfd, info, SFRAME_PLT); + /* 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_sframe->size =3D sizeof (sframe_header) + 1; + } + + /* FIXME - generate for .got.plt ? */ + + /* Unwind info for the second PLT. */ + if (htab->plt_second_sframe !=3D NULL + && htab->plt_second !=3D NULL + && htab->plt_second->size !=3D 0 + && !bfd_is_abs_section (htab->plt_second->output_section)) + { + _bfd_x86_elf_create_sframe_plt (output_bfd, info, + SFRAME_PLT_SEC); + /* 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_second_sframe->size =3D sizeof (sframe_header) + 1; + } + } + /* We now have determined the sizes of the various dynamic sections. Allocate memory for them. */ relocs =3D false; @@ -2302,6 +2523,8 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, || s =3D=3D htab->plt_eh_frame || s =3D=3D htab->plt_got_eh_frame || s =3D=3D htab->plt_second_eh_frame + || s =3D=3D htab->plt_sframe + || s =3D=3D htab->plt_second_sframe || s =3D=3D htab->elf.sdynbss || s =3D=3D htab->elf.sdynrelro) { @@ -2344,6 +2567,11 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, if ((s->flags & SEC_HAS_CONTENTS) =3D=3D 0) continue; =20 + /* Skip allocating contents for .sframe section as it is written + out differently. See below. */ + if ((s =3D=3D htab->plt_sframe) || (s =3D=3D htab->plt_second_sframe= )) + continue; + /* NB: Initially, the iplt section has minimal alignment to avoid moving dot of the following section backwards when it is empty. Update its section alignment now since it @@ -2393,6 +2621,21 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, + PLT_FDE_LEN_OFFSET)); } =20 + if (_bfd_elf_sframe_present (info)) + { + if (htab->plt_sframe !=3D NULL + && htab->elf.splt !=3D NULL + && htab->elf.splt->size !=3D 0 + && htab->plt_sframe->contents =3D=3D NULL) + _bfd_x86_elf_write_sframe_plt (output_bfd, info, SFRAME_PLT); + + if (htab->plt_second_sframe !=3D NULL + && htab->elf.splt !=3D NULL + && htab->elf.splt->size !=3D 0 + && htab->plt_second_sframe->contents =3D=3D NULL) + _bfd_x86_elf_write_sframe_plt (output_bfd, info, SFRAME_PLT_SEC); + } + return _bfd_elf_maybe_vxworks_add_dynamic_tags (output_bfd, info, relocs); } @@ -2607,6 +2850,74 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bf= d, } } =20 + /* Make any adjustment if necessary and merge .sframe section to + create the final .sframe section for output_bfd. */ + if (htab->plt_sframe !=3D NULL + && htab->plt_sframe->contents !=3D NULL) + { + if (htab->elf.splt !=3D NULL + && htab->elf.splt->size !=3D 0 + && (htab->elf.splt->flags & SEC_EXCLUDE) =3D=3D 0 + && htab->elf.splt->output_section !=3D NULL + && htab->plt_sframe->output_section !=3D NULL) + { + bfd_vma plt_start =3D htab->elf.splt->output_section->vma; + bfd_vma sframe_start =3D htab->plt_sframe->output_section->vma + + htab->plt_sframe->output_offset + + PLT_SFRAME_FDE_START_OFFSET; +#if 0 /* FIXME Testing only. Remove before review. */ + bfd_vma test_value =3D (plt_start - sframe_start) + + htab->plt_sframe->output_section->vma + + htab->plt_sframe->output_offset + + PLT_SFRAME_FDE_START_OFFSET; + bfd_put_signed_32 (dynobj, test_value, +#endif + bfd_put_signed_32 (dynobj, plt_start - sframe_start, + htab->plt_sframe->contents + + PLT_SFRAME_FDE_START_OFFSET); + } + if (htab->plt_sframe->sec_info_type =3D=3D SEC_INFO_TYPE_SFRAME) + { + if (! _bfd_elf_merge_section_sframe (output_bfd, info, + htab->plt_sframe, + htab->plt_sframe->contents)) + return NULL; + } + } + + if (htab->plt_second_sframe !=3D NULL + && htab->plt_second_sframe->contents !=3D NULL) + { + if (htab->plt_second !=3D NULL + && htab->plt_second->size !=3D 0 + && (htab->plt_second->flags & SEC_EXCLUDE) =3D=3D 0 + && htab->plt_second->output_section !=3D NULL + && htab->plt_second_sframe->output_section !=3D NULL) + { + bfd_vma plt_start =3D htab->plt_second->output_section->vma; + bfd_vma sframe_start + =3D (htab->plt_second_sframe->output_section->vma + + htab->plt_second_sframe->output_offset + + PLT_SFRAME_FDE_START_OFFSET); +#if 0 /* FIXME Testing only. Remove before review. */ + bfd_vma test_value =3D (plt_start - sframe_start) + + htab->plt_second_sframe->output_section->vma + + htab->plt_second_sframe->output_offset + + PLT_SFRAME_FDE_START_OFFSET; + bfd_put_signed_32 (dynobj, test_value, +#endif + bfd_put_signed_32 (dynobj, plt_start - sframe_start, + htab->plt_second_sframe->contents + + PLT_SFRAME_FDE_START_OFFSET); + } + if (htab->plt_second_sframe->sec_info_type =3D=3D SEC_INFO_TYPE_SFRA= ME) + { + if (! _bfd_elf_merge_section_sframe (output_bfd, info, + htab->plt_second_sframe, + htab->plt_second_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 =3D htab->got_entry_size; @@ -3949,12 +4260,36 @@ _bfd_x86_elf_link_setup_gnu_properties =20 pltsec =3D htab->elf.splt; =20 - /* If the non-lazy PLT is available, use it for all PLT entries if - there are no PLT0 or no .plt section. */ if (htab->non_lazy_plt !=3D NULL && (!htab->plt.has_plt0 || pltsec =3D=3D NULL)) + lazy_plt =3D false; + else + lazy_plt =3D true; + + if (normal_target) + { + if (use_ibt_plt) + { + if (lazy_plt) + htab->sframe_plt =3D init_table->sframe_lazy_ibt_plt; + else + htab->sframe_plt =3D init_table->sframe_non_lazy_ibt_plt; + } + else + { + if (lazy_plt) + htab->sframe_plt =3D init_table->sframe_lazy_plt; + else + htab->sframe_plt =3D init_table->sframe_non_lazy_plt; + } + } + else + htab->sframe_plt =3D NULL; + + /* If the non-lazy PLT is available, use it for all PLT entries if + there are no PLT0 or no .plt section. */ + if (!lazy_plt) { - lazy_plt =3D false; if (bfd_link_pic (info)) htab->plt.plt_entry =3D htab->non_lazy_plt->pic_plt_entry; else @@ -3969,7 +4304,6 @@ _bfd_x86_elf_link_setup_gnu_properties } else { - lazy_plt =3D true; if (bfd_link_pic (info)) { htab->plt.plt0_entry =3D htab->lazy_plt->pic_plt0_entry; @@ -4145,6 +4479,39 @@ _bfd_x86_elf_link_setup_gnu_properties htab->plt_second_eh_frame =3D sec; } } + + /* .sframe sections are emitted for AMD64 ABI only. */ + if (ABI_64_P (info->output_bfd) && !info->no_ld_generated_unwind_inf= o) + { + flagword flags =3D (SEC_ALLOC | SEC_LOAD | SEC_READONLY + | SEC_HAS_CONTENTS | SEC_IN_MEMORY + | SEC_LINKER_CREATED); + + sec =3D bfd_make_section_anyway_with_flags (dynobj, + ".sframe", + flags); + if (sec =3D=3D NULL) + info->callbacks->einfo (_("%F%P: failed to create PLT .sframe section= \n")); + + // FIXME check this + // if (!bfd_set_section_alignment (sec, class_align)) + // goto error_alignment; + + htab->plt_sframe =3D sec; + + /* Second PLT is generated for Intel IBT / MPX Support + lazy plt. */ + if (htab->plt_second !=3D NULL) + { + sec =3D bfd_make_section_anyway_with_flags (dynobj, + ".sframe", + flags); + if (sec =3D=3D NULL) + info->callbacks->einfo (_("%F%P: failed to create second PLT .sframe sec= tion\n")); + + htab->plt_second_sframe =3D sec; + } + /* FIXME - add later for plt_got. */ + } } =20 /* The .iplt section is used for IFUNC symbols in static diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h index 7d23893938c..83f417acb0c 100644 --- a/bfd/elfxx-x86.h +++ b/bfd/elfxx-x86.h @@ -30,6 +30,7 @@ #include "elf-linker-x86.h" #include "elf/i386.h" #include "elf/x86-64.h" +#include "sframe-api.h" =20 #define X86_64_PCREL_TYPE_P(TYPE) \ ((TYPE) =3D=3D R_X86_64_PC8 \ @@ -105,6 +106,11 @@ || (TYPE) =3D=3D R_X86_64_PC32_BND \ || (TYPE) =3D=3D R_X86_64_PC64) =20 +/* This must be the same as sframe_get_hdr_size (sfh). For x86-64, this v= alue + is the same as sizeof (sframe_header) because there is no SFrame auxill= iary + header. */ +#define PLT_SFRAME_FDE_START_OFFSET sizeof (sframe_header) + #define ABI_64_P(abfd) \ (get_elf_backend_data (abfd)->s->elfclass =3D=3D ELFCLASS64) =20 @@ -388,6 +394,24 @@ struct elf_x86_link_hash_entry bfd_vma tlsdesc_got; }; =20 +#define SFRAME_PLT0_MAX_NUM_FRES 2 +#define SFRAME_PLTN_MAX_NUM_FRES 2 + +struct elf_x86_sframe_plt +{ + unsigned int plt0_entry_size; + unsigned int plt0_num_fres; + const sframe_frame_row_entry *plt0_fres[SFRAME_PLT0_MAX_NUM_FRES]; + + unsigned int pltn_entry_size; + unsigned int pltn_num_fres; + const sframe_frame_row_entry *pltn_fres[SFRAME_PLTN_MAX_NUM_FRES]; + + 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]; +}; + struct elf_x86_lazy_plt_layout { /* The first entry in a lazy procedure linkage table looks like this. */ @@ -584,6 +608,11 @@ struct elf_x86_link_hash_table asection *plt_got; asection *plt_got_eh_frame; =20 + sframe_encoder_ctx *plt_cfe_ctx; + asection *plt_sframe; + sframe_encoder_ctx *plt_second_cfe_ctx; + asection *plt_second_sframe; + /* Parameters describing PLT generation, lazy or non-lazy. */ struct elf_x86_plt_layout plt; =20 @@ -593,6 +622,10 @@ struct elf_x86_link_hash_table /* Parameters describing non-lazy PLT generation. */ const struct elf_x86_non_lazy_plt_layout *non_lazy_plt; =20 + /* The .sframe helper object for .plt section. + This is used for x86-64 only. */ + const struct elf_x86_sframe_plt *sframe_plt; + union { bfd_signed_vma refcount; @@ -682,6 +715,22 @@ struct elf_x86_init_table /* The non-lazy PLT layout for IBT. */ const struct elf_x86_non_lazy_plt_layout *non_lazy_ibt_plt; =20 + /* The .sframe helper object for lazy .plt section. + This is used for x86-64 only. */ + const struct elf_x86_sframe_plt *sframe_lazy_plt; + + /* The .sframe helper object for non-lazy .plt section. + This is used for x86-64 only. */ + const struct elf_x86_sframe_plt *sframe_non_lazy_plt; + + /* The .sframe helper object for lazy IBT .plt section. + This is used for x86-64 only. */ + const struct elf_x86_sframe_plt *sframe_lazy_ibt_plt; + + /* The .sframe helper object for non-lazy IBT .plt section. + This is used for x86-64 only. */ + const struct elf_x86_sframe_plt *sframe_non_lazy_ibt_plt; + bfd_byte plt0_pad_byte; =20 bfd_vma (*r_info) (bfd_vma, bfd_vma); diff --git a/bfd/section.c b/bfd/section.c index 48505f373e2..f73e0345e15 100644 --- a/bfd/section.c +++ b/bfd/section.c @@ -409,6 +409,7 @@ CODE_FRAGMENT .#define SEC_INFO_TYPE_JUST_SYMS 4 .#define SEC_INFO_TYPE_TARGET 5 .#define SEC_INFO_TYPE_EH_FRAME_ENTRY 6 +.#define SEC_INFO_TYPE_SFRAME 7 . . {* Nonzero if this section uses RELA relocations, rather than REL. *} . unsigned int use_rela_p:1; diff --git a/binutils/readelf.c b/binutils/readelf.c index c8323539a21..f82c3a973f2 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -4604,6 +4604,7 @@ get_segment_type (Filedata * filedata, unsigned long = p_type) case PT_GNU_STACK: return "GNU_STACK"; case PT_GNU_RELRO: return "GNU_RELRO"; case PT_GNU_PROPERTY: return "GNU_PROPERTY"; + case PT_GNU_SFRAME: return "GNU_SFRAME"; =20 case PT_OPENBSD_RANDOMIZE: return "OPENBSD_RANDOMIZE"; case PT_OPENBSD_WXNEEDED: return "OPENBSD_WXNEEDED"; diff --git a/include/elf/common.h b/include/elf/common.h index 287526d74ed..16587f6fb06 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -489,6 +489,7 @@ #define PT_GNU_STACK (PT_LOOS + 0x474e551) /* Stack flags */ #define PT_GNU_RELRO (PT_LOOS + 0x474e552) /* Read-only after relocation */ #define PT_GNU_PROPERTY (PT_LOOS + 0x474e553) /* GNU property */ +#define PT_GNU_SFRAME (PT_LOOS + 0x474e554) /* SFrame unwind information */ =20 /* OpenBSD segment types. */ #define PT_OPENBSD_RANDOMIZE (PT_LOOS + 0x5a3dbe6) /* Fill with random da= ta. */ diff --git a/include/elf/internal.h b/include/elf/internal.h index 8affb3d9b2e..de9f67809b3 100644 --- a/include/elf/internal.h +++ b/include/elf/internal.h @@ -339,6 +339,7 @@ struct elf_segment_map || (segment)->p_type =3D=3D PT_GNU_EH_FRAME \ || (segment)->p_type =3D=3D PT_GNU_STACK \ || (segment)->p_type =3D=3D PT_GNU_RELRO \ + || (segment)->p_type =3D=3D PT_GNU_SFRAME \ || ((segment)->p_type >=3D PT_GNU_MBIND_LO \ && (segment)->p_type <=3D PT_GNU_MBIND_HI))) \ /* Any section besides one of type SHT_NOBITS must have file \ diff --git a/include/sframe-api.h b/include/sframe-api.h index f0924dc91e3..010a35a1674 100644 --- a/include/sframe-api.h +++ b/include/sframe-api.h @@ -187,7 +187,7 @@ sframe_encode (unsigned char ver, unsigned char flags, = int abi, =20 /* Free the encoder context. */ extern void -sframe_free_encoder (sframe_encoder_ctx *encoder); +sframe_encoder_free (sframe_encoder_ctx **encoder); =20 /* Get the size of the SFrame header from the encoder ctx ENCODER. */ extern unsigned int diff --git a/ld/Makefile.am b/ld/Makefile.am index 66e9094e86a..65fef4e1690 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -972,6 +972,7 @@ EXTRA_ld_new_SOURCES +=3D $(ALL_EMULATION_SOURCES) $(AL= L_64_EMULATION_SOURCES) # This is the real libbfd.a and libctf.a created by libtool. TESTBFDLIB =3D @TESTBFDLIB@ TESTCTFLIB =3D @TESTCTFLIB@ +TESTSFRAMELIB =3D @TESTSFRAMELIB@ =20 check-DEJAGNU: site.exp (cd .libs; test -e ldscripts || test ! -e ld-new || $(LN_S) ../ldscripts = .) @@ -989,6 +990,7 @@ check-DEJAGNU: site.exp CXX_FOR_TARGET=3D"$(CXX_FOR_TARGET)" \ CXXFLAGS_FOR_TARGET=3D"$(CXXFLAGS_FOR_TARGET)" \ OFILES=3D"$(OFILES)" BFDLIB=3D"$(TESTBFDLIB)" CTFLIB=3D"$(TESTCTFLIB) $(= ZLIB)" \ + SFRAMELIB=3D"$(TESTSFRAMELIB)" \ LIBIBERTY=3D"$(LIBIBERTY) $(LIBINTL)" LIBS=3D"$(LIBS)" \ DO_COMPARE=3D"`echo '$(do_compare)' | sed -e 's,\\$$,,g'`" \ $(RUNTESTFLAGS); \ diff --git a/ld/Makefile.in b/ld/Makefile.in index 5e4787f89b4..ff4c916c27b 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -470,6 +470,7 @@ TARGET_SYSTEM_ROOT_DEFINE =3D @TARGET_SYSTEM_ROOT_DEFIN= E@ # This is the real libbfd.a and libctf.a created by libtool. TESTBFDLIB =3D @TESTBFDLIB@ TESTCTFLIB =3D @TESTCTFLIB@ +TESTSFRAMELIB =3D @TESTSFRAMELIB@ USE_NLS =3D @USE_NLS@ VERSION =3D @VERSION@ WARN_CFLAGS =3D @WARN_CFLAGS@ @@ -2642,6 +2643,7 @@ check-DEJAGNU: site.exp CXX_FOR_TARGET=3D"$(CXX_FOR_TARGET)" \ CXXFLAGS_FOR_TARGET=3D"$(CXXFLAGS_FOR_TARGET)" \ OFILES=3D"$(OFILES)" BFDLIB=3D"$(TESTBFDLIB)" CTFLIB=3D"$(TESTCTFLIB) $(= ZLIB)" \ + SFRAMELIB=3D"$(TESTSFRAMELIB)" \ LIBIBERTY=3D"$(LIBIBERTY) $(LIBINTL)" LIBS=3D"$(LIBS)" \ DO_COMPARE=3D"`echo '$(do_compare)' | sed -e 's,\\$$,,g'`" \ $(RUNTESTFLAGS); \ diff --git a/ld/configure b/ld/configure index 79000452c95..a4d30abfb1c 100755 --- a/ld/configure +++ b/ld/configure @@ -634,6 +634,7 @@ ac_subst_vars=3D'am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS +TESTSFRAMELIB TESTCTFLIB TESTBFDLIB EMULATION_LIBPATH @@ -11624,7 +11625,7 @@ else lt_dlunknown=3D0; lt_dlno_uscore=3D1; lt_dlneed_uscore=3D2 lt_status=3D$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11627 "configure" +#line 11628 "configure" #include "confdefs.h" =20 #if HAVE_DLFCN_H @@ -11730,7 +11731,7 @@ else lt_dlunknown=3D0; lt_dlno_uscore=3D1; lt_dlneed_uscore=3D2 lt_status=3D$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11733 "configure" +#line 11734 "configure" #include "confdefs.h" =20 #if HAVE_DLFCN_H @@ -17487,9 +17488,11 @@ EMULATION_LIBPATH=3D$all_libpath if test x${enable_static} =3D xno; then TESTBFDLIB=3D"-Wl,--rpath,../bfd/.libs ../bfd/.libs/libbfd.so" TESTCTFLIB=3D"-Wl,--rpath,../libctf/.libs ../libctf/.libs/libctf.so" + TESTSFRAMELIB=3D"-Wl,--rpath,../libsframe/.libs ../libsframe/.libs/libsf= rame.so" else TESTBFDLIB=3D"../bfd/.libs/libbfd.a" TESTCTFLIB=3D"../libctf/.libs/libctf.a" + TESTSFRAMELIB=3D"../libsframe/.libs/libsframe.a" fi if test "${enable_libctf}" =3D no; then TESTCTFLIB=3D @@ -17497,6 +17500,7 @@ fi =20 =20 =20 + target_vendor=3D${target_vendor=3D$host_vendor} case "$target_vendor" in hp) EXTRA_SHLIB_EXTENSION=3D".sl" ;; diff --git a/ld/configure.ac b/ld/configure.ac index 6123ea78611..1ee40a51b08 100644 --- a/ld/configure.ac +++ b/ld/configure.ac @@ -628,15 +628,18 @@ AC_SUBST(EMULATION_LIBPATH) if test x${enable_static} =3D xno; then TESTBFDLIB=3D"-Wl,--rpath,../bfd/.libs ../bfd/.libs/libbfd.so" TESTCTFLIB=3D"-Wl,--rpath,../libctf/.libs ../libctf/.libs/libctf.so" + TESTSFRAMELIB=3D"-Wl,--rpath,../libsframe/.libs ../libsframe/.libs/libsf= rame.so" else TESTBFDLIB=3D"../bfd/.libs/libbfd.a" TESTCTFLIB=3D"../libctf/.libs/libctf.a" + TESTSFRAMELIB=3D"../libsframe/.libs/libsframe.a" fi if test "${enable_libctf}" =3D no; then TESTCTFLIB=3D fi AC_SUBST(TESTBFDLIB) AC_SUBST(TESTCTFLIB) +AC_SUBST(TESTSFRAMELIB) =20 target_vendor=3D${target_vendor=3D$host_vendor} case "$target_vendor" in diff --git a/ld/ld.texi b/ld/ld.texi index 82527e3652c..3836465730c 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -2837,7 +2837,9 @@ section and ELF @code{PT_GNU_EH_FRAME} segment header. @item --no-ld-generated-unwind-info Request creation of @code{.eh_frame} unwind info for linker generated code sections like PLT. This option is on by default -if linker generated unwind info is supported. +if linker generated unwind info is supported. This option also +controls the generation of @code{.sframe} unwind info for linker +generated code sections like PLT. =20 @kindex --enable-new-dtags @kindex --disable-new-dtags diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc index bf2268bb0ad..5cc364b0c2a 100644 --- a/ld/scripttempl/elf.sc +++ b/ld/scripttempl/elf.sc @@ -601,6 +601,7 @@ cat <sfe_funcdesc); - free (encoder->sfe_fres); - free (encoder->sfe_data); - free (encoder); + sframe_encoder_ctx *ectx =3D *encoder; + if (ectx =3D=3D NULL) + return; + + if (ectx->sfe_funcdesc !=3D NULL) + { + free (ectx->sfe_funcdesc); + ectx->sfe_funcdesc =3D NULL; + } + if (ectx->sfe_fres !=3D NULL) + { + free (ectx->sfe_fres); + ectx->sfe_fres =3D NULL; + } + if (ectx->sfe_data !=3D NULL) + { + free (ectx->sfe_data); + ectx->sfe_data =3D NULL; + } + + free (*encoder); + *encoder =3D NULL; } }