From 92e68c1d65f844c0027f471a0c9e1722d781ef7d Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Mon, 28 May 2018 10:46:16 -0700 Subject: [PATCH] x86-64: Add TLSDESC fields to elf_x86_lazy_plt_layout ENDBR64 is added to the special TLSDESC entry, which is similar to the PLT0 entry, in the x86-64 lazy procedure linkage table to support Intel CET. The NaCl PLT is different from the normal PLT. This patch adds plt_tlsdesc_entry, plt_tlsdesc_entry_size, plt_tlsdesc_got1_offset, plt_tlsdesc_got2_offset, plt_tlsdesc_got1_insn_end and plt_tlsdesc_got2_insn_end to elf_x86_lazy_plt_layout to support both normal and NaCl TLSDESC entries. This fixed FAIL: TLS descriptor -fpic -shared transitions for x86_64-nacl. * elf32-i386.c (elf_i386_lazy_plt): Add plt_tlsdesc_entry, plt_tlsdesc_entry_size, plt_tlsdesc_got1_offset, plt_tlsdesc_got2_offset, plt_tlsdesc_got1_insn_end and plt_tlsdesc_got2_insn_end for TLSDESC entry. (elf_i386_lazy_ibt_plt): Likewise. (elf_i386_nacl_plt): Likewise. * elf64-x86-64.c (tlsdesc_plt_entry): Moved and renamed to ... (elf_x86_64_tlsdesc_plt_entry): This. (elf_x86_64_lazy_plt): Add plt_tlsdesc_entry, plt_tlsdesc_entry_size, plt_tlsdesc_got1_offset, plt_tlsdesc_got2_offset, plt_tlsdesc_got1_insn_end and plt_tlsdesc_got2_insn_end for TLSDESC entry. (elf_x86_64_lazy_bnd_plt): Likewise. (elf_x86_64_lazy_ibt_plt): Likewise. (elf_x32_lazy_ibt_plt): Likewise. (elf_x86_64_nacl_plt): Likewise. (elf_x86_64_finish_dynamic_sections): Use plt_tlsdesc_entry, plt_tlsdesc_entry_size, plt_tlsdesc_got1_offset, plt_tlsdesc_got2_offset, plt_tlsdesc_got1_insn_end and plt_tlsdesc_got2_insn_end to update TLSDESC entry. * elfxx-x86.h (elf_x86_lazy_plt_layout): Update comments. Add plt_tlsdesc_entry, plt_tlsdesc_entry_size, plt_tlsdesc_got1_offset, plt_tlsdesc_got2_offset, plt_tlsdesc_got1_insn_end and plt_tlsdesc_got2_insn_end. (elf_x86_non_lazy_plt_layout): Update comments. (elf_x86_plt_layout): Likewise. --- bfd/ChangeLog | 29 +++++++++++++++++++++++ bfd/elf32-i386.c | 18 ++++++++++++++ bfd/elf64-x86-64.c | 58 +++++++++++++++++++++++++++++++++++----------- bfd/elfxx-x86.h | 33 ++++++++++++++++++-------- 4 files changed, 115 insertions(+), 23 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f190b9f3be0..5e1724b5f27 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,32 @@ +2018-05-28 H.J. Lu + + * elf32-i386.c (elf_i386_lazy_plt): Add plt_tlsdesc_entry, + plt_tlsdesc_entry_size, plt_tlsdesc_got1_offset, + plt_tlsdesc_got2_offset, plt_tlsdesc_got1_insn_end and + plt_tlsdesc_got2_insn_end for TLSDESC entry. + (elf_i386_lazy_ibt_plt): Likewise. + (elf_i386_nacl_plt): Likewise. + * elf64-x86-64.c (tlsdesc_plt_entry): Moved and renamed to ... + (elf_x86_64_tlsdesc_plt_entry): This. + (elf_x86_64_lazy_plt): Add plt_tlsdesc_entry, + plt_tlsdesc_entry_size, plt_tlsdesc_got1_offset, + plt_tlsdesc_got2_offset, plt_tlsdesc_got1_insn_end and + plt_tlsdesc_got2_insn_end for TLSDESC entry. + (elf_x86_64_lazy_bnd_plt): Likewise. + (elf_x86_64_lazy_ibt_plt): Likewise. + (elf_x32_lazy_ibt_plt): Likewise. + (elf_x86_64_nacl_plt): Likewise. + (elf_x86_64_finish_dynamic_sections): Use plt_tlsdesc_entry, + plt_tlsdesc_entry_size, plt_tlsdesc_got1_offset, + plt_tlsdesc_got2_offset, plt_tlsdesc_got1_insn_end and + plt_tlsdesc_got2_insn_end to update TLSDESC entry. + * elfxx-x86.h (elf_x86_lazy_plt_layout): Update comments. + Add plt_tlsdesc_entry, plt_tlsdesc_entry_size, + plt_tlsdesc_got1_offset, plt_tlsdesc_got2_offset, + plt_tlsdesc_got1_insn_end and plt_tlsdesc_got2_insn_end. + (elf_x86_non_lazy_plt_layout): Update comments. + (elf_x86_plt_layout): Likewise. + 2018-05-28 H.J. Lu PR ld/23238 diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 3dd709a10e4..49797dcbfaf 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -766,6 +766,12 @@ static const struct elf_x86_lazy_plt_layout elf_i386_lazy_plt = sizeof (elf_i386_lazy_plt0_entry), /* plt0_entry_size */ elf_i386_lazy_plt_entry, /* plt_entry */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + NULL, /* plt_tlsdesc_entry */ + 0, /* plt_tlsdesc_entry_size*/ + 0, /* plt_tlsdesc_got1_offset */ + 0, /* plt_tlsdesc_got2_offset */ + 0, /* plt_tlsdesc_got1_insn_end */ + 0, /* plt_tlsdesc_got2_insn_end */ 2, /* plt0_got1_offset */ 8, /* plt0_got2_offset */ 0, /* plt0_got2_insn_end */ @@ -798,6 +804,12 @@ static const struct elf_x86_lazy_plt_layout elf_i386_lazy_ibt_plt = sizeof (elf_i386_lazy_ibt_plt0_entry), /* plt0_entry_size */ elf_i386_lazy_ibt_plt_entry, /* plt_entry */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + NULL, /* plt_tlsdesc_entry */ + 0, /* plt_tlsdesc_entry_size*/ + 0, /* plt_tlsdesc_got1_offset */ + 0, /* plt_tlsdesc_got2_offset */ + 0, /* plt_tlsdesc_got1_insn_end */ + 0, /* plt_tlsdesc_got2_insn_end */ 2, /* plt0_got1_offset */ 8, /* plt0_got2_offset */ 0, /* plt0_got2_insn_end */ @@ -4728,6 +4740,12 @@ static const struct elf_x86_lazy_plt_layout elf_i386_nacl_plt = sizeof (elf_i386_nacl_plt0_entry), /* plt0_entry_size */ elf_i386_nacl_plt_entry, /* plt_entry */ NACL_PLT_ENTRY_SIZE, /* plt_entry_size */ + NULL, /* plt_tlsdesc_entry */ + 0, /* plt_tlsdesc_entry_size*/ + 0, /* plt_tlsdesc_got1_offset */ + 0, /* plt_tlsdesc_got2_offset */ + 0, /* plt_tlsdesc_got1_insn_end */ + 0, /* plt_tlsdesc_got2_insn_end */ 2, /* plt0_got1_offset */ 8, /* plt0_got2_offset */ 0, /* plt0_got2_insn_end */ diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index e5a4dbcd519..4349561f3c3 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -660,6 +660,14 @@ static const bfd_byte elf_x32_non_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] = 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 /* nopw 0x0(%rax,%rax,1) */ }; +/* The TLSDESC entry in a lazy procedure linkage table. */ +static const bfd_byte elf_x86_64_tlsdesc_plt_entry[LAZY_PLT_ENTRY_SIZE] = +{ + 0xf3, 0x0f, 0x1e, 0xfa, /* endbr64 */ + 0xff, 0x35, 8, 0, 0, 0, /* pushq GOT+8(%rip) */ + 0xff, 0x25, 16, 0, 0, 0 /* jmpq *GOT+TDG(%rip) */ +}; + /* .eh_frame covering the lazy .plt section. */ static const bfd_byte elf_x86_64_eh_frame_lazy_plt[] = @@ -834,6 +842,12 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_plt = LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */ elf_x86_64_lazy_plt_entry, /* plt_entry */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + elf_x86_64_tlsdesc_plt_entry, /* plt_tlsdesc_entry */ + LAZY_PLT_ENTRY_SIZE, /* plt_tlsdesc_entry_size */ + 6, /* plt_tlsdesc_got1_offset */ + 12, /* plt_tlsdesc_got2_offset */ + 10, /* plt_tlsdesc_got1_insn_end */ + 16, /* plt_tlsdesc_got2_insn_end */ 2, /* plt0_got1_offset */ 8, /* plt0_got2_offset */ 12, /* plt0_got2_insn_end */ @@ -866,6 +880,12 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_bnd_plt = LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */ elf_x86_64_lazy_bnd_plt_entry, /* plt_entry */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + elf_x86_64_tlsdesc_plt_entry, /* plt_tlsdesc_entry */ + LAZY_PLT_ENTRY_SIZE, /* plt_tlsdesc_entry_size */ + 6, /* plt_tlsdesc_got1_offset */ + 12, /* plt_tlsdesc_got2_offset */ + 10, /* plt_tlsdesc_got1_insn_end */ + 16, /* plt_tlsdesc_got2_insn_end */ 2, /* plt0_got1_offset */ 1+8, /* plt0_got2_offset */ 1+12, /* plt0_got2_insn_end */ @@ -898,6 +918,12 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_ibt_plt = LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */ elf_x86_64_lazy_ibt_plt_entry, /* plt_entry */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + elf_x86_64_tlsdesc_plt_entry, /* plt_tlsdesc_entry */ + LAZY_PLT_ENTRY_SIZE, /* plt_tlsdesc_entry_size */ + 6, /* plt_tlsdesc_got1_offset */ + 12, /* plt_tlsdesc_got2_offset */ + 10, /* plt_tlsdesc_got1_insn_end */ + 16, /* plt_tlsdesc_got2_insn_end */ 2, /* plt0_got1_offset */ 1+8, /* plt0_got2_offset */ 1+12, /* plt0_got2_insn_end */ @@ -919,6 +945,12 @@ static const struct elf_x86_lazy_plt_layout elf_x32_lazy_ibt_plt = LAZY_PLT_ENTRY_SIZE, /* plt0_entry_size */ elf_x32_lazy_ibt_plt_entry, /* plt_entry */ LAZY_PLT_ENTRY_SIZE, /* plt_entry_size */ + elf_x86_64_tlsdesc_plt_entry, /* plt_tlsdesc_entry */ + LAZY_PLT_ENTRY_SIZE, /* plt_tlsdesc_entry_size */ + 6, /* plt_tlsdesc_got1_offset */ + 12, /* plt_tlsdesc_got2_offset */ + 10, /* plt_tlsdesc_got1_insn_end */ + 16, /* plt_tlsdesc_got2_insn_end */ 2, /* plt0_got1_offset */ 8, /* plt0_got2_offset */ 12, /* plt0_got2_insn_end */ @@ -4417,19 +4449,12 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd, if (htab->tlsdesc_plt) { - /* The TLSDESC entry in a lazy procedure linkage table. */ - static const bfd_byte tlsdesc_plt_entry[LAZY_PLT_ENTRY_SIZE] = - { - 0xf3, 0x0f, 0x1e, 0xfa, /* endbr64 */ - 0xff, 0x35, 8, 0, 0, 0, /* pushq GOT+8(%rip) */ - 0xff, 0x25, 16, 0, 0, 0 /* jmpq *GOT+TDG(%rip) */ - }; - bfd_put_64 (output_bfd, (bfd_vma) 0, htab->elf.sgot->contents + htab->tlsdesc_got); memcpy (htab->elf.splt->contents + htab->tlsdesc_plt, - tlsdesc_plt_entry, LAZY_PLT_ENTRY_SIZE); + htab->lazy_plt->plt_tlsdesc_entry, + htab->lazy_plt->plt_tlsdesc_entry_size); /* Add offset for pushq GOT+8(%rip), since ENDBR64 uses 4 bytes and the instruction uses 6 bytes, subtract these @@ -4441,10 +4466,10 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd, - htab->elf.splt->output_section->vma - htab->elf.splt->output_offset - htab->tlsdesc_plt - - 4 - 6), + - htab->lazy_plt->plt_tlsdesc_got1_insn_end), (htab->elf.splt->contents + htab->tlsdesc_plt - + 4 + 2)); + + htab->lazy_plt->plt_tlsdesc_got1_offset)); /* Add offset for indirect branch via GOT+TDG, where TDG stands for htab->tlsdesc_got, subtracting the offset to the end of that instruction. */ @@ -4455,9 +4480,10 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd, - htab->elf.splt->output_section->vma - htab->elf.splt->output_offset - htab->tlsdesc_plt - - 4 - 6 - 6), + - htab->lazy_plt->plt_tlsdesc_got2_insn_end), (htab->elf.splt->contents - + htab->tlsdesc_plt + 4 + 6 + 2)); + + htab->tlsdesc_plt + + htab->lazy_plt->plt_tlsdesc_got2_offset)); } } @@ -5246,6 +5272,12 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_nacl_plt = NACL_PLT_ENTRY_SIZE, /* plt0_entry_size */ elf_x86_64_nacl_plt_entry, /* plt_entry */ NACL_PLT_ENTRY_SIZE, /* plt_entry_size */ + elf_x86_64_nacl_plt0_entry, /* plt_tlsdesc_entry */ + NACL_PLT_ENTRY_SIZE, /* plt_tlsdesc_entry_size */ + 2, /* plt_tlsdesc_got1_offset */ + 9, /* plt_tlsdesc_got2_offset */ + 6, /* plt_tlsdesc_got1_insn_end */ + 13, /* plt_tlsdesc_got2_insn_end */ 2, /* plt0_got1_offset */ 9, /* plt0_got2_offset */ 13, /* plt0_got2_insn_end */ diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h index 8f67c23a9fe..6a5609467d5 100644 --- a/bfd/elfxx-x86.h +++ b/bfd/elfxx-x86.h @@ -285,16 +285,30 @@ struct elf_x86_link_hash_entry struct elf_x86_lazy_plt_layout { - /* The first entry in an absolute lazy procedure linkage table looks - like this. */ + /* The first entry in a lazy procedure linkage table looks like this. */ const bfd_byte *plt0_entry; unsigned int plt0_entry_size; /* Size of PLT0 entry. */ - /* Later entries in an absolute lazy procedure linkage table look - like this. */ + /* Later entries in a lazy procedure linkage table look like this. */ const bfd_byte *plt_entry; unsigned int plt_entry_size; /* Size of each PLT entry. */ + /* The TLSDESC entry in a lazy procedure linkage table looks like + this. This is for x86-64 only. */ + const bfd_byte *plt_tlsdesc_entry; + unsigned int plt_tlsdesc_entry_size; /* Size of TLSDESC entry. */ + + /* Offsets into the TLSDESC entry that are to be replaced with + GOT+8 and GOT+TDG. These are for x86-64 only. */ + unsigned int plt_tlsdesc_got1_offset; + unsigned int plt_tlsdesc_got2_offset; + + /* Offset of the end of the PC-relative instructions containing + plt_tlsdesc_got1_offset and plt_tlsdesc_got2_offset. These + are for x86-64 only. */ + unsigned int plt_tlsdesc_got1_insn_end; + unsigned int plt_tlsdesc_got2_insn_end; + /* Offsets into plt0_entry that are to be replaced with GOT[1] and GOT[2]. */ unsigned int plt0_got1_offset; @@ -336,10 +350,11 @@ struct elf_x86_lazy_plt_layout struct elf_x86_non_lazy_plt_layout { - /* Entries in an absolute non-lazy procedure linkage table look like - this. */ + /* Entries in a non-lazy procedure linkage table look like this. */ const bfd_byte *plt_entry; - /* Entries in a PIC non-lazy procedure linkage table look like this. */ + /* Entries in a PIC non-lazy procedure linkage table look like this. + This is only used for i386 where absolute PLT and PIC PLT are + different. */ const bfd_byte *pic_plt_entry; unsigned int plt_entry_size; /* Size of each PLT entry. */ @@ -358,9 +373,7 @@ struct elf_x86_non_lazy_plt_layout struct elf_x86_plt_layout { - /* The first entry in a lazy procedure linkage table looks like this. - This is only used for i386 where absolute PLT0 and PIC PLT0 are - different. */ + /* The first entry in a lazy procedure linkage table looks like this. */ const bfd_byte *plt0_entry; /* Entries in a procedure linkage table look like this. */ const bfd_byte *plt_entry; -- 2.30.2