aboutsummaryrefslogtreecommitdiff
path: root/ld/emulparams
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2017-06-22 05:44:37 -0700
committerH.J. Lu <hjl.tools@gmail.com>2017-06-22 05:44:53 -0700
commitee2fdd6f36c10ceb84e05c7234983bcfbe6146d5 (patch)
treef8980ac68ae80a5db4c84efaec81d7b35c833da8 /ld/emulparams
parentf4906a9a7441ef9c2758513420568994a1e7fed3 (diff)
downloadgdb-ee2fdd6f36c10ceb84e05c7234983bcfbe6146d5.zip
gdb-ee2fdd6f36c10ceb84e05c7234983bcfbe6146d5.tar.gz
gdb-ee2fdd6f36c10ceb84e05c7234983bcfbe6146d5.tar.bz2
x86: Support Intel IBT with IBT property and IBT-enable PLT
To support IBT in Intel Control-flow Enforcement Technology (CET) instructions: https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf #define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 #define GNU_PROPERTY_X86_FEATURE_1_IBT (1U << 0) are added to GNU program properties to indicate that all executable sections are compatible with IBT when ENDBR instruction starts each valid target where an indirect branch instruction can land. GNU_PROPERTY_X86_FEATURE_1_IBT is set on output only if it is set on all relocatable inputs. The followings changes are made to the Procedure Linkage Table (PLT): 1. For 64-bit x86-64, PLT is changed to PLT0: push GOT[1] bnd jmp *GOT[2] nop ... PLTn: endbr64 push namen_reloc_index bnd jmp PLT0 together with the second PLT section: PLTn: endbr64 bnd jmp *GOT[namen_index] nop BND prefix is also added so that IBT-enabled PLT is compatible with MPX. 2. For 32-bit x86-64 (x32) and i386, PLT is changed to PLT0: push GOT[1] jmp *GOT[2] nop ... PLTn: endbr64 # endbr32 for i386. push namen_reloc_index jmp PLT0 together with the second PLT section: PLTn: endbr64 # endbr32 for i386. jmp *GOT[namen_index] nop BND prefix isn't used since MPX isn't supported on x32 and BND registers aren't used in parameter passing on i386. GOT is an array of addresses. Initially, GOT[namen_index] is filled with the address of the ENDBR instruction of the corresponding entry in the first PLT section. The function, namen, is called via the ENDBR instruction in the second PLT entry. GOT[namen_index] is updated to the actual address of the function, namen, at run-time. 2 linker command line options are added: 1. -z ibtplt: Generate IBT-enabled PLT. 2. -z ibt: Generate GNU_PROPERTY_X86_FEATURE_1_IBT in GNU program properties as well as IBT-enabled PLT. bfd/ * elf32-i386.c (elf_i386_lazy_ibt_plt0_entry): New. (elf_i386_lazy_ibt_plt_entry): Likewise. (elf_i386_pic_lazy_ibt_plt0_entry): Likewise. (elf_i386_non_lazy_ibt_plt_entry): Likewise. (elf_i386_pic_non_lazy_ibt_plt_entry): Likewise. (elf_i386_eh_frame_lazy_ibt_plt): Likewise. (elf_i386_lazy_plt_layout): Likewise. (elf_i386_non_lazy_plt_layout): Likewise. (elf_i386_link_hash_entry): Add plt_second. (elf_i386_link_hash_table): Add plt_second and plt_second_eh_frame. (elf_i386_allocate_dynrelocs): Use the second PLT if needed. (elf_i386_size_dynamic_sections): Use .plt.got unwind info for the second PLT. Check the second PLT. (elf_i386_relocate_section): Use the second PLT to resolve PLT reference if needed. (elf_i386_finish_dynamic_symbol): Fill and use the second PLT if needed. (elf_i386_finish_dynamic_sections): Set sh_entsize on the second PLT. Generate unwind info for the second PLT. (elf_i386_plt_type): Add plt_second. (elf_i386_get_synthetic_symtab): Support the second PLT. (elf_i386_parse_gnu_properties): Support GNU_PROPERTY_X86_FEATURE_1_AND. (elf_i386_merge_gnu_properties): Support GNU_PROPERTY_X86_FEATURE_1_AND. If info->ibt is set, turn on GNU_PROPERTY_X86_FEATURE_1_IBT (elf_i386_link_setup_gnu_properties): If info->ibt is set, turn on GNU_PROPERTY_X86_FEATURE_1_IBT. Use IBT-enabled PLT for info->ibtplt, info->ibt or GNU_PROPERTY_X86_FEATURE_1_IBT is set on all relocatable inputs. * elf64-x86-64.c (elf_x86_64_lazy_ibt_plt_entry): New. (elf_x32_lazy_ibt_plt_entry): Likewise. (elf_x86_64_non_lazy_ibt_plt_entry): Likewise. (elf_x32_non_lazy_ibt_plt_entry): Likewise. (elf_x86_64_eh_frame_lazy_ibt_plt): Likewise. (elf_x32_eh_frame_lazy_ibt_plt): Likewise. (elf_x86_64_lazy_ibt_plt): Likewise. (elf_x32_lazy_ibt_plt): Likewise. (elf_x86_64_non_lazy_ibt_plt): Likewise. (elf_x32_non_lazy_ibt_plt): Likewise. (elf_x86_64_get_synthetic_symtab): Support the second PLT. (elf_x86_64_parse_gnu_properties): Support GNU_PROPERTY_X86_FEATURE_1_AND. (elf_x86_64_merge_gnu_properties): Support GNU_PROPERTY_X86_FEATURE_1_AND. If info->ibt is set, turn on GNU_PROPERTY_X86_FEATURE_1_IBT (elf_x86_64_link_setup_gnu_properties): If info->ibt is set, turn on GNU_PROPERTY_X86_FEATURE_1_IBT. Use IBT-enabled PLT for info->ibtplt, info->ibt or GNU_PROPERTY_X86_FEATURE_1_IBT is set on all relocatable inputs. binutils/ * readelf.c (decode_x86_feature): New. (print_gnu_property_note): Call decode_x86_feature on GNU_PROPERTY_X86_FEATURE_1_AND. * testsuite/binutils-all/i386/empty.d: New file. * testsuite/binutils-all/i386/empty.s: Likewise. * testsuite/binutils-all/i386/ibt.d: Likewise. * testsuite/binutils-all/i386/ibt.s: Likewise. * testsuite/binutils-all/x86-64/empty-x32.d: Likewise. * testsuite/binutils-all/x86-64/empty.d: Likewise. * testsuite/binutils-all/x86-64/empty.s: Likewise. * testsuite/binutils-all/x86-64/ibt-x32.d: Likewise. * testsuite/binutils-all/x86-64/ibt.d: Likewise. * testsuite/binutils-all/x86-64/ibt.s: Likewise. include/ * bfdlink.h (bfd_link_info): Add ibtplt and ibt. * elf/common.h (GNU_PROPERTY_X86_FEATURE_1_AND): New. (GNU_PROPERTY_X86_FEATURE_1_IBT): Likewise. ld/ * Makefile.am (ELF_X86_DEPS): Add $(srcdir)/emulparams/cet.sh. * Makefile.in: Regenerated. * NEWS: Mention GNU_PROPERTY_X86_FEATURE_1_IBT, -z ibtplt and -z ibt. * emulparams/cet.sh: New file. * testsuite/ld-i386/ibt-plt-1.d: Likewise. * testsuite/ld-i386/ibt-plt-1.s: Likewise. * testsuite/ld-i386/ibt-plt-2.s: Likewise. * testsuite/ld-i386/ibt-plt-2a.d: Likewise. * testsuite/ld-i386/ibt-plt-2b.d: Likewise. * testsuite/ld-i386/ibt-plt-2c.d: Likewise. * testsuite/ld-i386/ibt-plt-2d.d: Likewise. * testsuite/ld-i386/ibt-plt-3.s: Likewise. * testsuite/ld-i386/ibt-plt-3a.d: Likewise. * testsuite/ld-i386/ibt-plt-3b.d: Likewise. * testsuite/ld-i386/ibt-plt-3c.d: Likewise. * testsuite/ld-i386/ibt-plt-3d.d: Likewise. * testsuite/ld-i386/plt-main-ibt.dd: Likewise. * testsuite/ld-i386/plt-pie-ibt.dd: Likewise. * testsuite/ld-i386/property-x86-empty.s: Likewise. * testsuite/ld-i386/property-x86-ibt.s: Likewise. * testsuite/ld-i386/property-x86-ibt1a.d: Likewise. * testsuite/ld-i386/property-x86-ibt1b.d: Likewise. * testsuite/ld-i386/property-x86-ibt2.d: Likewise. * testsuite/ld-i386/property-x86-ibt3a.d: Likewise. * testsuite/ld-i386/property-x86-ibt3b.d: Likewise. * testsuite/ld-i386/property-x86-ibt4.d: Likewise. * testsuite/ld-i386/property-x86-ibt5.d: Likewise. * testsuite/ld-x86-64/ibt-plt-1-x32.d: Likewise. * testsuite/ld-x86-64/ibt-plt-1.d: Likewise. * testsuite/ld-x86-64/ibt-plt-1.s: Likewise. * testsuite/ld-x86-64/ibt-plt-2.s: Likewise. * testsuite/ld-x86-64/ibt-plt-2a-x32.d: Likewise. * testsuite/ld-x86-64/ibt-plt-2a.d: Likewise. * testsuite/ld-x86-64/ibt-plt-2b-x32.d: Likewise. * testsuite/ld-x86-64/ibt-plt-2b.d: Likewise. * testsuite/ld-x86-64/ibt-plt-2c-x32.d: Likewise. * testsuite/ld-x86-64/ibt-plt-2c.d: Likewise. * testsuite/ld-x86-64/ibt-plt-2d-x32.d: Likewise. * testsuite/ld-x86-64/ibt-plt-2d.d: Likewise. * testsuite/ld-x86-64/ibt-plt-3.s: Likewise. * testsuite/ld-x86-64/ibt-plt-3a-x32.d: Likewise. * testsuite/ld-x86-64/ibt-plt-3a.d: Likewise. * testsuite/ld-x86-64/ibt-plt-3b-x32.d: Likewise. * testsuite/ld-x86-64/ibt-plt-3b.d: Likewise. * testsuite/ld-x86-64/ibt-plt-3c-x32.d: Likewise. * testsuite/ld-x86-64/ibt-plt-3c.d: Likewise. * testsuite/ld-x86-64/ibt-plt-3d-x32.d: Likewise. * testsuite/ld-x86-64/ibt-plt-3d.d: Likewise. * testsuite/ld-x86-64/plt-main-ibt-now.rd: Likewise. * testsuite/ld-x86-64/plt-main-ibt-x32.dd: Likewise. * testsuite/ld-x86-64/plt-main-ibt.dd: Likewise. * testsuite/ld-x86-64/property-x86-empty.s: Likewise. * testsuite/ld-x86-64/property-x86-ibt.s: Likewise. * testsuite/ld-x86-64/property-x86-ibt1a-x32.d: Likewise. * testsuite/ld-x86-64/property-x86-ibt1a.d: Likewise. * testsuite/ld-x86-64/property-x86-ibt1b-x32.d: Likewise. * testsuite/ld-x86-64/property-x86-ibt1b.d: Likewise. * testsuite/ld-x86-64/property-x86-ibt2-x32.d: Likewise. * testsuite/ld-x86-64/property-x86-ibt2.d: Likewise. * testsuite/ld-x86-64/property-x86-ibt3a-x32.d: Likewise. * testsuite/ld-x86-64/property-x86-ibt3a.d: Likewise. * testsuite/ld-x86-64/property-x86-ibt3b-x32.d: Likewise. * testsuite/ld-x86-64/property-x86-ibt3b.d: Likewise. * testsuite/ld-x86-64/property-x86-ibt4-x32.d: Likewise. * testsuite/ld-x86-64/property-x86-ibt4.d: Likewise. * testsuite/ld-x86-64/property-x86-ibt5-x32.d: Likewise. * testsuite/ld-x86-64/property-x86-ibt5.d: Likewise. * emulparams/elf32_x86_64.sh: Source emulparams/cet.sh. (TINY_READONLY_SECTION): Add .plt.sec. * emulparams/elf_i386.sh: Likewise. * emulparams/elf_x86_64.sh: Source emulparams/cet.sh. * ld.texinfo: Document -z ibtplt and -z ibt. * testsuite/ld-i386/i386.exp: Run IBT and IBT PLT tests. * testsuite/ld-x86-64/x86-64.exp: Likewise. * testsuite/ld-x86-64/pr21481b.S (check): Updated for x32.
Diffstat (limited to 'ld/emulparams')
-rw-r--r--ld/emulparams/cet.sh14
-rw-r--r--ld/emulparams/elf32_x86_64.sh2
-rw-r--r--ld/emulparams/elf_i386.sh2
-rw-r--r--ld/emulparams/elf_x86_64.sh1
4 files changed, 19 insertions, 0 deletions
diff --git a/ld/emulparams/cet.sh b/ld/emulparams/cet.sh
new file mode 100644
index 0000000..62ff105
--- /dev/null
+++ b/ld/emulparams/cet.sh
@@ -0,0 +1,14 @@
+PARSE_AND_LIST_OPTIONS_CET='
+ fprintf (file, _("\
+ -z ibtplt Generate IBT-enabled PLT entries\n\
+ -z ibt Generate GNU_PROPERTY_X86_FEATURE_1_IBT\n"));
+'
+PARSE_AND_LIST_ARGS_CASE_Z_CET='
+ else if (strcmp (optarg, "ibtplt") == 0)
+ link_info.ibtplt = TRUE;
+ else if (strcmp (optarg, "ibt") == 0)
+ link_info.ibt = TRUE;
+'
+
+PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_CET"
+PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_CET"
diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh
index 9b85239..06a0f3c 100644
--- a/ld/emulparams/elf32_x86_64.sh
+++ b/ld/emulparams/elf32_x86_64.sh
@@ -3,6 +3,7 @@
. ${srcdir}/emulparams/dynamic_undefined_weak.sh
. ${srcdir}/emulparams/reloc_overflow.sh
. ${srcdir}/emulparams/call_nop.sh
+. ${srcdir}/emulparams/cet.sh
SCRIPT_NAME=elf
ELFSIZE=32
OUTPUT_FORMAT="elf32-x86-64"
@@ -24,6 +25,7 @@ IREL_IN_PLT=
# Reuse TINY_READONLY_SECTION which is placed right after .plt section.
TINY_READONLY_SECTION="
.plt.got ${RELOCATING-0} : { *(.plt.got) }
+.plt.sec ${RELOCATING-0} : { *(.plt.sec) }
"
if [ "x${host}" = "x${target}" ]; then
diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh
index b08e661..6997d40 100644
--- a/ld/emulparams/elf_i386.sh
+++ b/ld/emulparams/elf_i386.sh
@@ -2,6 +2,7 @@
. ${srcdir}/emulparams/extern_protected_data.sh
. ${srcdir}/emulparams/dynamic_undefined_weak.sh
. ${srcdir}/emulparams/call_nop.sh
+. ${srcdir}/emulparams/cet.sh
SCRIPT_NAME=elf
OUTPUT_FORMAT="elf32-i386"
CHECK_RELOCS_AFTER_OPEN_INPUT=yes
@@ -20,6 +21,7 @@ IREL_IN_PLT=
# Reuse TINY_READONLY_SECTION which is placed right after .plt section.
TINY_READONLY_SECTION="
.plt.got ${RELOCATING-0} : { *(.plt.got) }
+.plt.sec ${RELOCATING-0} : { *(.plt.sec) }
"
# Linux modify the default library search path to first include
diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh
index ca6d06c..ad25526 100644
--- a/ld/emulparams/elf_x86_64.sh
+++ b/ld/emulparams/elf_x86_64.sh
@@ -3,6 +3,7 @@
. ${srcdir}/emulparams/dynamic_undefined_weak.sh
. ${srcdir}/emulparams/reloc_overflow.sh
. ${srcdir}/emulparams/call_nop.sh
+. ${srcdir}/emulparams/cet.sh
SCRIPT_NAME=elf
ELFSIZE=64
OUTPUT_FORMAT="elf64-x86-64"