This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] x86-64: Add TLSDESC fields to elf_x86_lazy_plt_layout


On Sat, Mar 24, 2018 at 8:45 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> The TLSDESC entry in a lazy procedure linkage table is called indirectly
> with "callq *(%rax)".  This patch adds an ENDBR64 to support indirect
> branch tracking in Intel CET.  The TLSDESC PLT entry now looks like:
>
> 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)  */
>
> The BND prefix isn't needed since MPX isn't used for TLSDESC.
>
> I will check it into master branch and backport it to 2.30 branch.
>
>
> H.J.
> ---
> bfd/
>
>         PR ld/23000
>         * elf64-x86-64.c (elf_x86_64_finish_dynamic_sections): Add
>         ENDBR64 to the TLSDESC PLT entry.
>
> ld/
>         PR ld/23000
>         * testsuite/ld-x86-64/tlsdesc.pd: Updated.
>

I am checking in this patch to fix

FAIL: TLS descriptor -fpic -shared transitions

for x86_64-nacl.   I will backport it to 2.30 branch.

-- 
H.J.
From 92e68c1d65f844c0027f471a0c9e1722d781ef7d Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
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 f190b9f3be..5e1724b5f2 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,32 @@
+2018-05-28  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* 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  <hongjiu.lu@intel.com>
 
 	PR ld/23238
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 3dd709a10e..49797dcbfa 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 e5a4dbcd51..4349561f3c 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 8f67c23a9f..6a5609467d 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.17.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]