diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2017-06-22 05:44:37 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2017-06-22 05:44:53 -0700 |
commit | ee2fdd6f36c10ceb84e05c7234983bcfbe6146d5 (patch) | |
tree | f8980ac68ae80a5db4c84efaec81d7b35c833da8 /binutils | |
parent | f4906a9a7441ef9c2758513420568994a1e7fed3 (diff) | |
download | gdb-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 'binutils')
-rw-r--r-- | binutils/ChangeLog | 16 | ||||
-rw-r--r-- | binutils/readelf.c | 38 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/i386/empty.d | 9 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/i386/empty.s | 27 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/i386/ibt.d | 9 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/i386/ibt.s | 27 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/x86-64/empty-x32.d | 10 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/x86-64/empty.d | 9 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/x86-64/empty.s | 27 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/x86-64/ibt-x32.d | 10 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/x86-64/ibt.d | 9 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/x86-64/ibt.s | 27 |
12 files changed, 218 insertions, 0 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index a9166de..3870711 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,19 @@ +2017-06-22 H.J. Lu <hongjiu.lu@intel.com> + + * 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. + 2017-06-21 H.J. Lu <hongjiu.lu@intel.com> * dwarf.c (READ_ULEB): Use DWARF_VMA_FMT to report error. diff --git a/binutils/readelf.c b/binutils/readelf.c index bb6bb79..50354c1 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -16338,6 +16338,36 @@ decode_x86_isa (unsigned int bitmask) } static void +decode_x86_feature (unsigned int type, unsigned int bitmask) +{ + while (bitmask) + { + unsigned int bit = bitmask & (- bitmask); + + bitmask &= ~ bit; + switch (bit) + { + case GNU_PROPERTY_X86_FEATURE_1_IBT: + switch (type) + { + case GNU_PROPERTY_X86_FEATURE_1_AND: + printf ("IBT"); + break; + default: + /* This should never happen. */ + abort (); + } + break; + default: + printf (_("<unknown: %x>"), bit); + break; + } + if (bitmask) + printf (", "); + } +} + +static void print_gnu_property_note (Elf_Internal_Note * pnote) { unsigned char * ptr = (unsigned char *) pnote->descdata; @@ -16391,6 +16421,14 @@ print_gnu_property_note (Elf_Internal_Note * pnote) decode_x86_isa (byte_get (ptr, 4)); goto next; + case GNU_PROPERTY_X86_FEATURE_1_AND: + printf ("x86 feature: "); + if (datasz != 4) + printf (_("<corrupt length: %#x> "), datasz); + else + decode_x86_feature (type, byte_get (ptr, 4)); + goto next; + default: break; } diff --git a/binutils/testsuite/binutils-all/i386/empty.d b/binutils/testsuite/binutils-all/i386/empty.d new file mode 100644 index 0000000..5f4cc56 --- /dev/null +++ b/binutils/testsuite/binutils-all/i386/empty.d @@ -0,0 +1,9 @@ +#PROG: objcopy +#as: --32 +#objcopy: +#readelf: -n + +Displaying notes found in: .note.gnu.property + Owner Data size Description + GNU 0x0000000c NT_GNU_PROPERTY_TYPE_0 + Properties: x86 feature: diff --git a/binutils/testsuite/binutils-all/i386/empty.s b/binutils/testsuite/binutils-all/i386/empty.s new file mode 100644 index 0000000..6a6b517 --- /dev/null +++ b/binutils/testsuite/binutils-all/i386/empty.s @@ -0,0 +1,27 @@ + .section ".note.gnu.property", "a" +.ifdef __64_bit__ + .p2align 3 +.else + .p2align 2 +.endif + .long 1f - 0f /* name length */ + .long 5f - 2f /* data length */ + .long 5 /* note type */ +0: .asciz "GNU" /* vendor name */ +1: +.ifdef __64_bit__ + .p2align 3 +.else + .p2align 2 +.endif +2: .long 0xc0000002 /* pr_type. */ + .long 4f - 3f /* pr_datasz. */ +3: + .long 0x0 +4: +.ifdef __64_bit__ + .p2align 3 +.else + .p2align 2 +.endif +5: diff --git a/binutils/testsuite/binutils-all/i386/ibt.d b/binutils/testsuite/binutils-all/i386/ibt.d new file mode 100644 index 0000000..dfd7676 --- /dev/null +++ b/binutils/testsuite/binutils-all/i386/ibt.d @@ -0,0 +1,9 @@ +#PROG: objcopy +#as: --32 +#objcopy: +#readelf: -n + +Displaying notes found in: .note.gnu.property + Owner Data size Description + GNU 0x0000000c NT_GNU_PROPERTY_TYPE_0 + Properties: x86 feature: IBT diff --git a/binutils/testsuite/binutils-all/i386/ibt.s b/binutils/testsuite/binutils-all/i386/ibt.s new file mode 100644 index 0000000..84ee964 --- /dev/null +++ b/binutils/testsuite/binutils-all/i386/ibt.s @@ -0,0 +1,27 @@ + .section ".note.gnu.property", "a" +.ifdef __64_bit__ + .p2align 3 +.else + .p2align 2 +.endif + .long 1f - 0f /* name length */ + .long 5f - 2f /* data length */ + .long 5 /* note type */ +0: .asciz "GNU" /* vendor name */ +1: +.ifdef __64_bit__ + .p2align 3 +.else + .p2align 2 +.endif +2: .long 0xc0000002 /* pr_type. */ + .long 4f - 3f /* pr_datasz. */ +3: + .long 0x1 +4: +.ifdef __64_bit__ + .p2align 3 +.else + .p2align 2 +.endif +5: diff --git a/binutils/testsuite/binutils-all/x86-64/empty-x32.d b/binutils/testsuite/binutils-all/x86-64/empty-x32.d new file mode 100644 index 0000000..4193818 --- /dev/null +++ b/binutils/testsuite/binutils-all/x86-64/empty-x32.d @@ -0,0 +1,10 @@ +#source: empty.s +#PROG: objcopy +#as: --x32 +#objcopy: +#readelf: -n + +Displaying notes found in: .note.gnu.property + Owner Data size Description + GNU 0x0000000c NT_GNU_PROPERTY_TYPE_0 + Properties: x86 feature: diff --git a/binutils/testsuite/binutils-all/x86-64/empty.d b/binutils/testsuite/binutils-all/x86-64/empty.d new file mode 100644 index 0000000..777efbb --- /dev/null +++ b/binutils/testsuite/binutils-all/x86-64/empty.d @@ -0,0 +1,9 @@ +#PROG: objcopy +#as: --64 -defsym __64_bit__=1 +#objcopy: +#readelf: -n + +Displaying notes found in: .note.gnu.property + Owner Data size Description + GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0 + Properties: x86 feature: diff --git a/binutils/testsuite/binutils-all/x86-64/empty.s b/binutils/testsuite/binutils-all/x86-64/empty.s new file mode 100644 index 0000000..6a6b517 --- /dev/null +++ b/binutils/testsuite/binutils-all/x86-64/empty.s @@ -0,0 +1,27 @@ + .section ".note.gnu.property", "a" +.ifdef __64_bit__ + .p2align 3 +.else + .p2align 2 +.endif + .long 1f - 0f /* name length */ + .long 5f - 2f /* data length */ + .long 5 /* note type */ +0: .asciz "GNU" /* vendor name */ +1: +.ifdef __64_bit__ + .p2align 3 +.else + .p2align 2 +.endif +2: .long 0xc0000002 /* pr_type. */ + .long 4f - 3f /* pr_datasz. */ +3: + .long 0x0 +4: +.ifdef __64_bit__ + .p2align 3 +.else + .p2align 2 +.endif +5: diff --git a/binutils/testsuite/binutils-all/x86-64/ibt-x32.d b/binutils/testsuite/binutils-all/x86-64/ibt-x32.d new file mode 100644 index 0000000..5be7c98 --- /dev/null +++ b/binutils/testsuite/binutils-all/x86-64/ibt-x32.d @@ -0,0 +1,10 @@ +#source: ibt.s +#PROG: objcopy +#as: --x32 +#objcopy: +#readelf: -n + +Displaying notes found in: .note.gnu.property + Owner Data size Description + GNU 0x0000000c NT_GNU_PROPERTY_TYPE_0 + Properties: x86 feature: IBT diff --git a/binutils/testsuite/binutils-all/x86-64/ibt.d b/binutils/testsuite/binutils-all/x86-64/ibt.d new file mode 100644 index 0000000..7bedff5 --- /dev/null +++ b/binutils/testsuite/binutils-all/x86-64/ibt.d @@ -0,0 +1,9 @@ +#PROG: objcopy +#as: --64 -defsym __64_bit__=1 +#objcopy: +#readelf: -n + +Displaying notes found in: .note.gnu.property + Owner Data size Description + GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0 + Properties: x86 feature: IBT diff --git a/binutils/testsuite/binutils-all/x86-64/ibt.s b/binutils/testsuite/binutils-all/x86-64/ibt.s new file mode 100644 index 0000000..84ee964 --- /dev/null +++ b/binutils/testsuite/binutils-all/x86-64/ibt.s @@ -0,0 +1,27 @@ + .section ".note.gnu.property", "a" +.ifdef __64_bit__ + .p2align 3 +.else + .p2align 2 +.endif + .long 1f - 0f /* name length */ + .long 5f - 2f /* data length */ + .long 5 /* note type */ +0: .asciz "GNU" /* vendor name */ +1: +.ifdef __64_bit__ + .p2align 3 +.else + .p2align 2 +.endif +2: .long 0xc0000002 /* pr_type. */ + .long 4f - 3f /* pr_datasz. */ +3: + .long 0x1 +4: +.ifdef __64_bit__ + .p2align 3 +.else + .p2align 2 +.endif +5: |