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: Clear extern_protected_data for GNU_PROPERTY_NO_COPY_ON_PROTECTED


On Wed, Aug 23, 2017 at 8:01 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Wed, Aug 23, 2017 at 7:52 AM, Michael Matz <matz@suse.de> wrote:
>> Hi,
>>
>> On Wed, 23 Aug 2017, H.J. Lu wrote:
>>
>>> >> STV_PROTECTED is meaningful only if there is a dynamic relocation.
>>> >> When the relocation is already resolved by the linker at run-time via
>>> >> SYMBOLIC_BIND, the symbol is not preemptable regardless if it is
>>> >> STV_PROTECTED or not.
>>> >
>>> > The symbolic_bind hack is only necessary because protected symbols are
>>> > broken on x86 and not usable for what they are intended.  In a better
>>>
>>> It is the direct result of copy relocation.
>>
>> Yes, and the fix is to not do copy relocs for protected symbols, instead
>> of breaking the reason d'etre for protected visibility.
>
> I added GNU_PROPERTY_NO_COPY_ON_PROTECTED to GNU
> program property.  Compiler can generate reference via GOT and set
> GNU_PROPERTY_NO_COPY_ON_PROTECTED.    This reminds me
> to update linker to check GNU_PROPERTY_NO_COPY_ON_PROTECTED.
>

This is the patch I am checking in.


-- 
H.J.
From 5ad868bd80a6a97beaccbb01054dfeb3ba1de415 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 23 Aug 2017 09:38:51 -0700
Subject: [PATCH] x86: Clear extern_protected_data for
 GNU_PROPERTY_NO_COPY_ON_PROTECTED

When GNU_PROPERTY_NO_COPY_ON_PROTECTED is set, it indicates that there
are no copy relocations against protected data symbols.  When linker
sees GNU_PROPERTY_NO_COPY_ON_PROTECTED on any input relocatable file,
it sets extern_protected_data to FALSE.

bfd/

	* elf32-i386.c (elf_i386_link_setup_gnu_properties): Set
	extern_protected_data to FALSE if GNU_PROPERTY_NO_COPY_ON_PROTECTED
	is set on any input relocatable file.
	* elf64-x86-64.c (elf_x86_64_link_setup_gnu_properties): Likewise.

ld/

	* testsuite/ld-i386/i386.exp: Run protected7.
	* testsuite/ld-i386/protected7.d: New file.
	* testsuite/ld-i386/protected7.s: Likewise.
	* testsuite/ld-x86-64/protected8.d: Likewise.
	* testsuite/ld-x86-64/protected8.s: Likewise.
	* testsuite/ld-x86-64/x86-64.exp: Run protected8.
---
 bfd/elf32-i386.c                    | 116 +++++++++++++++++++++---------------
 bfd/elf64-x86-64.c                  | 114 ++++++++++++++++++++---------------
 ld/testsuite/ld-i386/i386.exp       |   1 +
 ld/testsuite/ld-i386/protected7.d   |  13 ++++
 ld/testsuite/ld-i386/protected7.s   |  31 ++++++++++
 ld/testsuite/ld-x86-64/protected8.d |  13 ++++
 ld/testsuite/ld-x86-64/protected8.s |  31 ++++++++++
 ld/testsuite/ld-x86-64/x86-64.exp   |   1 +
 8 files changed, 225 insertions(+), 95 deletions(-)
 create mode 100644 ld/testsuite/ld-i386/protected7.d
 create mode 100644 ld/testsuite/ld-i386/protected7.s
 create mode 100644 ld/testsuite/ld-x86-64/protected8.d
 create mode 100644 ld/testsuite/ld-x86-64/protected8.s

diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index d5477c4215..1009c17ff2 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -6780,66 +6780,90 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
   unsigned int plt_alignment, features;
   struct elf_i386_link_hash_table *htab;
   bfd *pbfd;
+  bfd *ebfd = NULL;
+  elf_property *prop;
 
   features = 0;
   if (info->ibt)
     features = GNU_PROPERTY_X86_FEATURE_1_IBT;
   if (info->shstk)
     features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
-  if (features)
-    {
-      /* Turn on GNU_PROPERTY_X86_FEATURE_1_IBT and
-	 GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
-      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 and
-		   GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
-		prop->u.number |= features;
-		prop->pr_kind = property_number;
-		break;
-	      }
-	  }
+  /* Find a normal input file with GNU property note.  */
+  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 (pbfd == NULL && ebfd != NULL)
+	if (elf_properties (pbfd) != NULL)
+	  break;
+      }
+
+  if (ebfd != NULL)
+    {
+      if (features)
 	{
-	  /* Create GNU_PROPERTY_X86_FEATURE_1_IBT if needed.  */
+	  /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and
+	     GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
 	  prop = _bfd_elf_get_property (ebfd,
 					GNU_PROPERTY_X86_FEATURE_1_AND,
 					4);
-	  prop->u.number = features;
+	  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"));
+	  /* Create the GNU property note section if needed.  */
+	  if (pbfd == NULL)
+	    {
+	      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;
+	      if (!bfd_set_section_alignment (ebfd, sec, 2))
+		{
+error_alignment:
+		  info->callbacks->einfo (_("%F%A: failed to align section\n"),
+					  sec);
+		}
 
-	  elf_section_type (sec) = SHT_NOTE;
+	      elf_section_type (sec) = SHT_NOTE;
+	    }
 	}
+
+      /* Check GNU_PROPERTY_NO_COPY_ON_PROTECTED.  */
+      for (; pbfd != NULL; pbfd = pbfd->link.next)
+	if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
+	    && (pbfd->flags
+		& (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
+	  {
+	    elf_property_list *p;
+
+	    /* The property list is sorted in order of type.  */
+	    for (p = elf_properties (pbfd); p != NULL; p = p->next)
+	      {
+		if (GNU_PROPERTY_NO_COPY_ON_PROTECTED
+		    == p->property.pr_type)
+		  {
+		    /* Clear extern_protected_data if
+		       GNU_PROPERTY_NO_COPY_ON_PROTECTED is
+		       set on any input relocatable file.  */
+		    info->extern_protected_data = FALSE;
+		    break;
+		  }
+		else if (GNU_PROPERTY_NO_COPY_ON_PROTECTED
+			 < p->property.pr_type)
+		  break;
+	      }
+	  }
     }
 
   pbfd = _bfd_elf_link_setup_gnu_properties (info);
@@ -7116,11 +7140,7 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
       if (sec != NULL
 	  && !bfd_set_section_alignment (sec->owner, sec,
 					 plt_alignment))
-	{
-error_alignment:
-	  info->callbacks->einfo (_("%F%A: failed to align section\n"),
-				  sec);
-	}
+	goto error_alignment;
     }
 
   return pbfd;
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 8a6bd6285c..244db80ed6 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -7302,71 +7302,91 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
   unsigned int plt_alignment, features;
   struct elf_x86_64_link_hash_table *htab;
   bfd *pbfd;
+  bfd *ebfd = NULL;
+  elf_property *prop;
 
   features = 0;
   if (info->ibt)
     features = GNU_PROPERTY_X86_FEATURE_1_IBT;
   if (info->shstk)
     features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
-  if (features)
-    {
-      /* Turn on GNU_PROPERTY_X86_FEATURE_1_IBT and
-	 GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
-      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 and
-		   GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
-		prop->u.number |= features;
-		prop->pr_kind = property_number;
-		break;
-	      }
-	  }
+  /* Find a normal input file with GNU property note.  */
+  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)
+	  break;
+      }
 
-      if (pbfd == NULL && ebfd != NULL)
+  if (ebfd != NULL)
+    {
+      if (features)
 	{
-	  /* Create GNU_PROPERTY_X86_FEATURE_1_IBT if needed.  */
+	  /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and
+	     GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
 	  prop = _bfd_elf_get_property (ebfd,
 					GNU_PROPERTY_X86_FEATURE_1_AND,
 					4);
-	  prop->u.number = features;
+	  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,
-					  ABI_64_P (ebfd) ? 3 : 2))
+	  /* Create the GNU property note section if needed.  */
+	  if (pbfd == NULL)
 	    {
+	      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,
+					      ABI_64_P (ebfd) ? 3 : 2))
+		{
 error_alignment:
-	      info->callbacks->einfo (_("%F%A: failed to align section\n"),
-				      sec);
-	    }
+		  info->callbacks->einfo (_("%F%A: failed to align section\n"),
+					  sec);
+		}
 
-	  elf_section_type (sec) = SHT_NOTE;
+	      elf_section_type (sec) = SHT_NOTE;
+	    }
 	}
+
+      /* Check GNU_PROPERTY_NO_COPY_ON_PROTECTED.  */
+      for (; pbfd != NULL; pbfd = pbfd->link.next)
+	if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
+	    && (pbfd->flags
+		& (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
+	  {
+	    elf_property_list *p;
+
+	    /* The property list is sorted in order of type.  */
+	    for (p = elf_properties (pbfd); p != NULL; p = p->next)
+	      {
+		if (GNU_PROPERTY_NO_COPY_ON_PROTECTED
+		    == p->property.pr_type)
+		  {
+		    /* Clear extern_protected_data if
+		       GNU_PROPERTY_NO_COPY_ON_PROTECTED is
+		       set on any input relocatable file.  */
+		    info->extern_protected_data = FALSE;
+		    break;
+		  }
+		else if (GNU_PROPERTY_NO_COPY_ON_PROTECTED
+			 < p->property.pr_type)
+		  break;
+	      }
+	  }
     }
 
   pbfd = _bfd_elf_link_setup_gnu_properties (info);
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 27d622eab4..3c5de021b2 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -308,6 +308,7 @@ run_dump_test "protected4"
 run_dump_test "protected5"
 run_dump_test "protected6a"
 run_dump_test "protected6b"
+run_dump_test "protected7"
 run_dump_test "tlspie1"
 run_dump_test "tlspie2"
 run_dump_test "tlspie3a"
diff --git a/ld/testsuite/ld-i386/protected7.d b/ld/testsuite/ld-i386/protected7.d
new file mode 100644
index 0000000000..aafa2d81b3
--- /dev/null
+++ b/ld/testsuite/ld-i386/protected7.d
@@ -0,0 +1,13 @@
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -drw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+[a-f0-9]+ <bar>:
+[ 	]*[a-f0-9]+:	8b 81 [a-f0-9][a-f0-9] [a-f0-9][a-f0-9] 00 00    	mov    0x[a-f0-9]+\(%ecx\),%eax
+[ 	]*[a-f0-9]+:	c3                   	ret    
+#pass
diff --git a/ld/testsuite/ld-i386/protected7.s b/ld/testsuite/ld-i386/protected7.s
new file mode 100644
index 0000000000..bc2bc91958
--- /dev/null
+++ b/ld/testsuite/ld-i386/protected7.s
@@ -0,0 +1,31 @@
+	.protected	foo
+.globl foo
+	.data
+	.align 4
+	.type	foo, @object
+	.size	foo, 4
+foo:
+	.long	1
+	.text
+.globl bar
+	.type	bar, @function
+bar:
+	movl	foo@GOTOFF(%ecx), %eax
+	ret
+	.size	bar, .-bar
+
+	.section ".note.gnu.property", "a"
+	.p2align 2
+	.long 1f - 0f		/* name length.  */
+	.long 3f - 1f		/* data length.  */
+	/* NT_GNU_PROPERTY_TYPE_0 */
+	.long 5			/* note type.  */
+0:
+	.asciz "GNU"		/* vendor name.  */
+1:
+	.p2align 2
+	/* GNU_PROPERTY_NO_COPY_ON_PROTECTED */
+	.long 2			/* pr_type.  */
+	.long 0			/* pr_datasz.  */
+	.p2align 2
+3:
diff --git a/ld/testsuite/ld-x86-64/protected8.d b/ld/testsuite/ld-x86-64/protected8.d
new file mode 100644
index 0000000000..22a36ac4c8
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/protected8.d
@@ -0,0 +1,13 @@
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+[a-f0-9]+ <bar>:
+[ 	]*[a-f0-9]+:	8b 05 ([0-9a-f]{2} ){4} *	mov    0x[a-f0-9]+\(%rip\),%eax        # [a-f0-9]+ <foo>
+[ 	]*[a-f0-9]+:	c3                   	retq *
+#pass
diff --git a/ld/testsuite/ld-x86-64/protected8.s b/ld/testsuite/ld-x86-64/protected8.s
new file mode 100644
index 0000000000..314433d0d1
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/protected8.s
@@ -0,0 +1,31 @@
+	.protected	foo
+.globl foo
+	.data
+	.align 4
+	.type	foo, @object
+	.size	foo, 4
+foo:
+	.long	1
+	.text
+.globl bar
+	.type	bar, @function
+bar:
+	movl	foo(%rip), %eax
+	ret
+	.size	bar, .-bar
+
+	.section ".note.gnu.property", "a"
+	.p2align 3
+	.long 1f - 0f		/* name length.  */
+	.long 3f - 2f		/* data length.  */
+	/* NT_GNU_PROPERTY_TYPE_0 */
+	.long 5			/* note type.  */
+0:	.asciz "GNU"		/* vendor name.  */
+1:
+	.p2align 3
+2:
+	/* GNU_PROPERTY_NO_COPY_ON_PROTECTED */
+	.long 2			/* pr_type.  */
+	.long 0			/* pr_datasz.  */
+	.p2align 3
+3:
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 46311577e4..0b795df60b 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -291,6 +291,7 @@ run_dump_test "protected6a"
 run_dump_test "protected6b"
 run_dump_test "protected7a"
 run_dump_test "protected7b"
+run_dump_test "protected8"
 run_dump_test "tlsle1"
 run_dump_test "tlspie1"
 run_dump_test "tlspie2a"
-- 
2.13.5


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