From: H.J. Lu Date: Thu, 22 Jun 2017 12:44:37 +0000 (-0700) Subject: x86: Support Intel IBT with IBT property and IBT-enable PLT X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ee2fdd6f36c10ceb84e05c7234983bcfbe6146d5;p=binutils-gdb.git 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. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 57a07a5eca2..ac13db32788 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,57 @@ +2017-06-22 H.J. Lu + + * 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. + 2017-06-22 Nick Clifton PR binutils/21649 diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 6636551fb01..d6628165481 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -617,6 +617,60 @@ static const bfd_byte elf_i386_pic_non_lazy_plt_entry[NON_LAZY_PLT_ENTRY_SIZE] = 0x66, 0x90 /* xchg %ax,%ax */ }; +/* The first entry in an absolute IBT-enabled lazy procedure linkage + table looks like this. */ + +static const bfd_byte elf_i386_lazy_ibt_plt0_entry[LAZY_PLT_ENTRY_SIZE] = +{ + 0xff, 0x35, 0, 0, 0, 0, /* pushl GOT[1] */ + 0xff, 0x25, 0, 0, 0, 0, /* jmp *GOT[2] */ + 0x0f, 0x1f, 0x40, 0x00 /* nopl 0(%rax) */ +}; + +/* Subsequent entries for an absolute IBT-enabled lazy procedure linkage + table look like this. Subsequent entries for a PIC IBT-enabled lazy + procedure linkage table are the same. */ + +static const bfd_byte elf_i386_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] = +{ + 0xf3, 0x0f, 0x1e, 0xfb, /* endbr32 */ + 0x68, 0, 0, 0, 0, /* pushl immediate */ + 0xe9, 0, 0, 0, 0, /* jmp relative */ + 0x66, 0x90 /* xchg %ax,%ax */ +}; + +/* The first entry in a PIC IBT-enabled lazy procedure linkage table + look like. */ + +static const bfd_byte elf_i386_pic_lazy_ibt_plt0_entry[LAZY_PLT_ENTRY_SIZE] = +{ + 0xff, 0xb3, 4, 0, 0, 0, /* pushl 4(%ebx) */ + 0xff, 0xa3, 8, 0, 0, 0, /* jmp *8(%ebx) */ + 0x0f, 0x1f, 0x40, 0x00 /* nopl 0(%rax) */ +}; + +/* Entries for branches with IBT-enabled in the absolute non-lazey + procedure linkage table look like this. They have the same size + as the lazy PLT entry. */ + +static const bfd_byte elf_i386_non_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] = +{ + 0xf3, 0x0f, 0x1e, 0xfb, /* endbr32 */ + 0xff, 0x25, 0, 0, 0, 0, /* jmp *name@GOT */ + 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 /* nopw 0x0(%rax,%rax,1) */ +}; + +/* Entries for branches with IBT-enabled in the PIC non-lazey procedure + linkage table look like this. They have the same size as the lazy + PLT entry. */ + +static const bfd_byte elf_i386_pic_non_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] = +{ + 0xf3, 0x0f, 0x1e, 0xfb, /* endbr32 */ + 0xff, 0xa3, 0, 0, 0, 0, /* jmp *name@GOT(%ebx) */ + 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 /* nopw 0x0(%rax,%rax,1) */ +}; + /* .eh_frame covering the lazy .plt section. */ static const bfd_byte elf_i386_eh_frame_lazy_plt[] = @@ -656,6 +710,41 @@ static const bfd_byte elf_i386_eh_frame_lazy_plt[] = DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop }; +/* .eh_frame covering the lazy .plt section with IBT-enabled. */ + +static const bfd_byte elf_i386_eh_frame_lazy_ibt_plt[] = +{ + PLT_CIE_LENGTH, 0, 0, 0, /* CIE length */ + 0, 0, 0, 0, /* CIE ID */ + 1, /* CIE version */ + 'z', 'R', 0, /* Augmentation string */ + 1, /* Code alignment factor */ + 0x7c, /* Data alignment factor */ + 8, /* Return address column */ + 1, /* Augmentation size */ + DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */ + DW_CFA_def_cfa, 4, 4, /* DW_CFA_def_cfa: r4 (esp) ofs 4 */ + DW_CFA_offset + 8, 1, /* DW_CFA_offset: r8 (eip) at cfa-4 */ + DW_CFA_nop, DW_CFA_nop, + + PLT_FDE_LENGTH, 0, 0, 0, /* FDE length */ + PLT_CIE_LENGTH + 8, 0, 0, 0, /* CIE pointer */ + 0, 0, 0, 0, /* R_386_PC32 .plt goes here */ + 0, 0, 0, 0, /* .plt size goes here */ + 0, /* Augmentation size */ + DW_CFA_def_cfa_offset, 8, /* DW_CFA_def_cfa_offset: 8 */ + DW_CFA_advance_loc + 6, /* DW_CFA_advance_loc: 6 to __PLT__+6 */ + DW_CFA_def_cfa_offset, 12, /* DW_CFA_def_cfa_offset: 12 */ + DW_CFA_advance_loc + 10, /* DW_CFA_advance_loc: 10 to __PLT__+16 */ + DW_CFA_def_cfa_expression, /* DW_CFA_def_cfa_expression */ + 11, /* Block length */ + DW_OP_breg4, 4, /* DW_OP_breg4 (esp): 4 */ + DW_OP_breg8, 0, /* DW_OP_breg8 (eip): 0 */ + DW_OP_lit15, DW_OP_and, DW_OP_lit9, DW_OP_ge, + DW_OP_lit2, DW_OP_shl, DW_OP_plus, + DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop +}; + /* .eh_frame covering the non-lazy .plt section. */ static const bfd_byte elf_i386_eh_frame_non_lazy_plt[] = @@ -786,6 +875,34 @@ static const struct elf_i386_non_lazy_plt_layout elf_i386_non_lazy_plt = elf_i386_eh_frame_non_lazy_plt, /* eh_frame_plt */ sizeof (elf_i386_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ }; + +static const struct elf_i386_lazy_plt_layout elf_i386_lazy_ibt_plt = + { + elf_i386_lazy_ibt_plt0_entry, /* plt0_entry */ + sizeof (elf_i386_lazy_ibt_plt0_entry), /* plt0_entry_size */ + 2, /* plt0_got1_offset */ + 8, /* plt0_got2_offset */ + elf_i386_lazy_ibt_plt_entry, /* plt_entry */ + LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + 4+2, /* plt_got_offset */ + 4+1, /* plt_reloc_offset */ + 4+6, /* plt_plt_offset */ + 0, /* plt_lazy_offset */ + elf_i386_pic_lazy_ibt_plt0_entry, /* pic_plt0_entry */ + elf_i386_lazy_ibt_plt_entry, /* pic_plt_entry */ + elf_i386_eh_frame_lazy_ibt_plt, /* eh_frame_plt */ + sizeof (elf_i386_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */ + }; + +static const struct elf_i386_non_lazy_plt_layout elf_i386_non_lazy_ibt_plt = + { + elf_i386_non_lazy_ibt_plt_entry, /* plt_entry */ + elf_i386_pic_non_lazy_ibt_plt_entry,/* pic_plt_entry */ + LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + 4+2, /* plt_got_offset */ + elf_i386_eh_frame_non_lazy_plt, /* eh_frame_plt */ + sizeof (elf_i386_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ + }; /* On VxWorks, the .rel.plt.unloaded section has absolute relocations @@ -889,6 +1006,9 @@ struct elf_i386_link_hash_entry GOT and PLT relocations against the same function. */ union gotplt_union plt_got; + /* Information about the second PLT entry. */ + union gotplt_union plt_second; + /* Offset of the GOTPLT entry reserved for the TLS descriptor, starting at the end of the jump table. */ bfd_vma tlsdesc_got; @@ -937,6 +1057,8 @@ struct elf_i386_link_hash_table /* Short-cuts to get to dynamic linker sections. */ asection *interp; asection *plt_eh_frame; + asection *plt_second; + asection *plt_second_eh_frame; asection *plt_got; asection *plt_got_eh_frame; @@ -2644,12 +2766,29 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) here if it is defined and referenced in a non-shared object. */ if (h->type == STT_GNU_IFUNC && h->def_regular) - return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs, - &htab->readonly_dynrelocs_against_ifunc, - plt_entry_size, - (htab->plt.has_plt0 * + { + if (_bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs, + &htab->readonly_dynrelocs_against_ifunc, + plt_entry_size, + (htab->plt.has_plt0 * plt_entry_size), - 4, TRUE); + 4, TRUE)) + { + asection *s = htab->plt_second; + if (h->plt.offset != (bfd_vma) -1 && s != NULL) + { + /* Use the second PLT section if it is created. */ + eh->plt_second.offset = s->size; + + /* Make room for this entry in the second PLT section. */ + s->size += htab->non_lazy_plt->plt_entry_size; + } + + return TRUE; + } + else + return FALSE; + } /* Don't create the PLT entry if there are only function pointer relocations which can be resolved at run-time. */ else if (htab->elf.dynamic_sections_created @@ -2677,6 +2816,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) { asection *s = htab->elf.splt; + asection *second_s = htab->plt_second; asection *got_s = htab->plt_got; /* If this is the first .plt entry, make room for the special @@ -2688,7 +2828,11 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (use_plt_got) eh->plt_got.offset = got_s->size; else - h->plt.offset = s->size; + { + h->plt.offset = s->size; + if (second_s) + eh->plt_second.offset = second_s->size; + } /* If this symbol is not defined in a regular file, and we are not generating a shared library, then set the symbol to this @@ -2707,8 +2851,18 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } else { - h->root.u.def.section = s; - h->root.u.def.value = h->plt.offset; + if (second_s) + { + /* We need to make a call to the entry of the + second PLT instead of regular PLT entry. */ + h->root.u.def.section = second_s; + h->root.u.def.value = eh->plt_second.offset; + } + else + { + h->root.u.def.section = s; + h->root.u.def.value = h->plt.offset; + } } } @@ -2718,6 +2872,8 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) else { s->size += plt_entry_size; + if (second_s) + second_s->size += htab->non_lazy_plt->plt_entry_size; /* We also need to make an entry in the .got.plt section, which will be placed in the .got section by the linker @@ -3370,6 +3526,15 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) && !bfd_is_abs_section (htab->plt_got->output_section)) htab->plt_got_eh_frame->size = htab->non_lazy_plt->eh_frame_plt_size; + + /* Unwind info for the second PLT and .plt.got sections are + identical. */ + if (htab->plt_second_eh_frame != NULL + && htab->plt_second != NULL + && htab->plt_second->size != 0 + && !bfd_is_abs_section (htab->plt_second->output_section)) + htab->plt_second_eh_frame->size + = htab->non_lazy_plt->eh_frame_plt_size; } /* We now have determined the sizes of the various dynamic sections. @@ -3397,9 +3562,11 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) else if (s == htab->elf.sgotplt || s == htab->elf.iplt || s == htab->elf.igotplt + || s == htab->plt_second || s == htab->plt_got || s == htab->plt_eh_frame || s == htab->plt_got_eh_frame + || s == htab->plt_second_eh_frame || s == htab->elf.sdynbss || s == htab->elf.sdynrelro) { @@ -3472,6 +3639,17 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) + PLT_FDE_LEN_OFFSET)); } + if (htab->plt_second_eh_frame != NULL + && htab->plt_second_eh_frame->contents != NULL) + { + memcpy (htab->plt_second_eh_frame->contents, + htab->non_lazy_plt->eh_frame_plt, + htab->plt_second_eh_frame->size); + bfd_put_32 (dynobj, htab->plt_second->size, + (htab->plt_second_eh_frame->contents + + PLT_FDE_LEN_OFFSET)); + } + if (htab->elf.dynamic_sections_created) { /* Add some entries to the .dynamic section. We fill in the @@ -3903,13 +4081,15 @@ elf_i386_relocate_section (bfd *output_bfd, continue; } + eh = (struct elf_i386_link_hash_entry *) h; + /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it here if it is defined in a non-shared object. */ if (h != NULL && h->type == STT_GNU_IFUNC && h->def_regular) { - asection *plt, *gotplt, *base_got; + asection *gotplt, *base_got; bfd_vma plt_index; const char *name; @@ -3926,12 +4106,22 @@ elf_i386_relocate_section (bfd *output_bfd, /* STT_GNU_IFUNC symbol must go through PLT. */ if (htab->elf.splt != NULL) { - plt = htab->elf.splt; + if (htab->plt_second != NULL) + { + resolved_plt = htab->plt_second; + plt_offset = eh->plt_second.offset; + } + else + { + resolved_plt = htab->elf.splt; + plt_offset = h->plt.offset; + } gotplt = htab->elf.sgotplt; } else { - plt = htab->elf.iplt; + resolved_plt = htab->elf.iplt; + plt_offset = h->plt.offset; gotplt = htab->elf.igotplt; } @@ -4031,8 +4221,8 @@ elf_i386_relocate_section (bfd *output_bfd, goto bad_ifunc_reloc; } - relocation = (plt->output_section->vma - + plt->output_offset + h->plt.offset); + relocation = (resolved_plt->output_section->vma + + resolved_plt->output_offset + plt_offset); switch (r_type) { @@ -4126,7 +4316,6 @@ do_ifunc_pointer: } } - eh = (struct elf_i386_link_hash_entry *) h; resolved_to_zero = (eh != NULL && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh->has_got_reloc, @@ -4424,8 +4613,16 @@ disallow_got32: if (h->plt.offset != (bfd_vma) -1) { - resolved_plt = htab->elf.splt; - plt_offset = h->plt.offset; + if (htab->plt_second != NULL) + { + resolved_plt = htab->plt_second; + plt_offset = eh->plt_second.offset; + } + else + { + resolved_plt = htab->elf.splt; + plt_offset = h->plt.offset; + } } else { @@ -5258,6 +5455,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, const struct elf_i386_backend_data *abed; struct elf_i386_link_hash_entry *eh; bfd_boolean local_undefweak; + bfd_boolean use_plt_second; htab = elf_i386_hash_table (info); if (htab == NULL) @@ -5266,6 +5464,9 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, abed = get_elf_i386_backend_data (output_bfd); plt_entry_size = htab->plt.plt_entry_size; + /* Use the second PLT section only if there is .plt section. */ + use_plt_second = htab->elf.splt != NULL && htab->plt_second != NULL; + eh = (struct elf_i386_link_hash_entry *) h; if (eh->no_finish_dynamic_symbol) abort (); @@ -5279,11 +5480,11 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, if (h->plt.offset != (bfd_vma) -1) { - bfd_vma plt_index; + bfd_vma plt_index, plt_offset; bfd_vma got_offset; Elf_Internal_Rela rel; bfd_byte *loc; - asection *plt, *gotplt, *relplt; + asection *plt, *resolved_plt, *gotplt, *relplt; /* When building a static executable, use .iplt, .igot.plt and .rel.iplt sections for STT_GNU_IFUNC symbols. */ @@ -5340,13 +5541,33 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, the first slot. */ memcpy (plt->contents + h->plt.offset, htab->plt.plt_entry, plt_entry_size); + + if (use_plt_second) + { + const bfd_byte *plt_entry; + if (bfd_link_pic (info)) + plt_entry = htab->non_lazy_plt->pic_plt_entry; + else + plt_entry = htab->non_lazy_plt->plt_entry; + memcpy (htab->plt_second->contents + eh->plt_second.offset, + plt_entry, htab->non_lazy_plt->plt_entry_size); + + resolved_plt = htab->plt_second; + plt_offset = eh->plt_second.offset; + } + else + { + resolved_plt = plt; + plt_offset = h->plt.offset; + } + if (! bfd_link_pic (info)) { bfd_put_32 (output_bfd, (gotplt->output_section->vma + gotplt->output_offset + got_offset), - plt->contents + h->plt.offset + resolved_plt->contents + plt_offset + htab->plt.plt_got_offset); if (abed->os == is_vxworks) @@ -5370,8 +5591,8 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, loc = (htab->srelplt2->contents + reloc_index * sizeof (Elf32_External_Rel)); - rel.r_offset = (htab->elf.splt->output_section->vma - + htab->elf.splt->output_offset + rel.r_offset = (plt->output_section->vma + + plt->output_offset + h->plt.offset + 2), rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); @@ -5389,7 +5610,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, else { bfd_put_32 (output_bfd, got_offset, - plt->contents + h->plt.offset + resolved_plt->contents + plt_offset + htab->plt.plt_got_offset); } @@ -5577,6 +5798,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, else { asection *plt; + bfd_vma plt_offset; if (!h->pointer_equality_needed) abort (); @@ -5584,10 +5806,19 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, /* For non-shared object, we can't use .got.plt, which contains the real function addres if we need pointer equality. We load the GOT entry with the PLT entry. */ - plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt; + if (htab->plt_second != NULL) + { + plt = htab->plt_second; + plt_offset = eh->plt_second.offset; + } + else + { + plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt; + plt_offset = h->plt.offset; + } bfd_put_32 (output_bfd, (plt->output_section->vma - + plt->output_offset + h->plt.offset), + + plt->output_offset + plt_offset), htab->elf.sgot->contents + h->got.offset); return TRUE; } @@ -5868,6 +6099,10 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, if (htab->plt_got != NULL && htab->plt_got->size > 0) elf_section_data (htab->plt_got->output_section) ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size; + + if (htab->plt_second != NULL && htab->plt_second->size > 0) + elf_section_data (htab->plt_second->output_section) + ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size; } /* Fill in the first three entries in the global offset table. */ @@ -5945,6 +6180,35 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, } } + /* Adjust .eh_frame for the second PLT section. */ + if (htab->plt_second_eh_frame != NULL + && htab->plt_second_eh_frame->contents != NULL) + { + if (htab->plt_second != NULL + && htab->plt_second->size != 0 + && (htab->plt_second->flags & SEC_EXCLUDE) == 0 + && htab->plt_second->output_section != NULL + && htab->plt_second_eh_frame->output_section != NULL) + { + bfd_vma plt_start = htab->plt_second->output_section->vma; + bfd_vma eh_frame_start + = (htab->plt_second_eh_frame->output_section->vma + + htab->plt_second_eh_frame->output_offset + + PLT_FDE_START_OFFSET); + bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, + htab->plt_second_eh_frame->contents + + PLT_FDE_START_OFFSET); + } + if (htab->plt_second_eh_frame->sec_info_type + == SEC_INFO_TYPE_EH_FRAME) + { + if (! _bfd_elf_write_section_eh_frame (output_bfd, info, + htab->plt_second_eh_frame, + htab->plt_second_eh_frame->contents)) + return FALSE; + } + } + if (htab->elf.sgot && htab->elf.sgot->size > 0) elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4; @@ -6005,6 +6269,7 @@ enum elf_i386_plt_type plt_non_lazy = 0, plt_lazy = 1 << 0, plt_pic = 1 << 1, + plt_second = 1 << 2, plt_unknown = -1 }; @@ -6042,6 +6307,8 @@ elf_i386_get_synthetic_symtab (bfd *abfd, arelent **dynrelbuf; const struct elf_i386_lazy_plt_layout *lazy_plt; const struct elf_i386_non_lazy_plt_layout *non_lazy_plt; + const struct elf_i386_lazy_plt_layout *lazy_ibt_plt; + const struct elf_i386_non_lazy_plt_layout *non_lazy_ibt_plt; asection *plt; bfd_vma got_addr; char *names; @@ -6050,6 +6317,7 @@ elf_i386_get_synthetic_symtab (bfd *abfd, { { ".plt", NULL, NULL, plt_unknown, 0, 0, 0 }, { ".plt.got", NULL, NULL, plt_non_lazy, 0, 0, 0 }, + { ".plt.sec", NULL, NULL, plt_second, 0, 0, 0 }, { NULL, NULL, NULL, plt_non_lazy, 0, 0, 0 } }; @@ -6078,10 +6346,14 @@ elf_i386_get_synthetic_symtab (bfd *abfd, non_lazy_plt = NULL; /* Silence GCC 6. */ lazy_plt = NULL; + non_lazy_ibt_plt = NULL; + lazy_ibt_plt = NULL; switch (get_elf_i386_backend_data (abfd)->os) { case is_normal: non_lazy_plt = &elf_i386_non_lazy_plt; + lazy_ibt_plt = &elf_i386_lazy_ibt_plt; + non_lazy_ibt_plt = &elf_i386_non_lazy_ibt_plt; /* Fall through */ case is_vxworks: lazy_plt = &elf_i386_lazy_plt; @@ -6118,10 +6390,30 @@ elf_i386_get_synthetic_symtab (bfd *abfd, /* Match lazy PLT first. */ if (memcmp (plt_contents, lazy_plt->plt0_entry, lazy_plt->plt0_got1_offset) == 0) - plt_type = plt_lazy; + { + /* The fist entry in the lazy IBT PLT is the same as the + normal lazy PLT. */ + if (lazy_ibt_plt != NULL + && (memcmp (plt_contents + lazy_ibt_plt->plt_entry_size, + lazy_ibt_plt->plt_entry, + lazy_ibt_plt->plt_got_offset) == 0)) + plt_type = plt_lazy | plt_second; + else + plt_type = plt_lazy; + } else if (memcmp (plt_contents, lazy_plt->pic_plt0_entry, lazy_plt->plt0_got1_offset) == 0) - plt_type = plt_lazy | plt_pic; + { + /* The fist entry in the PIC lazy IBT PLT is the same as + the normal PIC lazy PLT. */ + if (lazy_ibt_plt != NULL + && (memcmp (plt_contents + lazy_ibt_plt->plt_entry_size, + lazy_ibt_plt->pic_plt_entry, + lazy_ibt_plt->plt_got_offset) == 0)) + plt_type = plt_lazy | plt_pic | plt_second; + else + plt_type = plt_lazy | plt_pic; + } } if (non_lazy_plt != NULL @@ -6136,6 +6428,27 @@ elf_i386_get_synthetic_symtab (bfd *abfd, plt_type = plt_pic; } + if ((non_lazy_ibt_plt != NULL) + && (plt_type == plt_unknown || plt_type == plt_second)) + { + if (memcmp (plt_contents, + non_lazy_ibt_plt->plt_entry, + non_lazy_ibt_plt->plt_got_offset) == 0) + { + /* Match IBT PLT. */ + plt_type = plt_second; + non_lazy_plt = non_lazy_ibt_plt; + } + else if (memcmp (plt_contents, + non_lazy_ibt_plt->pic_plt_entry, + non_lazy_ibt_plt->plt_got_offset) == 0) + { + /* Match PIC IBT PLT. */ + plt_type = plt_second | plt_pic; + non_lazy_plt = non_lazy_ibt_plt; + } + } + if (plt_type == plt_unknown) continue; @@ -6156,9 +6469,16 @@ elf_i386_get_synthetic_symtab (bfd *abfd, i = 0; } - n = plt->size / plts[j].plt_entry_size; - plts[j].count = n; - count += n - i; + /* Skip lazy PLT when the second PLT is used. */ + if ((plt_type & (plt_lazy | plt_second)) + == (plt_lazy | plt_second)) + plts[j].count = 0; + else + { + n = plt->size / plts[j].plt_entry_size; + plts[j].count = n; + count += n - i; + } plts[j].contents = plt_contents; @@ -6363,12 +6683,15 @@ elf_i386_parse_gnu_properties (bfd *abfd, unsigned int type, { case GNU_PROPERTY_X86_ISA_1_USED: case GNU_PROPERTY_X86_ISA_1_NEEDED: + case GNU_PROPERTY_X86_FEATURE_1_AND: if (datasz != 4) { _bfd_error_handler ((type == GNU_PROPERTY_X86_ISA_1_USED ? _("error: %B: ") - : _("error: %B: ")), + : (type == GNU_PROPERTY_X86_ISA_1_NEEDED + ? _("error: %B: ") + : _("error: %B: "))), abfd, datasz); return property_corrupt; } @@ -6390,12 +6713,12 @@ elf_i386_parse_gnu_properties (bfd *abfd, unsigned int type, should be merged with ABFD. */ static bfd_boolean -elf_i386_merge_gnu_properties (struct bfd_link_info *info ATTRIBUTE_UNUSED, +elf_i386_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd ATTRIBUTE_UNUSED, elf_property *aprop, elf_property *bprop) { - unsigned int number; + unsigned int number, features; bfd_boolean updated = FALSE; unsigned int pr_type = aprop != NULL ? aprop->pr_type : bprop->pr_type; @@ -6417,6 +6740,53 @@ elf_i386_merge_gnu_properties (struct bfd_link_info *info ATTRIBUTE_UNUSED, } break; + case GNU_PROPERTY_X86_FEATURE_1_AND: + /* Only one of APROP and BPROP can be NULL: + 1. APROP & BPROP when both APROP and BPROP aren't NULL. + 2. If APROP is NULL, remove x86 feature. + 3. Otherwise, do nothing. + */ + if (aprop != NULL && bprop != NULL) + { + features = 0; + if (info->ibt) + features = GNU_PROPERTY_X86_FEATURE_1_IBT; + number = aprop->u.number; + /* Add GNU_PROPERTY_X86_FEATURE_1_IBT. */ + aprop->u.number = (number & bprop->u.number) | features; + updated = number != (unsigned int) aprop->u.number; + /* Remove the property if all feature bits are cleared. */ + if (aprop->u.number == 0) + aprop->pr_kind = property_remove; + } + else + { + features = 0; + if (info->ibt) + features = GNU_PROPERTY_X86_FEATURE_1_IBT; + if (features) + { + /* Add GNU_PROPERTY_X86_FEATURE_1_IBT. */ + if (aprop != NULL) + { + number = aprop->u.number; + aprop->u.number = number | features; + updated = number != (unsigned int) aprop->u.number; + } + else + { + bprop->u.number |= features; + updated = TRUE; + } + } + else if (aprop != NULL) + { + aprop->pr_kind = property_remove; + updated = TRUE; + } + } + break; + default: /* Never should happen. */ abort (); @@ -6432,11 +6802,72 @@ static bfd * elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) { bfd_boolean normal_target; + bfd_boolean lazy_plt; asection *sec, *pltsec; bfd *dynobj; - unsigned int plt_alignment; + bfd_boolean use_ibt_plt; + unsigned int plt_alignment, features; struct elf_i386_link_hash_table *htab; - bfd *pbfd = _bfd_elf_link_setup_gnu_properties (info); + bfd *pbfd; + + features = 0; + if (info->ibt) + features = GNU_PROPERTY_X86_FEATURE_1_IBT; + if (features) + { + /* Turn on GNU_PROPERTY_X86_FEATURE_1_IBT. */ + bfd *ebfd = NULL; + elf_property *prop; + + for (pbfd = info->input_bfds; + pbfd != NULL; + pbfd = pbfd->link.next) + if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour + && bfd_count_sections (pbfd) != 0) + { + ebfd = pbfd; + + if (elf_properties (pbfd) != NULL) + { + /* Find a normal input file with GNU property note. */ + prop = _bfd_elf_get_property (pbfd, + GNU_PROPERTY_X86_FEATURE_1_AND, + 4); + /* Add GNU_PROPERTY_X86_FEATURE_1_IBT. */ + prop->u.number |= features; + prop->pr_kind = property_number; + break; + } + } + + if (pbfd == NULL && ebfd != NULL) + { + /* Create GNU_PROPERTY_X86_FEATURE_1_IBT if needed. */ + prop = _bfd_elf_get_property (ebfd, + GNU_PROPERTY_X86_FEATURE_1_AND, + 4); + prop->u.number = features; + prop->pr_kind = property_number; + + sec = bfd_make_section_with_flags (ebfd, + NOTE_GNU_PROPERTY_SECTION_NAME, + (SEC_ALLOC + | SEC_LOAD + | SEC_IN_MEMORY + | SEC_READONLY + | SEC_HAS_CONTENTS + | SEC_DATA)); + if (sec == NULL) + info->callbacks->einfo (_("%F: failed to create GNU property section\n")); + + if (!bfd_set_section_alignment (ebfd, sec, 2)) + goto error_alignment; + + elf_section_type (sec) = SHT_NOTE; + } + } + + pbfd = _bfd_elf_link_setup_gnu_properties (info); if (bfd_link_relocatable (info)) return pbfd; @@ -6445,6 +6876,26 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) if (htab == NULL) return pbfd; + use_ibt_plt = info->ibtplt || info->ibt; + if (!use_ibt_plt && pbfd != NULL) + { + /* Check if GNU_PROPERTY_X86_FEATURE_1_IBT is on. */ + elf_property_list *p; + + /* The property list is sorted in order of type. */ + for (p = elf_properties (pbfd); p; p = p->next) + { + if (GNU_PROPERTY_X86_FEATURE_1_AND == p->property.pr_type) + { + use_ibt_plt = !!(p->property.u.number + & GNU_PROPERTY_X86_FEATURE_1_IBT); + break; + } + else if (GNU_PROPERTY_X86_FEATURE_1_AND < p->property.pr_type) + break; + } + } + dynobj = htab->elf.dynobj; /* Set htab->elf.dynobj here so that there is no need to check and @@ -6476,8 +6927,16 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) switch (get_elf_i386_backend_data (info->output_bfd)->os) { case is_normal: - htab->lazy_plt = &elf_i386_lazy_plt; - htab->non_lazy_plt = &elf_i386_non_lazy_plt; + if (use_ibt_plt) + { + htab->lazy_plt = &elf_i386_lazy_ibt_plt; + htab->non_lazy_plt = &elf_i386_non_lazy_ibt_plt; + } + else + { + htab->lazy_plt = &elf_i386_lazy_plt; + htab->non_lazy_plt = &elf_i386_non_lazy_plt; + } normal_target = TRUE; break; case is_vxworks: @@ -6500,6 +6959,7 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) if (htab->non_lazy_plt != NULL && (!htab->plt.has_plt0 || pltsec == NULL)) { + lazy_plt = FALSE; if (bfd_link_pic (info)) htab->plt.plt_entry = htab->non_lazy_plt->pic_plt_entry; @@ -6517,6 +6977,7 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) } else { + lazy_plt = TRUE; if (bfd_link_pic (info)) { htab->plt.plt0_entry @@ -6605,6 +7066,29 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) goto error_alignment; htab->plt_got = sec; + + if (lazy_plt) + { + sec = NULL; + + if (use_ibt_plt) + { + /* Create the second PLT for Intel IBT support. IBT + PLT is supported only for non-NaCl target and is + is needed only for lazy binding. */ + sec = bfd_make_section_anyway_with_flags (dynobj, + ".plt.sec", + pltflags); + if (sec == NULL) + info->callbacks->einfo (_("%F: failed to create IBT-enabled PLT section\n")); + + if (!bfd_set_section_alignment (dynobj, sec, + plt_alignment)) + goto error_alignment; + } + + htab->plt_second = sec; + } } if (!info->no_ld_generated_unwind_info) diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index ab6f06887e0..1f8e6d0ebde 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -596,6 +596,32 @@ static const bfd_byte elf_x86_64_lazy_bnd_plt_entry[LAZY_PLT_ENTRY_SIZE] = 0x0f, 0x1f, 0x44, 0, 0 /* nopl 0(%rax,%rax,1) */ }; +/* The first entry in the IBT-enabled lazy procedure linkage table is the + the same as the lazy PLT with BND prefix so that bound registers are + preserved when control is passed to dynamic linker. Subsequent + entries for a IBT-enabled lazy procedure linkage table look like + this. */ + +static const bfd_byte elf_x86_64_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] = +{ + 0xf3, 0x0f, 0x1e, 0xfa, /* endbr64 */ + 0x68, 0, 0, 0, 0, /* pushq immediate */ + 0xf2, 0xe9, 0, 0, 0, 0, /* bnd jmpq relative */ + 0x90 /* nop */ +}; + +/* The first entry in the x32 IBT-enabled lazy procedure linkage table + is the the same as the normal lazy PLT. Subsequent entries for an + x32 IBT-enabled lazy procedure linkage table look like this. */ + +static const bfd_byte elf_x32_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] = +{ + 0xf3, 0x0f, 0x1e, 0xfa, /* endbr64 */ + 0x68, 0, 0, 0, 0, /* pushq immediate */ + 0xe9, 0, 0, 0, 0, /* jmpq relative */ + 0x66, 0x90 /* xchg %ax,%ax */ +}; + /* Entries in the non-lazey procedure linkage table look like this. */ static const bfd_byte elf_x86_64_non_lazy_plt_entry[NON_LAZY_PLT_ENTRY_SIZE] = @@ -615,6 +641,30 @@ static const bfd_byte elf_x86_64_non_lazy_bnd_plt_entry[NON_LAZY_PLT_ENTRY_SIZE] 0x90 /* nop */ }; +/* Entries for branches with IBT-enabled in the non-lazey procedure + linkage table look like this. They have the same size as the lazy + PLT entry. */ + +static const bfd_byte elf_x86_64_non_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] = +{ + 0xf3, 0x0f, 0x1e, 0xfa, /* endbr64 */ + 0xf2, 0xff, 0x25, /* bnd jmpq *name@GOTPC(%rip) */ + 0, 0, 0, 0, /* replaced with offset to this symbol in .got. */ + 0x0f, 0x1f, 0x44, 0x00, 0x00 /* nopl 0x0(%rax,%rax,1) */ +}; + +/* Entries for branches with IBT-enabled in the x32 non-lazey procedure + linkage table look like this. They have the same size as the lazy + PLT entry. */ + +static const bfd_byte elf_x32_non_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] = +{ + 0xf3, 0x0f, 0x1e, 0xfa, /* endbr64 */ + 0xff, 0x25, /* jmpq *name@GOTPC(%rip) */ + 0, 0, 0, 0, /* replaced with offset to this symbol in .got. */ + 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 /* nopw 0x0(%rax,%rax,1) */ +}; + /* .eh_frame covering the lazy .plt section. */ static const bfd_byte elf_x86_64_eh_frame_lazy_plt[] = @@ -689,6 +739,76 @@ static const bfd_byte elf_x86_64_eh_frame_lazy_bnd_plt[] = DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop }; +/* .eh_frame covering the lazy .plt section with IBT-enabled. */ + +static const bfd_byte elf_x86_64_eh_frame_lazy_ibt_plt[] = +{ + PLT_CIE_LENGTH, 0, 0, 0, /* CIE length */ + 0, 0, 0, 0, /* CIE ID */ + 1, /* CIE version */ + 'z', 'R', 0, /* Augmentation string */ + 1, /* Code alignment factor */ + 0x78, /* Data alignment factor */ + 16, /* Return address column */ + 1, /* Augmentation size */ + DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */ + DW_CFA_def_cfa, 7, 8, /* DW_CFA_def_cfa: r7 (rsp) ofs 8 */ + DW_CFA_offset + 16, 1, /* DW_CFA_offset: r16 (rip) at cfa-8 */ + DW_CFA_nop, DW_CFA_nop, + + PLT_FDE_LENGTH, 0, 0, 0, /* FDE length */ + PLT_CIE_LENGTH + 8, 0, 0, 0, /* CIE pointer */ + 0, 0, 0, 0, /* R_X86_64_PC32 .plt goes here */ + 0, 0, 0, 0, /* .plt size goes here */ + 0, /* Augmentation size */ + DW_CFA_def_cfa_offset, 16, /* DW_CFA_def_cfa_offset: 16 */ + DW_CFA_advance_loc + 6, /* DW_CFA_advance_loc: 6 to __PLT__+6 */ + DW_CFA_def_cfa_offset, 24, /* DW_CFA_def_cfa_offset: 24 */ + DW_CFA_advance_loc + 10, /* DW_CFA_advance_loc: 10 to __PLT__+16 */ + DW_CFA_def_cfa_expression, /* DW_CFA_def_cfa_expression */ + 11, /* Block length */ + DW_OP_breg7, 8, /* DW_OP_breg7 (rsp): 8 */ + DW_OP_breg16, 0, /* DW_OP_breg16 (rip): 0 */ + DW_OP_lit15, DW_OP_and, DW_OP_lit10, DW_OP_ge, + DW_OP_lit3, DW_OP_shl, DW_OP_plus, + DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop +}; + +/* .eh_frame covering the x32 lazy .plt section with IBT-enabled. */ + +static const bfd_byte elf_x32_eh_frame_lazy_ibt_plt[] = +{ + PLT_CIE_LENGTH, 0, 0, 0, /* CIE length */ + 0, 0, 0, 0, /* CIE ID */ + 1, /* CIE version */ + 'z', 'R', 0, /* Augmentation string */ + 1, /* Code alignment factor */ + 0x78, /* Data alignment factor */ + 16, /* Return address column */ + 1, /* Augmentation size */ + DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */ + DW_CFA_def_cfa, 7, 8, /* DW_CFA_def_cfa: r7 (rsp) ofs 8 */ + DW_CFA_offset + 16, 1, /* DW_CFA_offset: r16 (rip) at cfa-8 */ + DW_CFA_nop, DW_CFA_nop, + + PLT_FDE_LENGTH, 0, 0, 0, /* FDE length */ + PLT_CIE_LENGTH + 8, 0, 0, 0, /* CIE pointer */ + 0, 0, 0, 0, /* R_X86_64_PC32 .plt goes here */ + 0, 0, 0, 0, /* .plt size goes here */ + 0, /* Augmentation size */ + DW_CFA_def_cfa_offset, 16, /* DW_CFA_def_cfa_offset: 16 */ + DW_CFA_advance_loc + 6, /* DW_CFA_advance_loc: 6 to __PLT__+6 */ + DW_CFA_def_cfa_offset, 24, /* DW_CFA_def_cfa_offset: 24 */ + DW_CFA_advance_loc + 10, /* DW_CFA_advance_loc: 10 to __PLT__+16 */ + DW_CFA_def_cfa_expression, /* DW_CFA_def_cfa_expression */ + 11, /* Block length */ + DW_OP_breg7, 8, /* DW_OP_breg7 (rsp): 8 */ + DW_OP_breg16, 0, /* DW_OP_breg16 (rip): 0 */ + DW_OP_lit15, DW_OP_and, DW_OP_lit9, DW_OP_ge, + DW_OP_lit3, DW_OP_shl, DW_OP_plus, + DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop +}; + /* .eh_frame covering the non-lazy .plt section. */ static const bfd_byte elf_x86_64_eh_frame_non_lazy_plt[] = @@ -862,6 +982,62 @@ static const struct elf_x86_64_non_lazy_plt_layout elf_x86_64_non_lazy_bnd_plt = sizeof (elf_x86_64_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ }; +static const struct elf_x86_64_lazy_plt_layout elf_x86_64_lazy_ibt_plt = + { + elf_x86_64_lazy_bnd_plt0_entry, /* plt0_entry */ + elf_x86_64_lazy_ibt_plt_entry, /* plt_entry */ + LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + 2, /* plt0_got1_offset */ + 1+8, /* plt0_got2_offset */ + 1+12, /* plt0_got2_insn_end */ + 4+1+2, /* plt_got_offset */ + 4+1, /* plt_reloc_offset */ + 4+1+6, /* plt_plt_offset */ + 4+1+6, /* plt_got_insn_size */ + 4+1+5+5, /* plt_plt_insn_end */ + 0, /* plt_lazy_offset */ + elf_x86_64_eh_frame_lazy_ibt_plt, /* eh_frame_plt */ + sizeof (elf_x86_64_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */ + }; + +static const struct elf_x86_64_lazy_plt_layout elf_x32_lazy_ibt_plt = + { + elf_x86_64_lazy_plt0_entry, /* plt0_entry */ + elf_x32_lazy_ibt_plt_entry, /* plt_entry */ + LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + 2, /* plt0_got1_offset */ + 8, /* plt0_got2_offset */ + 12, /* plt0_got2_insn_end */ + 4+2, /* plt_got_offset */ + 4+1, /* plt_reloc_offset */ + 4+6, /* plt_plt_offset */ + 4+6, /* plt_got_insn_size */ + 4+5+5, /* plt_plt_insn_end */ + 0, /* plt_lazy_offset */ + elf_x32_eh_frame_lazy_ibt_plt, /* eh_frame_plt */ + sizeof (elf_x32_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */ + }; + +static const struct elf_x86_64_non_lazy_plt_layout elf_x86_64_non_lazy_ibt_plt = + { + elf_x86_64_non_lazy_ibt_plt_entry, /* plt_entry */ + LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + 4+1+2, /* plt_got_offset */ + 4+1+6, /* plt_got_insn_size */ + elf_x86_64_eh_frame_non_lazy_plt, /* eh_frame_plt */ + sizeof (elf_x86_64_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ + }; + +static const struct elf_x86_64_non_lazy_plt_layout elf_x32_non_lazy_ibt_plt = + { + elf_x32_non_lazy_ibt_plt_entry, /* plt_entry */ + LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + 4+2, /* plt_got_offset */ + 4+6, /* plt_got_insn_size */ + elf_x86_64_eh_frame_non_lazy_plt, /* eh_frame_plt */ + sizeof (elf_x86_64_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ + }; + static const struct elf_x86_64_backend_data elf_x86_64_arch_bed = { is_normal /* os */ @@ -6508,6 +6684,8 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd, const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt; const struct elf_x86_64_lazy_plt_layout *lazy_bnd_plt; const struct elf_x86_64_non_lazy_plt_layout *non_lazy_bnd_plt; + const struct elf_x86_64_lazy_plt_layout *lazy_ibt_plt; + const struct elf_x86_64_non_lazy_plt_layout *non_lazy_ibt_plt; asection *plt; char *names; enum elf_x86_64_plt_type plt_type; @@ -6548,6 +6726,16 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd, non_lazy_plt = &elf_x86_64_non_lazy_plt; lazy_bnd_plt = &elf_x86_64_lazy_bnd_plt; non_lazy_bnd_plt = &elf_x86_64_non_lazy_bnd_plt; + if (ABI_64_P (abfd)) + { + lazy_ibt_plt = &elf_x86_64_lazy_ibt_plt; + non_lazy_ibt_plt = &elf_x86_64_non_lazy_ibt_plt; + } + else + { + lazy_ibt_plt = &elf_x32_lazy_ibt_plt; + non_lazy_ibt_plt = &elf_x32_non_lazy_ibt_plt; + } } else { @@ -6555,6 +6743,8 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd, non_lazy_plt = NULL; lazy_bnd_plt = NULL; non_lazy_bnd_plt = NULL; + lazy_ibt_plt = NULL; + non_lazy_ibt_plt = NULL; } count = 0; @@ -6593,7 +6783,14 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd, lazy_bnd_plt->plt0_entry + 6, 3) == 0)) { plt_type = plt_lazy | plt_second; - lazy_plt = lazy_bnd_plt; + /* The fist entry in the lazy IBT PLT is the same as the + lazy BND PLT. */ + if ((memcmp (plt_contents + lazy_ibt_plt->plt_entry_size, + lazy_ibt_plt->plt_entry, + lazy_ibt_plt->plt_got_offset) == 0)) + lazy_plt = lazy_ibt_plt; + else + lazy_plt = lazy_bnd_plt; } } @@ -6606,16 +6803,25 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd, plt_type = plt_non_lazy; } - if (non_lazy_bnd_plt != NULL - && (plt_type == plt_unknown || plt_type == plt_second)) + if (plt_type == plt_unknown || plt_type == plt_second) { - /* Match BND PLT. */ - if (memcmp (plt_contents, non_lazy_bnd_plt->plt_entry, - non_lazy_bnd_plt->plt_got_offset) == 0) + if (non_lazy_bnd_plt != NULL + && (memcmp (plt_contents, non_lazy_bnd_plt->plt_entry, + non_lazy_bnd_plt->plt_got_offset) == 0)) { + /* Match BND PLT. */ plt_type = plt_second; non_lazy_plt = non_lazy_bnd_plt; } + else if (non_lazy_ibt_plt != NULL + && (memcmp (plt_contents, + non_lazy_ibt_plt->plt_entry, + non_lazy_ibt_plt->plt_got_offset) == 0)) + { + /* Match IBT PLT. */ + plt_type = plt_second; + non_lazy_plt = non_lazy_ibt_plt; + } } if (plt_type == plt_unknown) @@ -7012,12 +7218,15 @@ elf_x86_64_parse_gnu_properties (bfd *abfd, unsigned int type, { case GNU_PROPERTY_X86_ISA_1_USED: case GNU_PROPERTY_X86_ISA_1_NEEDED: + case GNU_PROPERTY_X86_FEATURE_1_AND: if (datasz != 4) { _bfd_error_handler ((type == GNU_PROPERTY_X86_ISA_1_USED ? _("error: %B: ") - : _("error: %B: ")), + : (type == GNU_PROPERTY_X86_ISA_1_NEEDED + ? _("error: %B: ") + : _("error: %B: "))), abfd, datasz); return property_corrupt; } @@ -7039,12 +7248,12 @@ elf_x86_64_parse_gnu_properties (bfd *abfd, unsigned int type, should be merged with ABFD. */ static bfd_boolean -elf_x86_64_merge_gnu_properties (struct bfd_link_info *info ATTRIBUTE_UNUSED, +elf_x86_64_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd ATTRIBUTE_UNUSED, elf_property *aprop, elf_property *bprop) { - unsigned int number; + unsigned int number, features; bfd_boolean updated = FALSE; unsigned int pr_type = aprop != NULL ? aprop->pr_type : bprop->pr_type; @@ -7066,6 +7275,53 @@ elf_x86_64_merge_gnu_properties (struct bfd_link_info *info ATTRIBUTE_UNUSED, } break; + case GNU_PROPERTY_X86_FEATURE_1_AND: + /* Only one of APROP and BPROP can be NULL: + 1. APROP & BPROP when both APROP and BPROP aren't NULL. + 2. If APROP is NULL, remove x86 feature. + 3. Otherwise, do nothing. + */ + if (aprop != NULL && bprop != NULL) + { + features = 0; + if (info->ibt) + features = GNU_PROPERTY_X86_FEATURE_1_IBT; + number = aprop->u.number; + /* Add GNU_PROPERTY_X86_FEATURE_1_IBT. */ + aprop->u.number = (number & bprop->u.number) | features; + updated = number != (unsigned int) aprop->u.number; + /* Remove the property if all feature bits are cleared. */ + if (aprop->u.number == 0) + aprop->pr_kind = property_remove; + } + else + { + features = 0; + if (info->ibt) + features = GNU_PROPERTY_X86_FEATURE_1_IBT; + if (features) + { + /* Add GNU_PROPERTY_X86_FEATURE_1_IBT. */ + if (aprop != NULL) + { + number = aprop->u.number; + aprop->u.number = number | features; + updated = number != (unsigned int) aprop->u.number; + } + else + { + bprop->u.number |= features; + updated = TRUE; + } + } + else if (aprop != NULL) + { + aprop->pr_kind = property_remove; + updated = TRUE; + } + } + break; + default: /* Never should happen. */ abort (); @@ -7084,9 +7340,69 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info) bfd_boolean lazy_plt; asection *sec, *pltsec; bfd *dynobj; - unsigned int plt_alignment; + bfd_boolean use_ibt_plt; + unsigned int plt_alignment, features; struct elf_x86_64_link_hash_table *htab; - bfd *pbfd = _bfd_elf_link_setup_gnu_properties (info); + bfd *pbfd; + + features = 0; + if (info->ibt) + features = GNU_PROPERTY_X86_FEATURE_1_IBT; + if (features) + { + /* Turn on GNU_PROPERTY_X86_FEATURE_1_IBT. */ + bfd *ebfd = NULL; + elf_property *prop; + + for (pbfd = info->input_bfds; + pbfd != NULL; + pbfd = pbfd->link.next) + if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour + && bfd_count_sections (pbfd) != 0) + { + ebfd = pbfd; + + if (elf_properties (pbfd) != NULL) + { + /* Find a normal input file with GNU property note. */ + prop = _bfd_elf_get_property (pbfd, + GNU_PROPERTY_X86_FEATURE_1_AND, + 4); + /* Add GNU_PROPERTY_X86_FEATURE_1_IBT. */ + prop->u.number |= features; + prop->pr_kind = property_number; + break; + } + } + + if (pbfd == NULL && ebfd != NULL) + { + /* Create GNU_PROPERTY_X86_FEATURE_1_IBT if needed. */ + prop = _bfd_elf_get_property (ebfd, + GNU_PROPERTY_X86_FEATURE_1_AND, + 4); + prop->u.number = features; + prop->pr_kind = property_number; + + sec = bfd_make_section_with_flags (ebfd, + NOTE_GNU_PROPERTY_SECTION_NAME, + (SEC_ALLOC + | SEC_LOAD + | SEC_IN_MEMORY + | SEC_READONLY + | SEC_HAS_CONTENTS + | SEC_DATA)); + if (sec == NULL) + info->callbacks->einfo (_("%F: failed to create GNU property section\n")); + + if (!bfd_set_section_alignment (ebfd, sec, 2)) + goto error_alignment; + + elf_section_type (sec) = SHT_NOTE; + } + } + + pbfd = _bfd_elf_link_setup_gnu_properties (info); if (bfd_link_relocatable (info)) return pbfd; @@ -7095,26 +7411,54 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info) if (htab == NULL) return pbfd; + use_ibt_plt = info->ibtplt || info->ibt; + if (!use_ibt_plt && pbfd != NULL) + { + /* Check if GNU_PROPERTY_X86_FEATURE_1_IBT is on. */ + elf_property_list *p; + + /* The property list is sorted in order of type. */ + for (p = elf_properties (pbfd); p; p = p->next) + { + if (GNU_PROPERTY_X86_FEATURE_1_AND == p->property.pr_type) + { + use_ibt_plt = !!(p->property.u.number + & GNU_PROPERTY_X86_FEATURE_1_IBT); + break; + } + else if (GNU_PROPERTY_X86_FEATURE_1_AND < p->property.pr_type) + break; + } + } + dynobj = htab->elf.dynobj; /* Set htab->elf.dynobj here so that there is no need to check and set it in check_relocs. */ if (dynobj == NULL) { - bfd *abfd; - - /* Find a normal input file to hold linker created - sections. */ - for (abfd = info->input_bfds; - abfd != NULL; - abfd = abfd->link.next) - if ((abfd->flags - & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0) - { - htab->elf.dynobj = abfd; - dynobj = abfd; - break; - } + if (pbfd != NULL) + { + htab->elf.dynobj = pbfd; + dynobj = pbfd; + } + else + { + bfd *abfd; + + /* Find a normal input file to hold linker created + sections. */ + for (abfd = info->input_bfds; + abfd != NULL; + abfd = abfd->link.next) + if ((abfd->flags + & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0) + { + htab->elf.dynobj = abfd; + dynobj = abfd; + break; + } + } } /* Even when lazy binding is disabled by "-z now", the PLT0 entry may @@ -7125,7 +7469,20 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info) if (get_elf_x86_64_backend_data (info->output_bfd)->os == is_normal) { - if (info->bndplt) + if (use_ibt_plt) + { + if (ABI_64_P (dynobj)) + { + htab->lazy_plt = &elf_x86_64_lazy_ibt_plt; + htab->non_lazy_plt = &elf_x86_64_non_lazy_ibt_plt; + } + else + { + htab->lazy_plt = &elf_x32_lazy_ibt_plt; + htab->non_lazy_plt = &elf_x32_non_lazy_ibt_plt; + } + } + else if (info->bndplt) { htab->lazy_plt = &elf_x86_64_lazy_bnd_plt; htab->non_lazy_plt = &elf_x86_64_non_lazy_bnd_plt; @@ -7262,21 +7619,40 @@ error_alignment: htab->plt_got = sec; - /* MPX PLT is supported only for non-NaCl target in 64-bit - mode and is needed only for lazy binding. */ - if (lazy_plt - && info->bndplt && ABI_64_P (dynobj)) + if (lazy_plt) { - /* Create the second PLT for Intel MPX support. */ - sec = bfd_make_section_anyway_with_flags (dynobj, - ".plt.sec", - pltflags); - if (sec == NULL) - info->callbacks->einfo (_("%F: failed to create BND PLT section\n")); + sec = NULL; - if (!bfd_set_section_alignment (dynobj, sec, - non_lazy_plt_alignment)) - goto error_alignment; + if (use_ibt_plt) + { + /* Create the second PLT for Intel IBT support. IBT + PLT is supported only for non-NaCl target and is + is needed only for lazy binding. */ + sec = bfd_make_section_anyway_with_flags (dynobj, + ".plt.sec", + pltflags); + if (sec == NULL) + info->callbacks->einfo (_("%F: failed to create IBT-enabled PLT section\n")); + + if (!bfd_set_section_alignment (dynobj, sec, + plt_alignment)) + goto error_alignment; + } + else if (info->bndplt && ABI_64_P (dynobj)) + { + /* Create the second PLT for Intel MPX support. MPX + PLT is supported only for non-NaCl target in 64-bit + mode and is needed only for lazy binding. */ + sec = bfd_make_section_anyway_with_flags (dynobj, + ".plt.sec", + pltflags); + if (sec == NULL) + info->callbacks->einfo (_("%F: failed to create BND PLT section\n")); + + if (!bfd_set_section_alignment (dynobj, sec, + non_lazy_plt_alignment)) + goto error_alignment; + } htab->plt_second = sec; } diff --git a/binutils/ChangeLog b/binutils/ChangeLog index a9166debf15..3870711754e 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,19 @@ +2017-06-22 H.J. Lu + + * 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 * dwarf.c (READ_ULEB): Use DWARF_VMA_FMT to report error. diff --git a/binutils/readelf.c b/binutils/readelf.c index bb6bb79d4e0..50354c1bd22 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -16337,6 +16337,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 (_(""), bit); + break; + } + if (bitmask) + printf (", "); + } +} + static void print_gnu_property_note (Elf_Internal_Note * pnote) { @@ -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 (_(" "), 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 00000000000..5f4cc5632e3 --- /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 00000000000..6a6b517fd07 --- /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 00000000000..dfd76760029 --- /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 00000000000..84ee9641369 --- /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 00000000000..4193818a91e --- /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 00000000000..777efbb1e05 --- /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 00000000000..6a6b517fd07 --- /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 00000000000..5be7c98e076 --- /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 00000000000..7bedff50325 --- /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 00000000000..84ee9641369 --- /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: diff --git a/include/ChangeLog b/include/ChangeLog index b48df0913ff..4858699a7ee 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,9 @@ +2017-06-22 H.J. Lu + + * 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. + 2017-06-21 Thomas Preud'homme * opcode/arm.h (FPU_ANY): New macro. diff --git a/include/bfdlink.h b/include/bfdlink.h index 69232c45491..3b4dce9ca61 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -471,6 +471,12 @@ struct bfd_link_info /* TRUE if BND prefix in PLT entries is always generated. */ unsigned int bndplt: 1; + /* TRUE if IBT-enabled PLT entries should be generated. */ + unsigned int ibtplt: 1; + + /* TRUE if GNU_PROPERTY_X86_FEATURE_1_IBT should be generated. */ + unsigned int ibt: 1; + /* TRUE if generation of .interp/PT_INTERP should be suppressed. */ unsigned int nointerp: 1; diff --git a/include/elf/common.h b/include/elf/common.h index 484cb48f96e..e638ba09ae6 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -709,6 +709,7 @@ #define GNU_PROPERTY_X86_ISA_1_USED 0xc0000000 #define GNU_PROPERTY_X86_ISA_1_NEEDED 0xc0000001 +#define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 #define GNU_PROPERTY_X86_ISA_1_486 (1U << 0) #define GNU_PROPERTY_X86_ISA_1_586 (1U << 1) @@ -729,6 +730,8 @@ #define GNU_PROPERTY_X86_ISA_1_AVX512DQ (1U << 16) #define GNU_PROPERTY_X86_ISA_1_AVX512BW (1U << 17) +#define GNU_PROPERTY_X86_FEATURE_1_IBT (1U << 0) + /* Values used in GNU .note.ABI-tag notes (NT_GNU_ABI_TAG). */ #define GNU_ABI_TAG_LINUX 0 #define GNU_ABI_TAG_HURD 1 diff --git a/ld/ChangeLog b/ld/ChangeLog index 94af73dfaab..b3567e112ec 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,82 @@ +2017-06-22 H.J. Lu + + * 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. + 2017-06-21 H.J. Lu PR ld/21090 diff --git a/ld/Makefile.am b/ld/Makefile.am index b509e236e8f..fcd4c363959 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -677,7 +677,8 @@ ELF_X86_DEPS = $(ELF_DEPS) $(srcdir)/emulparams/plt_unwind.sh \ $(srcdir)/emulparams/extern_protected_data.sh \ $(srcdir)/emulparams/dynamic_undefined_weak.sh \ $(srcdir)/emulparams/reloc_overflow.sh \ - $(srcdir)/emulparams/call_nop.sh + $(srcdir)/emulparams/call_nop.sh \ + $(srcdir)/emulparams/cet.sh @TDIRS@ diff --git a/ld/Makefile.in b/ld/Makefile.in index b69d6b86c1f..5e66e02aafc 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -932,7 +932,8 @@ ELF_X86_DEPS = $(ELF_DEPS) $(srcdir)/emulparams/plt_unwind.sh \ $(srcdir)/emulparams/extern_protected_data.sh \ $(srcdir)/emulparams/dynamic_undefined_weak.sh \ $(srcdir)/emulparams/reloc_overflow.sh \ - $(srcdir)/emulparams/call_nop.sh + $(srcdir)/emulparams/call_nop.sh \ + $(srcdir)/emulparams/cet.sh # We need this for automake to use YLWRAP. diff --git a/ld/NEWS b/ld/NEWS index 98055b5f4ed..b1158431465 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -1,5 +1,14 @@ -*- text -*- +* Add support for GNU_PROPERTY_X86_FEATURE_1_IBT in ELF GNU program + +* Support for -z ibtplt in the x86 ELF linker to generate IBT-enabled + PLT. + +* Support for -z ibt in the x86 ELF linker to generate IBT-enabled + PLT as well as GNU_PROPERTY_X86_FEATURE_1_IBT in ELF GNU program + properties. + * Add support for ELF SHF_GNU_MBIND and PT_GNU_MBIND_XXX. * Add support for ELF GNU program properties. diff --git a/ld/emulparams/cet.sh b/ld/emulparams/cet.sh new file mode 100644 index 00000000000..62ff105613f --- /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 9b8523947ec..06a0f3c6fe5 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 b08e6610d0b..6997d40ba1c 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 ca6d06cef7e..ad255266fce 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" diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 44ad84b3517..4f7873cd905 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -1261,6 +1261,15 @@ to a locally defined function, foo, via its GOT slot. @option{call-nop=suffix-@var{byte}} generates @code{call foo @var{byte}}. Supported for i386 and x86_64. +@item ibtplt +Generate Intel Indirect Branch Tracking (IBT) enabled PLT entries. +Supported for Linux/i386 and Linux/x86_64. + +@item IBT +Generate GNU_PROPERTY_X86_FEATURE_1_IBT in .note.gnu.property section +to indicate compatibility with IBT. This also implies @option{ibtplt}. +Supported for Linux/i386 and Linux/x86_64. + @end table Other keywords are ignored for Solaris compatibility. diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp index 2e3c2249f51..d30dc767036 100644 --- a/ld/testsuite/ld-i386/i386.exp +++ b/ld/testsuite/ld-i386/i386.exp @@ -420,6 +420,13 @@ run_dump_test "pr20515" run_dump_test "property-x86-3" run_dump_test "property-x86-4a" run_dump_test "property-x86-4b" +run_dump_test "property-x86-ibt1a" +run_dump_test "property-x86-ibt1b" +run_dump_test "property-x86-ibt2" +run_dump_test "property-x86-ibt3a" +run_dump_test "property-x86-ibt3b" +run_dump_test "property-x86-ibt4" +run_dump_test "property-x86-ibt5" if { !([istarget "i?86-*-linux*"] || [istarget "i?86-*-gnu*"] @@ -1100,6 +1107,8 @@ if { [isnative] undefined_weak "-fPIE" "-pie -z nodynamic-undefined-weak" } +global NOPIE_LDFLAGS + # Must be native with the C compiler and working IFUNC support, if { [isnative] && [check_ifunc_available] @@ -1156,6 +1165,66 @@ if { [isnative] "pass.out" \ ] \ ] + + if { [istarget "i?86-*-linux*"] } { + run_cc_link_tests [list \ + [list \ + "Build pr21168.so with -z ibtplt" \ + "-shared -Wl,-z,ibtplt" \ + "" \ + { pr21168b.S } \ + "" \ + "pr21168-ibt.so" \ + ] \ + [list \ + "Build ifunc-1a with -z ibtplt" \ + "-Wl,-z,ibtplt $NOPIE_LDFLAGS tmpdir/ifunc-1a.o \ + tmpdir/ifunc-1b.o tmpdir/ifunc-1c.o tmpdir/ifunc-1d.o" \ + "" \ + { dummy.c } \ + {{objdump {-dw} plt-main-ibt.dd}} \ + "ifunc-1a-ibt" \ + ] \ + [list \ + "Build ifunc-1a with PIE -z ibtplt" \ + "-Wl,-z,ibtplt -pie tmpdir/ifunc-1a.o \ + tmpdir/ifunc-1b.o tmpdir/ifunc-1c.o tmpdir/ifunc-1d.o" \ + "" \ + { dummy.c } \ + {{objdump {-dw} plt-pie-ibt.dd}} \ + "ifunc-1a-pie-ibt" \ + ] \ + ] + + run_ld_link_exec_tests [list \ + [list \ + "Run ifunc-1a with -z ibtplt" \ + "-Wl,-z,ibtplt $NOPIE_LDFLAGS tmpdir/ifunc-1a.o \ + tmpdir/ifunc-1b.o tmpdir/ifunc-1c.o tmpdir/ifunc-1d.o" \ + "" \ + { dummy.c } \ + "ifunc-1a-ibt" \ + "pass.out" \ + ] \ + [list \ + "Run ifunc-1a with PIE -z ibtplt" \ + "-Wl,-z,ibtplt -pie tmpdir/ifunc-1a.o \ + tmpdir/ifunc-1b.o tmpdir/ifunc-1c.o tmpdir/ifunc-1d.o" \ + "" \ + { dummy.c } \ + "ifunc-1a-pie-ibt" \ + "pass.out" \ + ] \ + [list \ + "Run pr21168 with -z ibtplt" \ + "tmpdir/pr21168a.o tmpdir/pr21168-ibt.so" \ + "" \ + { dummy.c } \ + "pr21168-ibt" \ + "pass.out" \ + ] \ + ] + } } if { !([istarget "i?86-*-linux*"] @@ -1206,3 +1275,12 @@ run_ld_link_tests [list \ run_dump_test "pltgot-1" run_dump_test "pltgot-2" run_dump_test "pr20830" +run_dump_test "ibt-plt-1" +run_dump_test "ibt-plt-2a" +run_dump_test "ibt-plt-2b" +run_dump_test "ibt-plt-2c" +run_dump_test "ibt-plt-2d" +run_dump_test "ibt-plt-3a" +run_dump_test "ibt-plt-3b" +run_dump_test "ibt-plt-3c" +run_dump_test "ibt-plt-3d" diff --git a/ld/testsuite/ld-i386/ibt-plt-1.d b/ld/testsuite/ld-i386/ibt-plt-1.d new file mode 100644 index 00000000000..1c905915e49 --- /dev/null +++ b/ld/testsuite/ld-i386/ibt-plt-1.d @@ -0,0 +1,51 @@ +#as: --32 +#ld: -shared -m elf_i386 +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+1b0 <.plt>: + +[a-f0-9]+: ff b3 04 00 00 00 pushl 0x4\(%ebx\) + +[a-f0-9]+: ff a3 08 00 00 00 jmp \*0x8\(%ebx\) + +[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%eax\) + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: 68 00 00 00 00 push \$0x0 + +[a-f0-9]+: e9 e2 ff ff ff jmp 1b0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: 68 08 00 00 00 push \$0x8 + +[a-f0-9]+: e9 d2 ff ff ff jmp 1b0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +Disassembly of section .plt.sec: + +0+1e0 : + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: ff a3 0c 00 00 00 jmp \*0xc\(%ebx\) + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%eax,%eax,1\) + +0+1f0 : + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: ff a3 10 00 00 00 jmp \*0x10\(%ebx\) + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%eax,%eax,1\) + +Disassembly of section .text: + +0+200 : + +[a-f0-9]+: 53 push %ebx + +[a-f0-9]+: e8 18 00 00 00 call 21e <__x86.get_pc_thunk.bx> + +[a-f0-9]+: 81 c3 22 11 00 00 add \$0x1122,%ebx + +[a-f0-9]+: 83 ec 08 sub \$0x8,%esp + +[a-f0-9]+: e8 dc ff ff ff call 1f0 + +[a-f0-9]+: e8 c7 ff ff ff call 1e0 + +[a-f0-9]+: 83 c4 08 add \$0x8,%esp + +[a-f0-9]+: 5b pop %ebx + +[a-f0-9]+: c3 ret + +0+21e <__x86.get_pc_thunk.bx>: + +[a-f0-9]+: 8b 1c 24 mov \(%esp\),%ebx + +[a-f0-9]+: c3 ret +#pass diff --git a/ld/testsuite/ld-i386/ibt-plt-1.s b/ld/testsuite/ld-i386/ibt-plt-1.s new file mode 100644 index 00000000000..80e2311de9e --- /dev/null +++ b/ld/testsuite/ld-i386/ibt-plt-1.s @@ -0,0 +1,54 @@ + .text + .p2align 4,,15 + .globl foo + .type foo, @function +foo: +.LFB0: + .cfi_startproc + pushl %ebx + .cfi_def_cfa_offset 8 + .cfi_offset 3, -8 + call __x86.get_pc_thunk.bx + addl $_GLOBAL_OFFSET_TABLE_, %ebx + subl $8, %esp + .cfi_def_cfa_offset 16 + call bar2@PLT + call bar1@PLT + addl $8, %esp + .cfi_def_cfa_offset 8 + popl %ebx + .cfi_restore 3 + .cfi_def_cfa_offset 4 + ret + .cfi_endproc +.LFE0: + .size foo, .-foo + .section .note.GNU-stack,"",@progbits + + .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat + .globl __x86.get_pc_thunk.bx + .hidden __x86.get_pc_thunk.bx + .type __x86.get_pc_thunk.bx, @function +__x86.get_pc_thunk.bx: +.LFB1: + .cfi_startproc + movl (%esp), %ebx + ret + .cfi_endproc +.LFE1: + + .section ".note.gnu.property", "a" + .p2align 2 + .long 1f - 0f /* name length */ + .long 5f - 2f /* data length */ + .long 5 /* note type */ +0: .asciz "GNU" /* vendor name */ +1: + .p2align 2 +2: .long 0xc0000002 /* pr_type. */ + .long 4f - 3f /* pr_datasz. */ +3: + .long 0x1 +4: + .p2align 2 +5: diff --git a/ld/testsuite/ld-i386/ibt-plt-2.s b/ld/testsuite/ld-i386/ibt-plt-2.s new file mode 100644 index 00000000000..500fdd28f9a --- /dev/null +++ b/ld/testsuite/ld-i386/ibt-plt-2.s @@ -0,0 +1,54 @@ + .text + .p2align 4,,15 + .globl foo + .type foo, @function +foo: +.LFB0: + .cfi_startproc + pushl %ebx + .cfi_def_cfa_offset 8 + .cfi_offset 3, -8 + call __x86.get_pc_thunk.bx + addl $_GLOBAL_OFFSET_TABLE_, %ebx + subl $8, %esp + .cfi_def_cfa_offset 16 + call bar2@PLT + call bar1@PLT + addl $8, %esp + .cfi_def_cfa_offset 8 + popl %ebx + .cfi_restore 3 + .cfi_def_cfa_offset 4 + ret + .cfi_endproc +.LFE0: + .size foo, .-foo + .section .note.GNU-stack,"",@progbits + + .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat + .globl __x86.get_pc_thunk.bx + .hidden __x86.get_pc_thunk.bx + .type __x86.get_pc_thunk.bx, @function +__x86.get_pc_thunk.bx: +.LFB1: + .cfi_startproc + movl (%esp), %ebx + ret + .cfi_endproc +.LFE1: + + .section ".note.gnu.property", "a" + .p2align 2 + .long 1f - 0f /* name length */ + .long 5f - 2f /* data length */ + .long 5 /* note type */ +0: .asciz "GNU" /* vendor name */ +1: + .p2align 2 +2: .long 0xc0000002 /* pr_type. */ + .long 4f - 3f /* pr_datasz. */ +3: + .long 0x0 +4: + .p2align 2 +5: diff --git a/ld/testsuite/ld-i386/ibt-plt-2a.d b/ld/testsuite/ld-i386/ibt-plt-2a.d new file mode 100644 index 00000000000..4881dea1c47 --- /dev/null +++ b/ld/testsuite/ld-i386/ibt-plt-2a.d @@ -0,0 +1,52 @@ +#source: ibt-plt-2.s +#as: --32 +#ld: -shared -m elf_i386 -z ibtplt +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+1b0 <.plt>: + +[a-f0-9]+: ff b3 04 00 00 00 pushl 0x4\(%ebx\) + +[a-f0-9]+: ff a3 08 00 00 00 jmp \*0x8\(%ebx\) + +[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%eax\) + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: 68 00 00 00 00 push \$0x0 + +[a-f0-9]+: e9 e2 ff ff ff jmp 1b0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: 68 08 00 00 00 push \$0x8 + +[a-f0-9]+: e9 d2 ff ff ff jmp 1b0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +Disassembly of section .plt.sec: + +0+1e0 : + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: ff a3 0c 00 00 00 jmp \*0xc\(%ebx\) + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%eax,%eax,1\) + +0+1f0 : + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: ff a3 10 00 00 00 jmp \*0x10\(%ebx\) + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%eax,%eax,1\) + +Disassembly of section .text: + +0+200 : + +[a-f0-9]+: 53 push %ebx + +[a-f0-9]+: e8 18 00 00 00 call 21e <__x86.get_pc_thunk.bx> + +[a-f0-9]+: 81 c3 22 11 00 00 add \$0x1122,%ebx + +[a-f0-9]+: 83 ec 08 sub \$0x8,%esp + +[a-f0-9]+: e8 dc ff ff ff call 1f0 + +[a-f0-9]+: e8 c7 ff ff ff call 1e0 + +[a-f0-9]+: 83 c4 08 add \$0x8,%esp + +[a-f0-9]+: 5b pop %ebx + +[a-f0-9]+: c3 ret + +0+21e <__x86.get_pc_thunk.bx>: + +[a-f0-9]+: 8b 1c 24 mov \(%esp\),%ebx + +[a-f0-9]+: c3 ret +#pass diff --git a/ld/testsuite/ld-i386/ibt-plt-2b.d b/ld/testsuite/ld-i386/ibt-plt-2b.d new file mode 100644 index 00000000000..740b889b98d --- /dev/null +++ b/ld/testsuite/ld-i386/ibt-plt-2b.d @@ -0,0 +1,9 @@ +#source: ibt-plt-2.s +#as: --32 +#ld: -shared -m elf_i386 -z ibtplt +#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/ld/testsuite/ld-i386/ibt-plt-2c.d b/ld/testsuite/ld-i386/ibt-plt-2c.d new file mode 100644 index 00000000000..2ba1d78c54b --- /dev/null +++ b/ld/testsuite/ld-i386/ibt-plt-2c.d @@ -0,0 +1,52 @@ +#source: ibt-plt-2.s +#as: --32 +#ld: -shared -m elf_i386 -z ibt +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+1b0 <.plt>: + +[a-f0-9]+: ff b3 04 00 00 00 pushl 0x4\(%ebx\) + +[a-f0-9]+: ff a3 08 00 00 00 jmp \*0x8\(%ebx\) + +[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%eax\) + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: 68 00 00 00 00 push \$0x0 + +[a-f0-9]+: e9 e2 ff ff ff jmp 1b0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: 68 08 00 00 00 push \$0x8 + +[a-f0-9]+: e9 d2 ff ff ff jmp 1b0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +Disassembly of section .plt.sec: + +0+1e0 : + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: ff a3 0c 00 00 00 jmp \*0xc\(%ebx\) + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%eax,%eax,1\) + +0+1f0 : + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: ff a3 10 00 00 00 jmp \*0x10\(%ebx\) + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%eax,%eax,1\) + +Disassembly of section .text: + +0+200 : + +[a-f0-9]+: 53 push %ebx + +[a-f0-9]+: e8 18 00 00 00 call 21e <__x86.get_pc_thunk.bx> + +[a-f0-9]+: 81 c3 22 11 00 00 add \$0x1122,%ebx + +[a-f0-9]+: 83 ec 08 sub \$0x8,%esp + +[a-f0-9]+: e8 dc ff ff ff call 1f0 + +[a-f0-9]+: e8 c7 ff ff ff call 1e0 + +[a-f0-9]+: 83 c4 08 add \$0x8,%esp + +[a-f0-9]+: 5b pop %ebx + +[a-f0-9]+: c3 ret + +0+21e <__x86.get_pc_thunk.bx>: + +[a-f0-9]+: 8b 1c 24 mov \(%esp\),%ebx + +[a-f0-9]+: c3 ret +#pass diff --git a/ld/testsuite/ld-i386/ibt-plt-2d.d b/ld/testsuite/ld-i386/ibt-plt-2d.d new file mode 100644 index 00000000000..3e02a62464e --- /dev/null +++ b/ld/testsuite/ld-i386/ibt-plt-2d.d @@ -0,0 +1,9 @@ +#source: ibt-plt-2.s +#as: --32 +#ld: -shared -m elf_i386 -z ibt +#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/ld/testsuite/ld-i386/ibt-plt-3.s b/ld/testsuite/ld-i386/ibt-plt-3.s new file mode 100644 index 00000000000..b52f2e7383e --- /dev/null +++ b/ld/testsuite/ld-i386/ibt-plt-3.s @@ -0,0 +1,38 @@ + .text + .p2align 4,,15 + .globl foo + .type foo, @function +foo: +.LFB0: + .cfi_startproc + pushl %ebx + .cfi_def_cfa_offset 8 + .cfi_offset 3, -8 + call __x86.get_pc_thunk.bx + addl $_GLOBAL_OFFSET_TABLE_, %ebx + subl $8, %esp + .cfi_def_cfa_offset 16 + call bar2@PLT + call bar1@PLT + addl $8, %esp + .cfi_def_cfa_offset 8 + popl %ebx + .cfi_restore 3 + .cfi_def_cfa_offset 4 + ret + .cfi_endproc +.LFE0: + .size foo, .-foo + .section .note.GNU-stack,"",@progbits + + .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat + .globl __x86.get_pc_thunk.bx + .hidden __x86.get_pc_thunk.bx + .type __x86.get_pc_thunk.bx, @function +__x86.get_pc_thunk.bx: +.LFB1: + .cfi_startproc + movl (%esp), %ebx + ret + .cfi_endproc +.LFE1: diff --git a/ld/testsuite/ld-i386/ibt-plt-3a.d b/ld/testsuite/ld-i386/ibt-plt-3a.d new file mode 100644 index 00000000000..c2ce3fd6fcd --- /dev/null +++ b/ld/testsuite/ld-i386/ibt-plt-3a.d @@ -0,0 +1,52 @@ +#source: ibt-plt-3.s +#as: --32 +#ld: -shared -m elf_i386 -z ibtplt +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+190 <.plt>: + +[a-f0-9]+: ff b3 04 00 00 00 pushl 0x4\(%ebx\) + +[a-f0-9]+: ff a3 08 00 00 00 jmp \*0x8\(%ebx\) + +[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%eax\) + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: 68 00 00 00 00 push \$0x0 + +[a-f0-9]+: e9 e2 ff ff ff jmp 190 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: 68 08 00 00 00 push \$0x8 + +[a-f0-9]+: e9 d2 ff ff ff jmp 190 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +Disassembly of section .plt.sec: + +0+1c0 : + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: ff a3 0c 00 00 00 jmp \*0xc\(%ebx\) + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%eax,%eax,1\) + +0+1d0 : + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: ff a3 10 00 00 00 jmp \*0x10\(%ebx\) + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%eax,%eax,1\) + +Disassembly of section .text: + +0+1e0 : + +[a-f0-9]+: 53 push %ebx + +[a-f0-9]+: e8 18 00 00 00 call 1fe <__x86.get_pc_thunk.bx> + +[a-f0-9]+: 81 c3 06 11 00 00 add \$0x1106,%ebx + +[a-f0-9]+: 83 ec 08 sub \$0x8,%esp + +[a-f0-9]+: e8 dc ff ff ff call 1d0 + +[a-f0-9]+: e8 c7 ff ff ff call 1c0 + +[a-f0-9]+: 83 c4 08 add \$0x8,%esp + +[a-f0-9]+: 5b pop %ebx + +[a-f0-9]+: c3 ret + +0+1fe <__x86.get_pc_thunk.bx>: + +[a-f0-9]+: 8b 1c 24 mov \(%esp\),%ebx + +[a-f0-9]+: c3 ret +#pass diff --git a/ld/testsuite/ld-i386/ibt-plt-3b.d b/ld/testsuite/ld-i386/ibt-plt-3b.d new file mode 100644 index 00000000000..d9b5be231bc --- /dev/null +++ b/ld/testsuite/ld-i386/ibt-plt-3b.d @@ -0,0 +1,5 @@ +#source: ibt-plt-3.s +#as: --32 +#ld: -shared -m elf_i386 -z ibtplt +#readelf: -n + diff --git a/ld/testsuite/ld-i386/ibt-plt-3c.d b/ld/testsuite/ld-i386/ibt-plt-3c.d new file mode 100644 index 00000000000..c2ce3fd6fcd --- /dev/null +++ b/ld/testsuite/ld-i386/ibt-plt-3c.d @@ -0,0 +1,52 @@ +#source: ibt-plt-3.s +#as: --32 +#ld: -shared -m elf_i386 -z ibtplt +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+190 <.plt>: + +[a-f0-9]+: ff b3 04 00 00 00 pushl 0x4\(%ebx\) + +[a-f0-9]+: ff a3 08 00 00 00 jmp \*0x8\(%ebx\) + +[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%eax\) + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: 68 00 00 00 00 push \$0x0 + +[a-f0-9]+: e9 e2 ff ff ff jmp 190 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: 68 08 00 00 00 push \$0x8 + +[a-f0-9]+: e9 d2 ff ff ff jmp 190 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +Disassembly of section .plt.sec: + +0+1c0 : + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: ff a3 0c 00 00 00 jmp \*0xc\(%ebx\) + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%eax,%eax,1\) + +0+1d0 : + +[a-f0-9]+: f3 0f 1e fb endbr32 + +[a-f0-9]+: ff a3 10 00 00 00 jmp \*0x10\(%ebx\) + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%eax,%eax,1\) + +Disassembly of section .text: + +0+1e0 : + +[a-f0-9]+: 53 push %ebx + +[a-f0-9]+: e8 18 00 00 00 call 1fe <__x86.get_pc_thunk.bx> + +[a-f0-9]+: 81 c3 06 11 00 00 add \$0x1106,%ebx + +[a-f0-9]+: 83 ec 08 sub \$0x8,%esp + +[a-f0-9]+: e8 dc ff ff ff call 1d0 + +[a-f0-9]+: e8 c7 ff ff ff call 1c0 + +[a-f0-9]+: 83 c4 08 add \$0x8,%esp + +[a-f0-9]+: 5b pop %ebx + +[a-f0-9]+: c3 ret + +0+1fe <__x86.get_pc_thunk.bx>: + +[a-f0-9]+: 8b 1c 24 mov \(%esp\),%ebx + +[a-f0-9]+: c3 ret +#pass diff --git a/ld/testsuite/ld-i386/ibt-plt-3d.d b/ld/testsuite/ld-i386/ibt-plt-3d.d new file mode 100644 index 00000000000..3cf159aba80 --- /dev/null +++ b/ld/testsuite/ld-i386/ibt-plt-3d.d @@ -0,0 +1,9 @@ +#source: ibt-plt-3.s +#as: --32 +#ld: -shared -m elf_i386 -z ibt +#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/ld/testsuite/ld-i386/plt-main-ibt.dd b/ld/testsuite/ld-i386/plt-main-ibt.dd new file mode 100644 index 00000000000..18240a26f00 --- /dev/null +++ b/ld/testsuite/ld-i386/plt-main-ibt.dd @@ -0,0 +1,7 @@ +#... +Disassembly of section .plt.got: + +[a-f0-9]+ <[_a-z]+@plt>: +[ ]*[a-f0-9]+: f3 0f 1e fb endbr32 +[ ]*[a-f0-9]+: ff 25 .. .. .. .. jmp +\*0x[a-f0-9]+ +#pass diff --git a/ld/testsuite/ld-i386/plt-pie-ibt.dd b/ld/testsuite/ld-i386/plt-pie-ibt.dd new file mode 100644 index 00000000000..2dc016c3b24 --- /dev/null +++ b/ld/testsuite/ld-i386/plt-pie-ibt.dd @@ -0,0 +1,7 @@ +#... +Disassembly of section .plt.got: + +[a-f0-9]+ <[_a-z]+@plt>: +[ ]*[a-f0-9]+: f3 0f 1e fb endbr32 +[ ]*[a-f0-9]+: ff a3 .. .. .. .. jmp +\*\-0x[a-f0-9]+\(%ebx\) +#pass diff --git a/ld/testsuite/ld-i386/property-x86-empty.s b/ld/testsuite/ld-i386/property-x86-empty.s new file mode 100644 index 00000000000..6a6b517fd07 --- /dev/null +++ b/ld/testsuite/ld-i386/property-x86-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/ld/testsuite/ld-i386/property-x86-ibt.s b/ld/testsuite/ld-i386/property-x86-ibt.s new file mode 100644 index 00000000000..84ee9641369 --- /dev/null +++ b/ld/testsuite/ld-i386/property-x86-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/ld/testsuite/ld-i386/property-x86-ibt1a.d b/ld/testsuite/ld-i386/property-x86-ibt1a.d new file mode 100644 index 00000000000..43b272f7622 --- /dev/null +++ b/ld/testsuite/ld-i386/property-x86-ibt1a.d @@ -0,0 +1,6 @@ +#source: property-x86-empty.s +#source: property-x86-ibt.s +#as: --32 +#ld: -r -melf_i386 +#readelf: -n + diff --git a/ld/testsuite/ld-i386/property-x86-ibt1b.d b/ld/testsuite/ld-i386/property-x86-ibt1b.d new file mode 100644 index 00000000000..83bf4117f69 --- /dev/null +++ b/ld/testsuite/ld-i386/property-x86-ibt1b.d @@ -0,0 +1,6 @@ +#source: property-x86-ibt.s +#source: property-x86-empty.s +#as: --32 +#ld: -r -melf_i386 +#readelf: -n + diff --git a/ld/testsuite/ld-i386/property-x86-ibt2.d b/ld/testsuite/ld-i386/property-x86-ibt2.d new file mode 100644 index 00000000000..fbdf4c17a87 --- /dev/null +++ b/ld/testsuite/ld-i386/property-x86-ibt2.d @@ -0,0 +1,9 @@ +#source: property-x86-ibt.s +#as: --32 +#ld: -r -melf_i386 +#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/ld/testsuite/ld-i386/property-x86-ibt3a.d b/ld/testsuite/ld-i386/property-x86-ibt3a.d new file mode 100644 index 00000000000..4bb35b00fb5 --- /dev/null +++ b/ld/testsuite/ld-i386/property-x86-ibt3a.d @@ -0,0 +1,11 @@ +#source: property-x86-3.s +#source: property-x86-ibt.s +#as: --32 +#ld: -r -melf_i386 +#readelf: -n + +Displaying notes found in: .note.gnu.property + Owner Data size Description + GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0 + Properties: x86 ISA used: i486, 586, SSE2, SSE3 + x86 ISA needed: 586, SSE, SSE3, SSE4_1 diff --git a/ld/testsuite/ld-i386/property-x86-ibt3b.d b/ld/testsuite/ld-i386/property-x86-ibt3b.d new file mode 100644 index 00000000000..418d58a8f74 --- /dev/null +++ b/ld/testsuite/ld-i386/property-x86-ibt3b.d @@ -0,0 +1,11 @@ +#source: property-x86-ibt.s +#source: property-x86-3.s +#as: --32 +#ld: -r -melf_i386 +#readelf: -n + +Displaying notes found in: .note.gnu.property + Owner Data size Description + GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0 + Properties: x86 ISA used: i486, 586, SSE2, SSE3 + x86 ISA needed: 586, SSE, SSE3, SSE4_1 diff --git a/ld/testsuite/ld-i386/property-x86-ibt4.d b/ld/testsuite/ld-i386/property-x86-ibt4.d new file mode 100644 index 00000000000..db14fb9962c --- /dev/null +++ b/ld/testsuite/ld-i386/property-x86-ibt4.d @@ -0,0 +1,9 @@ +#source: property-x86-empty.s +#as: --32 +#ld: -r -melf_i386 -z ibt +#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/ld/testsuite/ld-i386/property-x86-ibt5.d b/ld/testsuite/ld-i386/property-x86-ibt5.d new file mode 100644 index 00000000000..652f6604d0a --- /dev/null +++ b/ld/testsuite/ld-i386/property-x86-ibt5.d @@ -0,0 +1,9 @@ +#source: start.s +#as: --32 +#ld: -r -melf_i386 -z ibt +#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/ld/testsuite/ld-x86-64/ibt-plt-1-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-1-x32.d new file mode 100644 index 00000000000..6147ab49fd7 --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-1-x32.d @@ -0,0 +1,43 @@ +#source: ibt-plt-1.s +#as: --x32 +#ld: -shared -m elf32_x86_64 +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+1c0 <.plt>: + +[a-f0-9]+: ff 35 6a 01 20 00 pushq 0x20016a\(%rip\) # 200330 <_GLOBAL_OFFSET_TABLE_\+0x8> + +[a-f0-9]+: ff 25 6c 01 20 00 jmpq \*0x20016c\(%rip\) # 200338 <_GLOBAL_OFFSET_TABLE_\+0x10> + +[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%rax\) + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 00 00 00 00 pushq \$0x0 + +[a-f0-9]+: e9 e2 ff ff ff jmpq 1c0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 01 00 00 00 pushq \$0x1 + +[a-f0-9]+: e9 d2 ff ff ff jmpq 1c0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +Disassembly of section .plt.sec: + +0+1f0 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: ff 25 46 01 20 00 jmpq \*0x200146\(%rip\) # 200340 + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\) + +0+200 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: ff 25 3e 01 20 00 jmpq \*0x20013e\(%rip\) # 200348 + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\) + +Disassembly of section .text: + +0+210 : + +[a-f0-9]+: 48 83 ec 08 sub \$0x8,%rsp + +[a-f0-9]+: e8 e7 ff ff ff callq 200 + +[a-f0-9]+: 48 83 c4 08 add \$0x8,%rsp + +[a-f0-9]+: e9 ce ff ff ff jmpq 1f0 +#pass diff --git a/ld/testsuite/ld-x86-64/ibt-plt-1.d b/ld/testsuite/ld-x86-64/ibt-plt-1.d new file mode 100644 index 00000000000..dbec3ede87b --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-1.d @@ -0,0 +1,43 @@ +#source: ibt-plt-1.s +#as: --64 -defsym __64_bit__=1 +#ld: -shared -m elf_x86_64 +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+290 <.plt>: + +[a-f0-9]+: ff 35 ea 01 20 00 pushq 0x2001ea\(%rip\) # 200480 <_GLOBAL_OFFSET_TABLE_\+0x8> + +[a-f0-9]+: f2 ff 25 eb 01 20 00 bnd jmpq \*0x2001eb\(%rip\) # 200488 <_GLOBAL_OFFSET_TABLE_\+0x10> + +[a-f0-9]+: 0f 1f 00 nopl \(%rax\) + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 00 00 00 00 pushq \$0x0 + +[a-f0-9]+: f2 e9 e1 ff ff ff bnd jmpq 290 <.plt> + +[a-f0-9]+: 90 nop + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 01 00 00 00 pushq \$0x1 + +[a-f0-9]+: f2 e9 d1 ff ff ff bnd jmpq 290 <.plt> + +[a-f0-9]+: 90 nop + +Disassembly of section .plt.sec: + +0+2c0 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: f2 ff 25 c5 01 20 00 bnd jmpq \*0x2001c5\(%rip\) # 200490 + +[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\) + +0+2d0 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: f2 ff 25 bd 01 20 00 bnd jmpq \*0x2001bd\(%rip\) # 200498 + +[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\) + +Disassembly of section .text: + +0+2e0 : + +[a-f0-9]+: 48 83 ec 08 sub \$0x8,%rsp + +[a-f0-9]+: e8 e7 ff ff ff callq 2d0 + +[a-f0-9]+: 48 83 c4 08 add \$0x8,%rsp + +[a-f0-9]+: e9 ce ff ff ff jmpq 2c0 +#pass diff --git a/ld/testsuite/ld-x86-64/ibt-plt-1.s b/ld/testsuite/ld-x86-64/ibt-plt-1.s new file mode 100644 index 00000000000..2ddf3bbd113 --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-1.s @@ -0,0 +1,45 @@ + .text + .p2align 4,,15 + .globl foo + .type foo, @function +foo: +.LFB0: + .cfi_startproc + subq $8, %rsp + .cfi_def_cfa_offset 16 + call bar2@PLT + addq $8, %rsp + .cfi_def_cfa_offset 8 + jmp bar1@PLT + .cfi_endproc +.LFE0: + .size foo, .-foo + .section .note.GNU-stack,"",@progbits + + .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/ld/testsuite/ld-x86-64/ibt-plt-2.s b/ld/testsuite/ld-x86-64/ibt-plt-2.s new file mode 100644 index 00000000000..e1ea540ff5f --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-2.s @@ -0,0 +1,45 @@ + .text + .p2align 4,,15 + .globl foo + .type foo, @function +foo: +.LFB0: + .cfi_startproc + subq $8, %rsp + .cfi_def_cfa_offset 16 + call bar2@PLT + addq $8, %rsp + .cfi_def_cfa_offset 8 + jmp bar1@PLT + .cfi_endproc +.LFE0: + .size foo, .-foo + .section .note.GNU-stack,"",@progbits + + .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/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d new file mode 100644 index 00000000000..df9dc8e3d71 --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-2a-x32.d @@ -0,0 +1,43 @@ +#source: ibt-plt-2.s +#as: --x32 +#ld: -shared -m elf32_x86_64 -z ibtplt +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+1c0 <.plt>: + +[a-f0-9]+: ff 35 6a 01 20 00 pushq 0x20016a\(%rip\) # 200330 <_GLOBAL_OFFSET_TABLE_\+0x8> + +[a-f0-9]+: ff 25 6c 01 20 00 jmpq \*0x20016c\(%rip\) # 200338 <_GLOBAL_OFFSET_TABLE_\+0x10> + +[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%rax\) + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 00 00 00 00 pushq \$0x0 + +[a-f0-9]+: e9 e2 ff ff ff jmpq 1c0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 01 00 00 00 pushq \$0x1 + +[a-f0-9]+: e9 d2 ff ff ff jmpq 1c0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +Disassembly of section .plt.sec: + +0+1f0 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: ff 25 46 01 20 00 jmpq \*0x200146\(%rip\) # 200340 + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\) + +0+200 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: ff 25 3e 01 20 00 jmpq \*0x20013e\(%rip\) # 200348 + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\) + +Disassembly of section .text: + +0+210 : + +[a-f0-9]+: 48 83 ec 08 sub \$0x8,%rsp + +[a-f0-9]+: e8 e7 ff ff ff callq 200 + +[a-f0-9]+: 48 83 c4 08 add \$0x8,%rsp + +[a-f0-9]+: e9 ce ff ff ff jmpq 1f0 +#pass diff --git a/ld/testsuite/ld-x86-64/ibt-plt-2a.d b/ld/testsuite/ld-x86-64/ibt-plt-2a.d new file mode 100644 index 00000000000..0e4f424d3f4 --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-2a.d @@ -0,0 +1,43 @@ +#source: ibt-plt-2.s +#as: --64 -defsym __64_bit__=1 +#ld: -shared -m elf_x86_64 -z ibtplt +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+290 <.plt>: + +[a-f0-9]+: ff 35 ea 01 20 00 pushq 0x2001ea\(%rip\) # 200480 <_GLOBAL_OFFSET_TABLE_\+0x8> + +[a-f0-9]+: f2 ff 25 eb 01 20 00 bnd jmpq \*0x2001eb\(%rip\) # 200488 <_GLOBAL_OFFSET_TABLE_\+0x10> + +[a-f0-9]+: 0f 1f 00 nopl \(%rax\) + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 00 00 00 00 pushq \$0x0 + +[a-f0-9]+: f2 e9 e1 ff ff ff bnd jmpq 290 <.plt> + +[a-f0-9]+: 90 nop + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 01 00 00 00 pushq \$0x1 + +[a-f0-9]+: f2 e9 d1 ff ff ff bnd jmpq 290 <.plt> + +[a-f0-9]+: 90 nop + +Disassembly of section .plt.sec: + +0+2c0 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: f2 ff 25 c5 01 20 00 bnd jmpq \*0x2001c5\(%rip\) # 200490 + +[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\) + +0+2d0 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: f2 ff 25 bd 01 20 00 bnd jmpq \*0x2001bd\(%rip\) # 200498 + +[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\) + +Disassembly of section .text: + +0+2e0 : + +[a-f0-9]+: 48 83 ec 08 sub \$0x8,%rsp + +[a-f0-9]+: e8 e7 ff ff ff callq 2d0 + +[a-f0-9]+: 48 83 c4 08 add \$0x8,%rsp + +[a-f0-9]+: e9 ce ff ff ff jmpq 2c0 +#pass diff --git a/ld/testsuite/ld-x86-64/ibt-plt-2b-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-2b-x32.d new file mode 100644 index 00000000000..e9e5638ea3e --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-2b-x32.d @@ -0,0 +1,9 @@ +#source: ibt-plt-2.s +#as: --x32 +#ld: -shared -m elf32_x86_64 -z ibtplt +#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/ld/testsuite/ld-x86-64/ibt-plt-2b.d b/ld/testsuite/ld-x86-64/ibt-plt-2b.d new file mode 100644 index 00000000000..604db827459 --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-2b.d @@ -0,0 +1,9 @@ +#source: ibt-plt-2.s +#as: --64 -defsym __64_bit__=1 +#ld: -shared -m elf_x86_64 -z ibtplt +#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/ld/testsuite/ld-x86-64/ibt-plt-2c-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-2c-x32.d new file mode 100644 index 00000000000..e908804cfab --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-2c-x32.d @@ -0,0 +1,43 @@ +#source: ibt-plt-2.s +#as: --x32 +#ld: -shared -m elf32_x86_64 -z ibt +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+1c0 <.plt>: + +[a-f0-9]+: ff 35 6a 01 20 00 pushq 0x20016a\(%rip\) # 200330 <_GLOBAL_OFFSET_TABLE_\+0x8> + +[a-f0-9]+: ff 25 6c 01 20 00 jmpq \*0x20016c\(%rip\) # 200338 <_GLOBAL_OFFSET_TABLE_\+0x10> + +[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%rax\) + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 00 00 00 00 pushq \$0x0 + +[a-f0-9]+: e9 e2 ff ff ff jmpq 1c0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 01 00 00 00 pushq \$0x1 + +[a-f0-9]+: e9 d2 ff ff ff jmpq 1c0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +Disassembly of section .plt.sec: + +0+1f0 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: ff 25 46 01 20 00 jmpq \*0x200146\(%rip\) # 200340 + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\) + +0+200 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: ff 25 3e 01 20 00 jmpq \*0x20013e\(%rip\) # 200348 + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\) + +Disassembly of section .text: + +0+210 : + +[a-f0-9]+: 48 83 ec 08 sub \$0x8,%rsp + +[a-f0-9]+: e8 e7 ff ff ff callq 200 + +[a-f0-9]+: 48 83 c4 08 add \$0x8,%rsp + +[a-f0-9]+: e9 ce ff ff ff jmpq 1f0 +#pass diff --git a/ld/testsuite/ld-x86-64/ibt-plt-2c.d b/ld/testsuite/ld-x86-64/ibt-plt-2c.d new file mode 100644 index 00000000000..0ef1131271f --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-2c.d @@ -0,0 +1,43 @@ +#source: ibt-plt-2.s +#as: --64 -defsym __64_bit__=1 +#ld: -shared -m elf_x86_64 -z ibt +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+290 <.plt>: + +[a-f0-9]+: ff 35 ea 01 20 00 pushq 0x2001ea\(%rip\) # 200480 <_GLOBAL_OFFSET_TABLE_\+0x8> + +[a-f0-9]+: f2 ff 25 eb 01 20 00 bnd jmpq \*0x2001eb\(%rip\) # 200488 <_GLOBAL_OFFSET_TABLE_\+0x10> + +[a-f0-9]+: 0f 1f 00 nopl \(%rax\) + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 00 00 00 00 pushq \$0x0 + +[a-f0-9]+: f2 e9 e1 ff ff ff bnd jmpq 290 <.plt> + +[a-f0-9]+: 90 nop + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 01 00 00 00 pushq \$0x1 + +[a-f0-9]+: f2 e9 d1 ff ff ff bnd jmpq 290 <.plt> + +[a-f0-9]+: 90 nop + +Disassembly of section .plt.sec: + +0+2c0 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: f2 ff 25 c5 01 20 00 bnd jmpq \*0x2001c5\(%rip\) # 200490 + +[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\) + +0+2d0 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: f2 ff 25 bd 01 20 00 bnd jmpq \*0x2001bd\(%rip\) # 200498 + +[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\) + +Disassembly of section .text: + +0+2e0 : + +[a-f0-9]+: 48 83 ec 08 sub \$0x8,%rsp + +[a-f0-9]+: e8 e7 ff ff ff callq 2d0 + +[a-f0-9]+: 48 83 c4 08 add \$0x8,%rsp + +[a-f0-9]+: e9 ce ff ff ff jmpq 2c0 +#pass diff --git a/ld/testsuite/ld-x86-64/ibt-plt-2d-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-2d-x32.d new file mode 100644 index 00000000000..b3be9048d88 --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-2d-x32.d @@ -0,0 +1,9 @@ +#source: ibt-plt-2.s +#as: --x32 +#ld: -shared -m elf32_x86_64 -z ibt +#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/ld/testsuite/ld-x86-64/ibt-plt-2d.d b/ld/testsuite/ld-x86-64/ibt-plt-2d.d new file mode 100644 index 00000000000..7226b695d46 --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-2d.d @@ -0,0 +1,9 @@ +#source: ibt-plt-2.s +#as: --64 -defsym __64_bit__=1 +#ld: -shared -m elf_x86_64 -z ibt +#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/ld/testsuite/ld-x86-64/ibt-plt-3.s b/ld/testsuite/ld-x86-64/ibt-plt-3.s new file mode 100644 index 00000000000..299b02324fe --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-3.s @@ -0,0 +1,17 @@ + .text + .p2align 4,,15 + .globl foo + .type foo, @function +foo: +.LFB0: + .cfi_startproc + subq $8, %rsp + .cfi_def_cfa_offset 16 + call bar2@PLT + addq $8, %rsp + .cfi_def_cfa_offset 8 + jmp bar1@PLT + .cfi_endproc +.LFE0: + .size foo, .-foo + .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d new file mode 100644 index 00000000000..0f7835d966e --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-3a-x32.d @@ -0,0 +1,43 @@ +#source: ibt-plt-3.s +#as: --x32 +#ld: -shared -m elf32_x86_64 -z ibtplt +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+1a0 <.plt>: + +[a-f0-9]+: ff 35 52 01 20 00 pushq 0x200152\(%rip\) # 2002f8 <_GLOBAL_OFFSET_TABLE_\+0x8> + +[a-f0-9]+: ff 25 54 01 20 00 jmpq \*0x200154\(%rip\) # 200300 <_GLOBAL_OFFSET_TABLE_\+0x10> + +[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%rax\) + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 00 00 00 00 pushq \$0x0 + +[a-f0-9]+: e9 e2 ff ff ff jmpq 1a0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 01 00 00 00 pushq \$0x1 + +[a-f0-9]+: e9 d2 ff ff ff jmpq 1a0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +Disassembly of section .plt.sec: + +0+1d0 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: ff 25 2e 01 20 00 jmpq \*0x20012e\(%rip\) # 200308 + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\) + +0+1e0 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: ff 25 26 01 20 00 jmpq \*0x200126\(%rip\) # 200310 + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\) + +Disassembly of section .text: + +0+1f0 : + +[a-f0-9]+: 48 83 ec 08 sub \$0x8,%rsp + +[a-f0-9]+: e8 e7 ff ff ff callq 1e0 + +[a-f0-9]+: 48 83 c4 08 add \$0x8,%rsp + +[a-f0-9]+: e9 ce ff ff ff jmpq 1d0 +#pass diff --git a/ld/testsuite/ld-x86-64/ibt-plt-3a.d b/ld/testsuite/ld-x86-64/ibt-plt-3a.d new file mode 100644 index 00000000000..b8f2ebc04ef --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-3a.d @@ -0,0 +1,43 @@ +#source: ibt-plt-3.s +#as: --64 -defsym __64_bit__=1 +#ld: -shared -m elf_x86_64 -z ibtplt +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+250 <.plt>: + +[a-f0-9]+: ff 35 ca 01 20 00 pushq 0x2001ca\(%rip\) # 200420 <_GLOBAL_OFFSET_TABLE_\+0x8> + +[a-f0-9]+: f2 ff 25 cb 01 20 00 bnd jmpq \*0x2001cb\(%rip\) # 200428 <_GLOBAL_OFFSET_TABLE_\+0x10> + +[a-f0-9]+: 0f 1f 00 nopl \(%rax\) + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 00 00 00 00 pushq \$0x0 + +[a-f0-9]+: f2 e9 e1 ff ff ff bnd jmpq 250 <.plt> + +[a-f0-9]+: 90 nop + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 01 00 00 00 pushq \$0x1 + +[a-f0-9]+: f2 e9 d1 ff ff ff bnd jmpq 250 <.plt> + +[a-f0-9]+: 90 nop + +Disassembly of section .plt.sec: + +0+280 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: f2 ff 25 a5 01 20 00 bnd jmpq \*0x2001a5\(%rip\) # 200430 + +[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\) + +0+290 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: f2 ff 25 9d 01 20 00 bnd jmpq \*0x20019d\(%rip\) # 200438 + +[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\) + +Disassembly of section .text: + +0+2a0 : + +[a-f0-9]+: 48 83 ec 08 sub \$0x8,%rsp + +[a-f0-9]+: e8 e7 ff ff ff callq 290 + +[a-f0-9]+: 48 83 c4 08 add \$0x8,%rsp + +[a-f0-9]+: e9 ce ff ff ff jmpq 280 +#pass diff --git a/ld/testsuite/ld-x86-64/ibt-plt-3b-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-3b-x32.d new file mode 100644 index 00000000000..fb0a834be5a --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-3b-x32.d @@ -0,0 +1,5 @@ +#source: ibt-plt-3.s +#as: --x32 +#ld: -shared -m elf32_x86_64 -z ibtplt +#readelf: -n + diff --git a/ld/testsuite/ld-x86-64/ibt-plt-3b.d b/ld/testsuite/ld-x86-64/ibt-plt-3b.d new file mode 100644 index 00000000000..5a3843bc3ab --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-3b.d @@ -0,0 +1,5 @@ +#source: ibt-plt-3.s +#as: --64 -defsym __64_bit__=1 +#ld: -shared -m elf_x86_64 -z ibtplt +#readelf: -n + diff --git a/ld/testsuite/ld-x86-64/ibt-plt-3c-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-3c-x32.d new file mode 100644 index 00000000000..234944ddc4a --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-3c-x32.d @@ -0,0 +1,43 @@ +#source: ibt-plt-3.s +#as: --x32 +#ld: -shared -m elf32_x86_64 -z ibt +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+1c0 <.plt>: + +[a-f0-9]+: ff 35 6a 01 20 00 pushq 0x20016a\(%rip\) # 200330 <_GLOBAL_OFFSET_TABLE_\+0x8> + +[a-f0-9]+: ff 25 6c 01 20 00 jmpq \*0x20016c\(%rip\) # 200338 <_GLOBAL_OFFSET_TABLE_\+0x10> + +[a-f0-9]+: 0f 1f 40 00 nopl 0x0\(%rax\) + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 00 00 00 00 pushq \$0x0 + +[a-f0-9]+: e9 e2 ff ff ff jmpq 1c0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 01 00 00 00 pushq \$0x1 + +[a-f0-9]+: e9 d2 ff ff ff jmpq 1c0 <.plt> + +[a-f0-9]+: 66 90 xchg %ax,%ax + +Disassembly of section .plt.sec: + +0+1f0 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: ff 25 46 01 20 00 jmpq \*0x200146\(%rip\) # 200340 + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\) + +0+200 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: ff 25 3e 01 20 00 jmpq \*0x20013e\(%rip\) # 200348 + +[a-f0-9]+: 66 0f 1f 44 00 00 nopw 0x0\(%rax,%rax,1\) + +Disassembly of section .text: + +0+210 : + +[a-f0-9]+: 48 83 ec 08 sub \$0x8,%rsp + +[a-f0-9]+: e8 e7 ff ff ff callq 200 + +[a-f0-9]+: 48 83 c4 08 add \$0x8,%rsp + +[a-f0-9]+: e9 ce ff ff ff jmpq 1f0 +#pass diff --git a/ld/testsuite/ld-x86-64/ibt-plt-3c.d b/ld/testsuite/ld-x86-64/ibt-plt-3c.d new file mode 100644 index 00000000000..b299f22b6fe --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-3c.d @@ -0,0 +1,43 @@ +#source: ibt-plt-3.s +#as: --64 -defsym __64_bit__=1 +#ld: -shared -m elf_x86_64 -z ibt +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .plt: + +0+290 <.plt>: + +[a-f0-9]+: ff 35 ea 01 20 00 pushq 0x2001ea\(%rip\) # 200480 <_GLOBAL_OFFSET_TABLE_\+0x8> + +[a-f0-9]+: f2 ff 25 eb 01 20 00 bnd jmpq \*0x2001eb\(%rip\) # 200488 <_GLOBAL_OFFSET_TABLE_\+0x10> + +[a-f0-9]+: 0f 1f 00 nopl \(%rax\) + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 00 00 00 00 pushq \$0x0 + +[a-f0-9]+: f2 e9 e1 ff ff ff bnd jmpq 290 <.plt> + +[a-f0-9]+: 90 nop + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: 68 01 00 00 00 pushq \$0x1 + +[a-f0-9]+: f2 e9 d1 ff ff ff bnd jmpq 290 <.plt> + +[a-f0-9]+: 90 nop + +Disassembly of section .plt.sec: + +0+2c0 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: f2 ff 25 c5 01 20 00 bnd jmpq \*0x2001c5\(%rip\) # 200490 + +[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\) + +0+2d0 : + +[a-f0-9]+: f3 0f 1e fa endbr64 + +[a-f0-9]+: f2 ff 25 bd 01 20 00 bnd jmpq \*0x2001bd\(%rip\) # 200498 + +[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\) + +Disassembly of section .text: + +0+2e0 : + +[a-f0-9]+: 48 83 ec 08 sub \$0x8,%rsp + +[a-f0-9]+: e8 e7 ff ff ff callq 2d0 + +[a-f0-9]+: 48 83 c4 08 add \$0x8,%rsp + +[a-f0-9]+: e9 ce ff ff ff jmpq 2c0 +#pass diff --git a/ld/testsuite/ld-x86-64/ibt-plt-3d-x32.d b/ld/testsuite/ld-x86-64/ibt-plt-3d-x32.d new file mode 100644 index 00000000000..447e8116a93 --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-3d-x32.d @@ -0,0 +1,10 @@ +#source: ibt-plt-3.s +#as: --x32 +#ld: -shared -m elf32_x86_64 -z ibt +#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/ld/testsuite/ld-x86-64/ibt-plt-3d.d b/ld/testsuite/ld-x86-64/ibt-plt-3d.d new file mode 100644 index 00000000000..342626a4722 --- /dev/null +++ b/ld/testsuite/ld-x86-64/ibt-plt-3d.d @@ -0,0 +1,10 @@ +#source: ibt-plt-3.s +#as: --64 -defsym __64_bit__=1 +#ld: -shared -m elf_x86_64 -z ibt +#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/ld/testsuite/ld-x86-64/plt-main-ibt-now.rd b/ld/testsuite/ld-x86-64/plt-main-ibt-now.rd new file mode 100644 index 00000000000..2478c1fe9a5 --- /dev/null +++ b/ld/testsuite/ld-x86-64/plt-main-ibt-now.rd @@ -0,0 +1,3 @@ +#... + +\[[ 0-9]+\] \.plt\.sec +.* +#pass diff --git a/ld/testsuite/ld-x86-64/plt-main-ibt-x32.dd b/ld/testsuite/ld-x86-64/plt-main-ibt-x32.dd new file mode 100644 index 00000000000..7b5e174ef10 --- /dev/null +++ b/ld/testsuite/ld-x86-64/plt-main-ibt-x32.dd @@ -0,0 +1,7 @@ +#... +Disassembly of section .plt.got: + +[a-f0-9]+ <[_a-z]+@plt>: +[ ]*[a-f0-9]+: f3 0f 1e fa endbr64 +[ ]*[a-f0-9]+: ff 25 .. .. 20 00 jmpq +\*0x20....\(%rip\) # ...... <[_a-z]+> +#pass diff --git a/ld/testsuite/ld-x86-64/plt-main-ibt.dd b/ld/testsuite/ld-x86-64/plt-main-ibt.dd new file mode 100644 index 00000000000..725f427e76b --- /dev/null +++ b/ld/testsuite/ld-x86-64/plt-main-ibt.dd @@ -0,0 +1,7 @@ +#... +Disassembly of section .plt.got: + +[a-f0-9]+ <[_a-z]+@plt>: +[ ]*[a-f0-9]+: f3 0f 1e fa endbr64 +[ ]*[a-f0-9]+: f2 ff 25 .. .. 20 00 bnd jmpq \*0x20....\(%rip\) # ...... <[_a-z]+> +#pass diff --git a/ld/testsuite/ld-x86-64/pr21481b.S b/ld/testsuite/ld-x86-64/pr21481b.S index 744d86a382a..583ec77d121 100644 --- a/ld/testsuite/ld-x86-64/pr21481b.S +++ b/ld/testsuite/ld-x86-64/pr21481b.S @@ -10,7 +10,11 @@ check: cmpl $func1, %eax jne .L3 movq func1_p@GOTPCREL(%rip), %rdx +#ifdef __LP64__ cmpq %rax, (%rdx) +#else + cmpl %eax, (%rdx) +#endif jne .L3 call *func1@GOTPCREL(%rip) cmpl $1, %eax diff --git a/ld/testsuite/ld-x86-64/property-x86-empty.s b/ld/testsuite/ld-x86-64/property-x86-empty.s new file mode 100644 index 00000000000..6a6b517fd07 --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-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/ld/testsuite/ld-x86-64/property-x86-ibt.s b/ld/testsuite/ld-x86-64/property-x86-ibt.s new file mode 100644 index 00000000000..84ee9641369 --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-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/ld/testsuite/ld-x86-64/property-x86-ibt1a-x32.d b/ld/testsuite/ld-x86-64/property-x86-ibt1a-x32.d new file mode 100644 index 00000000000..b215d79debf --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-ibt1a-x32.d @@ -0,0 +1,6 @@ +#source: property-x86-empty.s +#source: property-x86-ibt.s +#as: --x32 +#ld: -r -m elf32_x86_64 +#readelf: -n + diff --git a/ld/testsuite/ld-x86-64/property-x86-ibt1a.d b/ld/testsuite/ld-x86-64/property-x86-ibt1a.d new file mode 100644 index 00000000000..50f220caed5 --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-ibt1a.d @@ -0,0 +1,6 @@ +#source: property-x86-empty.s +#source: property-x86-ibt.s +#as: --64 -defsym __64_bit__=1 +#ld: -r -melf_x86_64 +#readelf: -n + diff --git a/ld/testsuite/ld-x86-64/property-x86-ibt1b-x32.d b/ld/testsuite/ld-x86-64/property-x86-ibt1b-x32.d new file mode 100644 index 00000000000..7361cea8192 --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-ibt1b-x32.d @@ -0,0 +1,6 @@ +#source: property-x86-ibt.s +#source: property-x86-empty.s +#as: --x32 +#ld: -r -m elf32_x86_64 +#readelf: -n + diff --git a/ld/testsuite/ld-x86-64/property-x86-ibt1b.d b/ld/testsuite/ld-x86-64/property-x86-ibt1b.d new file mode 100644 index 00000000000..7f47db7e01d --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-ibt1b.d @@ -0,0 +1,6 @@ +#source: property-x86-ibt.s +#source: property-x86-empty.s +#as: --64 -defsym __64_bit__=1 +#ld: -r -melf_x86_64 +#readelf: -n + diff --git a/ld/testsuite/ld-x86-64/property-x86-ibt2-x32.d b/ld/testsuite/ld-x86-64/property-x86-ibt2-x32.d new file mode 100644 index 00000000000..a0fb61436d4 --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-ibt2-x32.d @@ -0,0 +1,9 @@ +#source: property-x86-ibt.s +#as: --x32 +#ld: -r -m elf32_x86_64 +#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/ld/testsuite/ld-x86-64/property-x86-ibt2.d b/ld/testsuite/ld-x86-64/property-x86-ibt2.d new file mode 100644 index 00000000000..be3df9c7ac9 --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-ibt2.d @@ -0,0 +1,9 @@ +#source: property-x86-ibt.s +#as: --64 -defsym __64_bit__=1 +#ld: -r -melf_x86_64 +#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/ld/testsuite/ld-x86-64/property-x86-ibt3a-x32.d b/ld/testsuite/ld-x86-64/property-x86-ibt3a-x32.d new file mode 100644 index 00000000000..011426f5a4d --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-ibt3a-x32.d @@ -0,0 +1,11 @@ +#source: property-x86-3.s +#source: property-x86-ibt.s +#as: --x32 +#ld: -r -m elf32_x86_64 +#readelf: -n + +Displaying notes found in: .note.gnu.property + Owner Data size Description + GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0 + Properties: x86 ISA used: 586, SSE, SSE3, SSE4_1 + x86 ISA needed: i486, 586, SSE2, SSE3 diff --git a/ld/testsuite/ld-x86-64/property-x86-ibt3a.d b/ld/testsuite/ld-x86-64/property-x86-ibt3a.d new file mode 100644 index 00000000000..1b4229a0378 --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-ibt3a.d @@ -0,0 +1,11 @@ +#source: property-x86-3.s +#source: property-x86-ibt.s +#as: --64 -defsym __64_bit__=1 +#ld: -r -melf_x86_64 +#readelf: -n + +Displaying notes found in: .note.gnu.property + Owner Data size Description + GNU 0x00000020 NT_GNU_PROPERTY_TYPE_0 + Properties: x86 ISA used: 586, SSE, SSE3, SSE4_1 + x86 ISA needed: i486, 586, SSE2, SSE3 diff --git a/ld/testsuite/ld-x86-64/property-x86-ibt3b-x32.d b/ld/testsuite/ld-x86-64/property-x86-ibt3b-x32.d new file mode 100644 index 00000000000..290ed6abf12 --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-ibt3b-x32.d @@ -0,0 +1,11 @@ +#source: property-x86-ibt.s +#source: property-x86-3.s +#as: --x32 +#ld: -r -m elf32_x86_64 +#readelf: -n + +Displaying notes found in: .note.gnu.property + Owner Data size Description + GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0 + Properties: x86 ISA used: 586, SSE, SSE3, SSE4_1 + x86 ISA needed: i486, 586, SSE2, SSE3 diff --git a/ld/testsuite/ld-x86-64/property-x86-ibt3b.d b/ld/testsuite/ld-x86-64/property-x86-ibt3b.d new file mode 100644 index 00000000000..1142e032721 --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-ibt3b.d @@ -0,0 +1,11 @@ +#source: property-x86-ibt.s +#source: property-x86-3.s +#as: --64 -defsym __64_bit__=1 +#ld: -r -melf_x86_64 +#readelf: -n + +Displaying notes found in: .note.gnu.property + Owner Data size Description + GNU 0x00000020 NT_GNU_PROPERTY_TYPE_0 + Properties: x86 ISA used: 586, SSE, SSE3, SSE4_1 + x86 ISA needed: i486, 586, SSE2, SSE3 diff --git a/ld/testsuite/ld-x86-64/property-x86-ibt4-x32.d b/ld/testsuite/ld-x86-64/property-x86-ibt4-x32.d new file mode 100644 index 00000000000..b96abbcebe1 --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-ibt4-x32.d @@ -0,0 +1,9 @@ +#source: property-x86-empty.s +#as: --x32 +#ld: -r -m elf32_x86_64 -z ibt +#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/ld/testsuite/ld-x86-64/property-x86-ibt4.d b/ld/testsuite/ld-x86-64/property-x86-ibt4.d new file mode 100644 index 00000000000..3f61a7691e0 --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-ibt4.d @@ -0,0 +1,9 @@ +#source: property-x86-empty.s +#as: --64 -defsym __64_bit__=1 +#ld: -r -melf_x86_64 -z ibt +#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/ld/testsuite/ld-x86-64/property-x86-ibt5-x32.d b/ld/testsuite/ld-x86-64/property-x86-ibt5-x32.d new file mode 100644 index 00000000000..5245d0bc909 --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-ibt5-x32.d @@ -0,0 +1,9 @@ +#source: start.s +#as: --x32 +#ld: -r -m elf32_x86_64 -z ibt +#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/ld/testsuite/ld-x86-64/property-x86-ibt5.d b/ld/testsuite/ld-x86-64/property-x86-ibt5.d new file mode 100644 index 00000000000..ab74033455a --- /dev/null +++ b/ld/testsuite/ld-x86-64/property-x86-ibt5.d @@ -0,0 +1,9 @@ +#source: start.s +#as: --64 -defsym __64_bit__=1 +#ld: -r -melf_x86_64 -z ibt +#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/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 21f408d27db..6cde22ff58e 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -335,6 +335,20 @@ run_dump_test "property-x86-4b" run_dump_test "property-x86-3-x32" run_dump_test "property-x86-4a-x32" run_dump_test "property-x86-4b-x32" +run_dump_test "property-x86-ibt1a" +run_dump_test "property-x86-ibt1b" +run_dump_test "property-x86-ibt1a-x32" +run_dump_test "property-x86-ibt1b-x32" +run_dump_test "property-x86-ibt2" +run_dump_test "property-x86-ibt2-x32" +run_dump_test "property-x86-ibt3a" +run_dump_test "property-x86-ibt3b" +run_dump_test "property-x86-ibt3a-x32" +run_dump_test "property-x86-ibt3b-x32" +run_dump_test "property-x86-ibt4" +run_dump_test "property-x86-ibt4-x32" +run_dump_test "property-x86-ibt5" +run_dump_test "property-x86-ibt5-x32" if { ![istarget "x86_64-*-linux*"] && ![istarget "x86_64-*-nacl*"]} { return @@ -1350,6 +1364,156 @@ if { [isnative] && [which $CC] != 0 } { } } + if { [istarget "x86_64-*-linux*"] } { + if { [istarget "x86_64-*-linux*-gnux32"] } { + set pltdump {{objdump {-drw} plt-main-ibt-x32.dd}} + set pltsecdump {{readelf {-SW} plt-main-ibt-now.rd} {objdump {-drw} plt-main-ibt-x32.dd}} + } else { + set pltdump {{objdump {-drw} plt-main-ibt.dd}} + set pltsecdump {{readelf {-SW} plt-main-ibt-now.rd} {objdump {-drw} plt-main-ibt.dd}} + } + run_cc_link_tests [list \ + [list \ + "Build plt-main with -z ibtplt" \ + "tmpdir/plt-main1.o tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so -z ibtplt" \ + "" \ + { plt-main5.c } \ + $pltdump \ + "plt-main-ibt" \ + ] \ + [list \ + "Build plt-main with PIE and -z ibtplt" \ + "tmpdir/plt-main1.o tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so -z ibtplt -pie" \ + "-fPIC" \ + { plt-main5.c } \ + $pltdump \ + "plt-main-pie-ibt" \ + ] \ + [list \ + "Build plt-main with -z ibtplt -z now" \ + "tmpdir/plt-main1.o tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so -z ibtplt -z now" \ + "" \ + { plt-main5.c } \ + $pltsecdump \ + "plt-main-ibt-now" \ + ] \ + [list \ + "Build plt-main with PIE and -z ibtplt -z now" \ + "tmpdir/plt-main1.o tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so -z ibtplt -z now -pie" \ + "-fPIC" \ + { plt-main5.c } \ + $pltsecdump \ + "plt-main-pie-ibt-now" \ + ] \ + [list \ + "Build libibtplt-lib.so with -z ibtplt" \ + "-shared -z ibtplt" \ + "-fPIC" \ + { plt-main1.c plt-main2.c plt-main3.c plt-main4.c} \ + $pltdump \ + "libibtplt-lib.so" \ + ] \ + [list \ + "Build libibtplt--now-lib.so with -z ibtplt -z now" \ + "-shared -z ibtplt -z now" \ + "-fPIC" \ + { plt-main1.c plt-main2.c plt-main3.c plt-main4.c} \ + $pltdump \ + "libibtplt-now-lib.so" \ + ] \ + ] + + run_ld_link_exec_tests [list \ + [list \ + "Run plt-main with -z ibtplt" \ + "-Wl,--no-as-needed,-z,ibtplt tmpdir/plt-main1.o \ + tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so" \ + "" \ + { plt-main5.c } \ + "plt-main-ibt" \ + "plt-main.out" \ + ] \ + [list \ + "Run plt-main with PIE and -z ibtplt" \ + "-Wl,--no-as-needed,-z,ibtplt -pie tmpdir/plt-main1.o \ + tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so" \ + "" \ + { plt-main5.c } \ + "plt-main-pie-ibt" \ + "plt-main.out" \ + "-fPIC" \ + ] \ + [list \ + "Run plt-main with -z ibtplt -z now" \ + "-Wl,--no-as-needed,-z,ibtplt,-z,now tmpdir/plt-main1.o \ + tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so" \ + "" \ + { plt-main5.c } \ + "plt-main-ibt-now" \ + "plt-main.out" \ + ] \ + [list \ + "Run plt-main with PIE and -z ibtplt -z now" \ + "-Wl,--no-as-needed,-z,ibtplt,-z,now -pie tmpdir/plt-main1.o \ + tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so" \ + "" \ + { plt-main5.c } \ + "plt-main-pie-ibt-now" \ + "plt-main.out" \ + "-fPIC" \ + ] \ + [list \ + "Run plt-main with libibtplt-lib.so -z ibtplt" \ + "-Wl,--no-as-needed,-z,ibtplt tmpdir/libibtplt-lib.so \ + tmpdir/libplt-lib.so" \ + "" \ + { plt-main5.c } \ + "plt-main-ibt-lib" \ + "plt-main.out" \ + ] \ + [list \ + "Run plt-main with libibtplt-lib.so -z ibtplt -z now" \ + "-Wl,--no-as-needed,-z,ibtplt,-z,now \ + tmpdir/libibtplt-now-lib.so tmpdir/libplt-lib.so" \ + "" \ + { plt-main5.c } \ + "plt-main-ibt-now-lib" \ + "plt-main.out" \ + ] \ + ] + + if { [check_ifunc_attribute_available] } { + run_ld_link_exec_tests [list \ + [list \ + "Run pr21481a" \ + "$NOPIE_LDFLAGS -Wl,-z,ibtplt" \ + "" \ + { pr21481a.c pr21481b.S } \ + "pr21481a" \ + "pass.out" \ + "$NOPIE_CFLAGS" \ + ] \ + [list \ + "Run pr21481b" \ + "$NOPIE_LDFLAGS -Wl,-z,ibtplt,-z,now" \ + "" \ + { pr21481a.c pr21481b.S } \ + "pr21481b" \ + "pass.out" \ + "$NOPIE_CFLAGS" \ + ] \ + ] + } + } + undefined_weak "$NOPIE_CFLAGS" "$NOPIE_LDFLAGS" undefined_weak "-fPIE" "" undefined_weak "-fPIE" "-pie" @@ -1405,3 +1569,21 @@ run_dump_test "pr20830b-now" run_dump_test "pr21038a-now" run_dump_test "pr21038b-now" run_dump_test "pr21038c-now" +run_dump_test "ibt-plt-1" +run_dump_test "ibt-plt-1-x32" +run_dump_test "ibt-plt-2a" +run_dump_test "ibt-plt-2b" +run_dump_test "ibt-plt-2c" +run_dump_test "ibt-plt-2d" +run_dump_test "ibt-plt-2a-x32" +run_dump_test "ibt-plt-2b-x32" +run_dump_test "ibt-plt-2c-x32" +run_dump_test "ibt-plt-2d-x32" +run_dump_test "ibt-plt-3a" +run_dump_test "ibt-plt-3b" +run_dump_test "ibt-plt-3c" +run_dump_test "ibt-plt-3d" +run_dump_test "ibt-plt-3a-x32" +run_dump_test "ibt-plt-3b-x32" +run_dump_test "ibt-plt-3c-x32" +run_dump_test "ibt-plt-3d-x32"