[committed, PATCH] x86: Add _bfd_x86_elf_link_setup_gnu_properties

H.J. Lu hongjiu.lu@intel.com
Fri Sep 1 14:57:00 GMT 2017


Extract the common parts of elf_i386_link_setup_gnu_properties and
elf_x86_64_link_setup_gnu_properties into a new function.

For x86-64, since PIC PLT layouts are the same as non-PIC PLT layouts,
initialize pic_plt0_entry and pic_plt_entry fields in PLT layouts with
the non-PIC PLT entries.

H.J.
---
	* elf32-i386.c (elf_i386_link_setup_gnu_properties): Updated.
	Call _bfd_x86_elf_link_setup_gnu_properties.
	* elf64-x86-64.c (elf_x86_lazy_plt_layout): Initialize
	pic_plt0_entry and pic_plt_entry fields with the non-PIC PLT
	entries.
	(elf_x86_64_non_lazy_plt): Likewise.
	(elf_x86_64_lazy_bnd_plt): Likewise.
	(elf_x86_64_non_lazy_bnd_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_nacl_plt): Likewise.
	(elf_x86_64_link_setup_gnu_properties): Updated.  Call
	_bfd_x86_elf_link_setup_gnu_properties.
	* elfxx-x86.c: Include elf-vxworks.h".
	(_bfd_x86_elf_link_setup_gnu_properties): New function.
	* elfxx-x86.h (elf_x86_lazy_plt_layout): Remove "for i386 only"
	comments for pic_plt0_entry and pic_plt_entry.
	(elf_x86_non_lazy_plt_layout): Likewise.
	(elf_x86_plt_layout_table): New.
	(_bfd_x86_elf_link_setup_gnu_properties): Likewise.
---
 bfd/elf32-i386.c   | 355 +++-------------------------------------------
 bfd/elf64-x86-64.c | 410 +++++------------------------------------------------
 bfd/elfxx-x86.c    | 390 ++++++++++++++++++++++++++++++++++++++++++++++++++
 bfd/elfxx-x86.h    |  31 +++-
 4 files changed, 469 insertions(+), 717 deletions(-)

diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index a983301bfb..a0d4285659 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -5825,354 +5825,35 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
 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;
-  bfd_boolean use_ibt_plt;
-  unsigned int plt_alignment, features;
-  struct elf_x86_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;
-
-  /* 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 (ebfd != NULL && features)
-    {
-      /* 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->pr_kind = property_number;
-
-      /* 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))
-	    {
-error_alignment:
-	      info->callbacks->einfo (_("%F%A: failed to align section\n"),
-				      sec);
-	    }
-
-	  elf_section_type (sec) = SHT_NOTE;
-	}
-    }
-
-  pbfd = _bfd_elf_link_setup_gnu_properties (info);
-
-  if (bfd_link_relocatable (info))
-    return pbfd;
-
-  htab = elf_x86_hash_table (info, I386_ELF_DATA);
-  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)
-    {
-      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 (bfd_get_flavour (abfd) == bfd_target_elf_flavour
-		&& (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
-     still be used with LD_AUDIT or LD_PROFILE if PLT entry is used for
-     canonical function address.  */
-  htab->plt.has_plt0 = 1;
-  normal_target = FALSE;
+  struct elf_x86_plt_layout_table plt_layout;
 
+  plt_layout.normal_target = FALSE;
+  plt_layout.is_vxworks = FALSE;
   switch (get_elf_i386_backend_data (info->output_bfd)->os)
     {
     case is_normal:
-      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;
+      plt_layout.lazy_plt = &elf_i386_lazy_plt;
+      plt_layout.non_lazy_plt = &elf_i386_non_lazy_plt;
+      plt_layout.lazy_ibt_plt = &elf_i386_lazy_ibt_plt;
+      plt_layout.non_lazy_ibt_plt = &elf_i386_non_lazy_ibt_plt;
+      plt_layout.normal_target = TRUE;
       break;
     case is_vxworks:
-      htab->lazy_plt = &elf_i386_lazy_plt;
-      htab->non_lazy_plt = NULL;
-      if (!elf_vxworks_create_dynamic_sections (dynobj, info,
-						&htab->srelplt2))
-	info->callbacks->einfo (_("%F: failed to create VxWorks dynamic sections\n"));
+      plt_layout.lazy_plt = &elf_i386_lazy_plt;
+      plt_layout.non_lazy_plt = NULL;
+      plt_layout.lazy_ibt_plt = NULL;
+      plt_layout.non_lazy_ibt_plt = NULL;
+      plt_layout.is_vxworks = TRUE;
       break;
     case is_nacl:
-      htab->lazy_plt = &elf_i386_nacl_plt;
-      htab->non_lazy_plt = NULL;
+      plt_layout.lazy_plt = &elf_i386_nacl_plt;
+      plt_layout.non_lazy_plt = NULL;
+      plt_layout.lazy_ibt_plt = NULL;
+      plt_layout.non_lazy_ibt_plt = NULL;
       break;
     }
 
-  pltsec = htab->elf.splt;
-
-  /* If the non-lazy PLT is available, use it for all PLT entries if
-     there are no PLT0 or no .plt section.  */
-  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;
-      else
-	htab->plt.plt_entry = htab->non_lazy_plt->plt_entry;
-      htab->plt.plt_entry_size = htab->non_lazy_plt->plt_entry_size;
-      htab->plt.plt_got_offset = htab->non_lazy_plt->plt_got_offset;
-      htab->plt.eh_frame_plt_size
-	= htab->non_lazy_plt->eh_frame_plt_size;
-      htab->plt.eh_frame_plt = htab->non_lazy_plt->eh_frame_plt;
-    }
-  else
-    {
-      lazy_plt = TRUE;
-      if (bfd_link_pic (info))
-	{
-	  htab->plt.plt0_entry = htab->lazy_plt->pic_plt0_entry;
-	  htab->plt.plt_entry = htab->lazy_plt->pic_plt_entry;
-	}
-      else
-	{
-	  htab->plt.plt0_entry = htab->lazy_plt->plt0_entry;
-	  htab->plt.plt_entry = htab->lazy_plt->plt_entry;
-	}
-
-      htab->plt.plt_entry_size = htab->lazy_plt->plt_entry_size;
-      htab->plt.plt_got_offset = htab->lazy_plt->plt_got_offset;
-      htab->plt.eh_frame_plt_size = htab->lazy_plt->eh_frame_plt_size;
-      htab->plt.eh_frame_plt = htab->lazy_plt->eh_frame_plt;
-    }
-
-  /* This is unused for i386.  */
-  htab->plt.plt_got_insn_size = 0;
-
-  /* Return if there are no normal input files.  */
-  if (dynobj == NULL)
-    return pbfd;
-
-  /* Since create_dynamic_sections isn't always called, but GOT
-     relocations need GOT sections, create them here so that we
-     don't need to do it in check_relocs.  */
-  if (htab->elf.sgot == NULL
-      && !_bfd_elf_create_got_section (dynobj, info))
-    info->callbacks->einfo (_("%F: failed to create GOT sections\n"));
-
-  /* Create the ifunc sections here so that check_relocs can be
-     simplified.  */
-  if (!_bfd_elf_create_ifunc_sections (dynobj, info))
-    info->callbacks->einfo (_("%F: failed to create ifunc sections\n"));
-
-  plt_alignment = bfd_log2 (htab->plt.plt_entry_size);
-
-  if (pltsec != NULL)
-    {
-      /* Whe creating executable, set the contents of the .interp
-	 section to the interpreter.  */
-      if (bfd_link_executable (info) && !info->nointerp)
-	{
-	  asection *s = bfd_get_linker_section (dynobj, ".interp");
-	  if (s == NULL)
-	    abort ();
-	  s->size = htab->dynamic_interpreter_size;
-	  s->contents = (unsigned char *) htab->dynamic_interpreter;
-	  htab->interp = s;
-	}
-
-      /* Don't change PLT section alignment for NaCl since it uses
-	 64-byte PLT entry and sets PLT section alignment to 32
-	 bytes.  */
-      if (normal_target)
-	{
-	  const struct elf_backend_data *bed
-	    = get_elf_backend_data (dynobj);
-	  flagword pltflags = (bed->dynamic_sec_flags
-			       | SEC_ALLOC
-			       | SEC_CODE
-			       | SEC_LOAD
-			       | SEC_READONLY);
-	  unsigned int non_lazy_plt_alignment
-	    = bfd_log2 (htab->non_lazy_plt->plt_entry_size);
-
-	  sec = pltsec;
-	  if (!bfd_set_section_alignment (sec->owner, sec,
-					  plt_alignment))
-	    goto error_alignment;
-
-	  /* Create the GOT procedure linkage table.  */
-	  sec = bfd_make_section_anyway_with_flags (dynobj,
-						    ".plt.got",
-						    pltflags);
-	  if (sec == NULL)
-	    info->callbacks->einfo (_("%F: failed to create GOT PLT section\n"));
-
-	  if (!bfd_set_section_alignment (dynobj, sec,
-					  non_lazy_plt_alignment))
-	    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)
-	{
-	  flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
-			    | SEC_HAS_CONTENTS | SEC_IN_MEMORY
-			    | SEC_LINKER_CREATED);
-
-	  sec = bfd_make_section_anyway_with_flags (dynobj,
-						    ".eh_frame",
-						    flags);
-	  if (sec == NULL)
-	    info->callbacks->einfo (_("%F: failed to create PLT .eh_frame section\n"));
-
-	  if (!bfd_set_section_alignment (dynobj, sec, 2))
-	    goto error_alignment;
-
-	  htab->plt_eh_frame = sec;
-
-	  if (htab->plt_got != NULL)
-	    {
-	      sec = bfd_make_section_anyway_with_flags (dynobj,
-							".eh_frame",
-							flags);
-	      if (sec == NULL)
-		info->callbacks->einfo (_("%F: failed to create GOT PLT .eh_frame section\n"));
-
-	      if (!bfd_set_section_alignment (dynobj, sec, 2))
-		goto error_alignment;
-
-	      htab->plt_got_eh_frame = sec;
-	    }
-
-	  if (htab->plt_second != NULL)
-	    {
-	      sec = bfd_make_section_anyway_with_flags (dynobj,
-							".eh_frame",
-							flags);
-	      if (sec == NULL)
-		info->callbacks->einfo (_("%F: failed to create the second PLT .eh_frame section\n"));
-
-	      if (!bfd_set_section_alignment (dynobj, sec, 2))
-		goto error_alignment;
-
-	      htab->plt_second_eh_frame = sec;
-	    }
-	}
-    }
-
-  if (normal_target)
-    {
-      /* The .iplt section is used for IFUNC symbols in static
-	 executables.  */
-      sec = htab->elf.iplt;
-      if (sec != NULL
-	  && !bfd_set_section_alignment (sec->owner, sec,
-					 plt_alignment))
-	goto error_alignment;
-    }
-
-  return pbfd;
+  return _bfd_x86_elf_link_setup_gnu_properties (info, &plt_layout);
 }
 
 #define TARGET_LITTLE_SYM		i386_elf32_vec
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 969a053e0b..547173b0a7 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -848,8 +848,8 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_plt =
     6,                                  /* plt_got_insn_size */
     LAZY_PLT_ENTRY_SIZE,                /* plt_plt_insn_end */
     6,                                  /* plt_lazy_offset */
-    NULL,                               /* pic_plt0_entry */
-    NULL,                               /* pic_plt_entry */
+    elf_x86_64_lazy_plt0_entry,         /* pic_plt0_entry */
+    elf_x86_64_lazy_plt_entry,          /* pic_plt_entry */
     elf_x86_64_eh_frame_lazy_plt,       /* eh_frame_plt */
     sizeof (elf_x86_64_eh_frame_lazy_plt) /* eh_frame_plt_size */
   };
@@ -857,7 +857,7 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_plt =
 static const struct elf_x86_non_lazy_plt_layout elf_x86_64_non_lazy_plt =
   {
     elf_x86_64_non_lazy_plt_entry,      /* plt_entry */
-    NULL,                               /* pic_plt_entry */
+    elf_x86_64_non_lazy_plt_entry,      /* pic_plt_entry */
     NON_LAZY_PLT_ENTRY_SIZE,            /* plt_entry_size */
     2,                                  /* plt_got_offset */
     6,                                  /* plt_got_insn_size */
@@ -880,8 +880,8 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_bnd_plt =
     1+6,                                /* plt_got_insn_size */
     11,                                 /* plt_plt_insn_end */
     0,                                  /* plt_lazy_offset */
-    NULL,                               /* pic_plt0_entry */
-    NULL,                               /* pic_plt_entry */
+    elf_x86_64_lazy_bnd_plt0_entry,     /* pic_plt0_entry */
+    elf_x86_64_lazy_bnd_plt_entry,      /* pic_plt_entry */
     elf_x86_64_eh_frame_lazy_bnd_plt,   /* eh_frame_plt */
     sizeof (elf_x86_64_eh_frame_lazy_bnd_plt) /* eh_frame_plt_size */
   };
@@ -889,7 +889,7 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_bnd_plt =
 static const struct elf_x86_non_lazy_plt_layout elf_x86_64_non_lazy_bnd_plt =
   {
     elf_x86_64_non_lazy_bnd_plt_entry,  /* plt_entry */
-    NULL,                               /* pic_plt_entry */
+    elf_x86_64_non_lazy_bnd_plt_entry,  /* pic_plt_entry */
     NON_LAZY_PLT_ENTRY_SIZE,            /* plt_entry_size */
     1+2,                                /* plt_got_offset */
     1+6,                                /* plt_got_insn_size */
@@ -912,8 +912,8 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_ibt_plt =
     4+1+6,                              /* plt_got_insn_size */
     4+1+5+5,                            /* plt_plt_insn_end */
     0,                                  /* plt_lazy_offset */
-    NULL,                               /* pic_plt0_entry */
-    NULL,                               /* pic_plt_entry */
+    elf_x86_64_lazy_bnd_plt0_entry,     /* pic_plt0_entry */
+    elf_x86_64_lazy_ibt_plt_entry,      /* pic_plt_entry */
     elf_x86_64_eh_frame_lazy_ibt_plt,   /* eh_frame_plt */
     sizeof (elf_x86_64_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */
   };
@@ -933,8 +933,8 @@ static const struct elf_x86_lazy_plt_layout elf_x32_lazy_ibt_plt =
     4+6,                                /* plt_got_insn_size */
     4+5+5,                              /* plt_plt_insn_end */
     0,                                  /* plt_lazy_offset */
-    NULL,                               /* pic_plt0_entry */
-    NULL,                               /* pic_plt_entry */
+    elf_x86_64_lazy_plt0_entry,         /* pic_plt0_entry */
+    elf_x32_lazy_ibt_plt_entry,         /* pic_plt_entry */
     elf_x32_eh_frame_lazy_ibt_plt,      /* eh_frame_plt */
     sizeof (elf_x32_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */
   };
@@ -942,7 +942,7 @@ static const struct elf_x86_lazy_plt_layout elf_x32_lazy_ibt_plt =
 static const struct elf_x86_non_lazy_plt_layout elf_x86_64_non_lazy_ibt_plt =
   {
     elf_x86_64_non_lazy_ibt_plt_entry,  /* plt_entry */
-    NULL,                               /* pic_plt_entry */
+    elf_x86_64_non_lazy_ibt_plt_entry,  /* pic_plt_entry */
     LAZY_PLT_ENTRY_SIZE,                /* plt_entry_size */
     4+1+2,                              /* plt_got_offset */
     4+1+6,                              /* plt_got_insn_size */
@@ -953,7 +953,7 @@ static const struct elf_x86_non_lazy_plt_layout elf_x86_64_non_lazy_ibt_plt =
 static const struct elf_x86_non_lazy_plt_layout elf_x32_non_lazy_ibt_plt =
   {
     elf_x32_non_lazy_ibt_plt_entry,     /* plt_entry */
-    NULL,                               /* pic_plt_entry */
+    elf_x32_non_lazy_ibt_plt_entry,     /* pic_plt_entry */
     LAZY_PLT_ENTRY_SIZE,                /* plt_entry_size */
     4+2,                                /* plt_got_offset */
     4+6,                                /* plt_got_insn_size */
@@ -6380,386 +6380,44 @@ elf_x86_64_relocs_compatible (const bfd_target *input,
 static bfd *
 elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
 {
-  bfd_boolean normal_target;
-  bfd_boolean lazy_plt;
-  asection *sec, *pltsec;
-  bfd *dynobj;
-  bfd_boolean use_ibt_plt;
-  unsigned int plt_alignment, features;
-  struct elf_x86_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;
-
-  /* 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;
-      }
+  struct elf_x86_plt_layout_table plt_layout;
 
-  if (ebfd != NULL && features)
+  plt_layout.is_vxworks = FALSE;
+  if (get_elf_x86_64_backend_data (info->output_bfd)->os == is_normal)
     {
-      /* 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->pr_kind = property_number;
-
-      /* Create the GNU property note section if needed.  */
-      if (pbfd == NULL)
+      if (info->bndplt)
 	{
-	  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);
-	    }
-
-	  elf_section_type (sec) = SHT_NOTE;
-	}
-    }
-
-  pbfd = _bfd_elf_link_setup_gnu_properties (info);
-
-  if (bfd_link_relocatable (info))
-    return pbfd;
-
-  htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
-  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)
-    {
-      if (pbfd != NULL)
-	{
-	  htab->elf.dynobj = pbfd;
-	  dynobj = pbfd;
+	  plt_layout.lazy_plt = &elf_x86_64_lazy_bnd_plt;
+	  plt_layout.non_lazy_plt = &elf_x86_64_non_lazy_bnd_plt;
 	}
       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 (bfd_get_flavour (abfd) == bfd_target_elf_flavour
-		&& (abfd->flags
-		    & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
-	      {
-		htab->elf.dynobj = abfd;
-		dynobj = abfd;
-		break;
-	      }
+	  plt_layout.lazy_plt = &elf_x86_64_lazy_plt;
+	  plt_layout.non_lazy_plt = &elf_x86_64_non_lazy_plt;
 	}
-    }
-
-  /* Even when lazy binding is disabled by "-z now", the PLT0 entry may
-     still be used with LD_AUDIT or LD_PROFILE if PLT entry is used for
-     canonical function address.  */
-  htab->plt.has_plt0 = 1;
 
-  if (get_elf_x86_64_backend_data (info->output_bfd)->os
-      == is_normal)
-    {
-      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)
+      if (ABI_64_P (info->output_bfd))
 	{
-	  htab->lazy_plt = &elf_x86_64_lazy_bnd_plt;
-	  htab->non_lazy_plt = &elf_x86_64_non_lazy_bnd_plt;
+	  plt_layout.lazy_ibt_plt = &elf_x86_64_lazy_ibt_plt;
+	  plt_layout.non_lazy_ibt_plt = &elf_x86_64_non_lazy_ibt_plt;
 	}
       else
 	{
-	  htab->lazy_plt = &elf_x86_64_lazy_plt;
-	  htab->non_lazy_plt = &elf_x86_64_non_lazy_plt;
+	  plt_layout.lazy_ibt_plt = &elf_x32_lazy_ibt_plt;
+	  plt_layout.non_lazy_ibt_plt = &elf_x32_non_lazy_ibt_plt;
 	}
-      normal_target = TRUE;
+      plt_layout.normal_target = TRUE;
     }
   else
     {
-      htab->lazy_plt = &elf_x86_64_nacl_plt;
-      htab->non_lazy_plt = NULL;
-      normal_target = FALSE;
-    }
-
-  pltsec = htab->elf.splt;
-
-  /* If the non-lazy PLT is available, use it for all PLT entries if
-     there are no PLT0 or no .plt section.  */
-  if (htab->non_lazy_plt != NULL
-      && (!htab->plt.has_plt0 || pltsec == NULL))
-    {
-      lazy_plt = FALSE;
-      htab->plt.plt_entry = htab->non_lazy_plt->plt_entry;
-      htab->plt.plt_entry_size = htab->non_lazy_plt->plt_entry_size;
-      htab->plt.plt_got_offset = htab->non_lazy_plt->plt_got_offset;
-      htab->plt.plt_got_insn_size
-	= htab->non_lazy_plt->plt_got_insn_size;
-      htab->plt.eh_frame_plt_size
-	= htab->non_lazy_plt->eh_frame_plt_size;
-      htab->plt.eh_frame_plt = htab->non_lazy_plt->eh_frame_plt;
-    }
-  else
-    {
-      lazy_plt = TRUE;
-      htab->plt.plt_entry = htab->lazy_plt->plt_entry;
-      htab->plt.plt_entry_size = htab->lazy_plt->plt_entry_size;
-      htab->plt.plt_got_offset = htab->lazy_plt->plt_got_offset;
-      htab->plt.plt_got_insn_size
-	= htab->lazy_plt->plt_got_insn_size;
-      htab->plt.eh_frame_plt_size
-	= htab->lazy_plt->eh_frame_plt_size;
-      htab->plt.eh_frame_plt = htab->lazy_plt->eh_frame_plt;
-    }
-
-  /* This is unused for x86-64.  */
-  htab->plt.plt0_entry = NULL;
-
-  /* Return if there are no normal input files.  */
-  if (dynobj == NULL)
-    return pbfd;
-
-  /* Since create_dynamic_sections isn't always called, but GOT
-     relocations need GOT relocations, create them here so that we
-     don't need to do it in check_relocs.  */
-  if (htab->elf.sgot == NULL
-      && !_bfd_elf_create_got_section (dynobj, info))
-    info->callbacks->einfo (_("%F: failed to create GOT sections\n"));
-
-  /* Align .got and .got.plt sections to their entry size.  Do it here
-     instead of in create_dynamic_sections so that they are always
-     properly aligned even if create_dynamic_sections isn't called.  */
-  sec = htab->elf.sgot;
-  if (!bfd_set_section_alignment (dynobj, sec, 3))
-    goto error_alignment;
-
-  sec = htab->elf.sgotplt;
-  if (!bfd_set_section_alignment (dynobj, sec, 3))
-    goto error_alignment;
-
-  /* Create the ifunc sections here so that check_relocs can be
-     simplified.  */
-  if (!_bfd_elf_create_ifunc_sections (dynobj, info))
-    info->callbacks->einfo (_("%F: failed to create ifunc sections\n"));
-
-  plt_alignment = bfd_log2 (htab->plt.plt_entry_size);
-
-  if (pltsec != NULL)
-    {
-      /* Whe creating executable, set the contents of the .interp
-	 section to the interpreter.  */
-      if (bfd_link_executable (info) && !info->nointerp)
-	{
-	  asection *s = bfd_get_linker_section (dynobj, ".interp");
-	  if (s == NULL)
-	    abort ();
-	  s->size = htab->dynamic_interpreter_size;
-	  s->contents = (unsigned char *) htab->dynamic_interpreter;
-	  htab->interp = s;
-	}
-
-      /* Don't change PLT section alignment for NaCl since it uses
-	 64-byte PLT entry and sets PLT section alignment to 32
-	 bytes.  Don't create additional PLT sections for NaCl.  */
-      if (normal_target)
-	{
-	  const struct elf_backend_data *bed
-	    = get_elf_backend_data (dynobj);
-	  flagword pltflags = (bed->dynamic_sec_flags
-			       | SEC_ALLOC
-			       | SEC_CODE
-			       | SEC_LOAD
-			       | SEC_READONLY);
-	  unsigned int non_lazy_plt_alignment
-	    = bfd_log2 (htab->non_lazy_plt->plt_entry_size);
-
-	  sec = pltsec;
-	  if (!bfd_set_section_alignment (sec->owner, sec,
-					  plt_alignment))
-	    goto error_alignment;
-
-	  /* Create the GOT procedure linkage table.  */
-	  sec = bfd_make_section_anyway_with_flags (dynobj,
-						    ".plt.got",
-						    pltflags);
-	  if (sec == NULL)
-	    info->callbacks->einfo (_("%F: failed to create GOT PLT section\n"));
-
-	  if (!bfd_set_section_alignment (dynobj, sec,
-					  non_lazy_plt_alignment))
-	    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;
-		}
-	      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;
-	    }
-	}
-
-      if (!info->no_ld_generated_unwind_info)
-	{
-	  flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
-			    | SEC_HAS_CONTENTS | SEC_IN_MEMORY
-			    | SEC_LINKER_CREATED);
-
-	  sec = bfd_make_section_anyway_with_flags (dynobj,
-						    ".eh_frame",
-						    flags);
-	  if (sec == NULL)
-	    info->callbacks->einfo (_("%F: failed to create PLT .eh_frame section\n"));
-
-	  if (!bfd_set_section_alignment (dynobj, sec,
-					  ABI_64_P (dynobj) ? 3 : 2))
-	    goto error_alignment;
-
-	  htab->plt_eh_frame = sec;
-
-	  if (htab->plt_got != NULL)
-	    {
-	      sec = bfd_make_section_anyway_with_flags (dynobj,
-							".eh_frame",
-							flags);
-	      if (sec == NULL)
-		info->callbacks->einfo (_("%F: failed to create GOT PLT .eh_frame section\n"));
-
-	      if (!bfd_set_section_alignment (dynobj, sec,
-					      ABI_64_P (dynobj) ? 3 : 2))
-		goto error_alignment;
-
-	      htab->plt_got_eh_frame = sec;
-	    }
-
-	  if (htab->plt_second != NULL)
-	    {
-	      sec = bfd_make_section_anyway_with_flags (dynobj,
-							".eh_frame",
-							flags);
-	      if (sec == NULL)
-		info->callbacks->einfo (_("%F: failed to create the second PLT .eh_frame section\n"));
-
-	      if (!bfd_set_section_alignment (dynobj, sec,
-					      ABI_64_P (dynobj) ? 3 : 2))
-		goto error_alignment;
-
-	      htab->plt_second_eh_frame = sec;
-	    }
-	}
-    }
-
-  if (normal_target)
-    {
-      /* The .iplt section is used for IFUNC symbols in static
-	 executables.  */
-      sec = htab->elf.iplt;
-      if (sec != NULL
-	  && !bfd_set_section_alignment (sec->owner, sec,
-					 plt_alignment))
-	goto error_alignment;
+      plt_layout.lazy_plt = &elf_x86_64_nacl_plt;
+      plt_layout.non_lazy_plt = NULL;
+      plt_layout.lazy_ibt_plt = NULL;
+      plt_layout.non_lazy_ibt_plt = NULL;
+      plt_layout.normal_target = FALSE;
     }
 
-  return pbfd;
+  return _bfd_x86_elf_link_setup_gnu_properties (info, &plt_layout);
 }
 
 static const struct bfd_elf_special_section
@@ -7062,8 +6720,8 @@ static const struct elf_x86_lazy_plt_layout elf_x86_64_nacl_plt =
     7,                                       /* plt_got_insn_size */
     42,                                      /* plt_plt_insn_end */
     32,                                      /* plt_lazy_offset */
-    NULL,                                    /* pic_plt0_entry */
-    NULL,                                    /* pic_plt_entry */
+    elf_x86_64_nacl_plt0_entry,              /* pic_plt0_entry */
+    elf_x86_64_nacl_plt_entry,               /* pic_plt_entry */
     elf_x86_64_nacl_eh_frame_plt,            /* eh_frame_plt */
     sizeof (elf_x86_64_nacl_eh_frame_plt)    /* eh_frame_plt_size */
   };
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index eb02ed24bc..d43fe31ede 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -19,6 +19,7 @@
    MA 02110-1301, USA.  */
 
 #include "elfxx-x86.h"
+#include "elf-vxworks.h"
 #include "objalloc.h"
 #include "elf/i386.h"
 #include "elf/x86-64.h"
@@ -900,3 +901,392 @@ _bfd_x86_elf_merge_gnu_properties (struct bfd_link_info *info,
 
   return updated;
 }
+
+/* Set up x86 GNU properties.  Return the first relocatable ELF input
+   with GNU properties if found.  Otherwise, return NULL.  */
+
+bfd *
+_bfd_x86_elf_link_setup_gnu_properties
+  (struct bfd_link_info *info,
+   struct elf_x86_plt_layout_table *plt_layout)
+{
+  bfd_boolean normal_target;
+  bfd_boolean lazy_plt;
+  asection *sec, *pltsec;
+  bfd *dynobj;
+  bfd_boolean use_ibt_plt;
+  unsigned int plt_alignment, features;
+  struct elf_x86_link_hash_table *htab;
+  bfd *pbfd;
+  bfd *ebfd = NULL;
+  elf_property *prop;
+  const struct elf_backend_data *bed;
+  unsigned int class_align = ABI_64_P (info->output_bfd) ? 3 : 2;
+  unsigned int got_align;
+
+  features = 0;
+  if (info->ibt)
+    features = GNU_PROPERTY_X86_FEATURE_1_IBT;
+  if (info->shstk)
+    features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
+
+  /* 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 (ebfd != NULL && features)
+    {
+      /* 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->pr_kind = property_number;
+
+      /* 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, class_align))
+	    {
+error_alignment:
+	      info->callbacks->einfo (_("%F%A: failed to align section\n"),
+				      sec);
+	    }
+
+	  elf_section_type (sec) = SHT_NOTE;
+	}
+    }
+
+  pbfd = _bfd_elf_link_setup_gnu_properties (info);
+
+  if (bfd_link_relocatable (info))
+    return pbfd;
+
+  bed = get_elf_backend_data (info->output_bfd);
+
+  htab = elf_x86_hash_table (info, bed->target_id);
+  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)
+    {
+      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 (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+		&& (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
+     still be used with LD_AUDIT or LD_PROFILE if PLT entry is used for
+     canonical function address.  */
+  htab->plt.has_plt0 = 1;
+  normal_target = plt_layout->normal_target;
+
+  if (normal_target)
+    {
+      if (use_ibt_plt)
+	{
+	  htab->lazy_plt = plt_layout->lazy_ibt_plt;
+	  htab->non_lazy_plt = plt_layout->non_lazy_ibt_plt;
+	}
+      else
+	{
+	  htab->lazy_plt = plt_layout->lazy_plt;
+	  htab->non_lazy_plt = plt_layout->non_lazy_plt;
+	}
+    }
+  else
+    {
+      htab->lazy_plt = plt_layout->lazy_plt;
+      htab->non_lazy_plt = NULL;
+    }
+
+  pltsec = htab->elf.splt;
+
+  /* If the non-lazy PLT is available, use it for all PLT entries if
+     there are no PLT0 or no .plt section.  */
+  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;
+      else
+	htab->plt.plt_entry = htab->non_lazy_plt->plt_entry;
+      htab->plt.plt_entry_size = htab->non_lazy_plt->plt_entry_size;
+      htab->plt.plt_got_offset = htab->non_lazy_plt->plt_got_offset;
+      htab->plt.plt_got_insn_size
+	= htab->non_lazy_plt->plt_got_insn_size;
+      htab->plt.eh_frame_plt_size
+	= htab->non_lazy_plt->eh_frame_plt_size;
+      htab->plt.eh_frame_plt = htab->non_lazy_plt->eh_frame_plt;
+    }
+  else
+    {
+      lazy_plt = TRUE;
+      if (bfd_link_pic (info))
+	{
+	  htab->plt.plt0_entry = htab->lazy_plt->pic_plt0_entry;
+	  htab->plt.plt_entry = htab->lazy_plt->pic_plt_entry;
+	}
+      else
+	{
+	  htab->plt.plt0_entry = htab->lazy_plt->plt0_entry;
+	  htab->plt.plt_entry = htab->lazy_plt->plt_entry;
+	}
+      htab->plt.plt_entry_size = htab->lazy_plt->plt_entry_size;
+      htab->plt.plt_got_offset = htab->lazy_plt->plt_got_offset;
+      htab->plt.plt_got_insn_size
+	= htab->lazy_plt->plt_got_insn_size;
+      htab->plt.eh_frame_plt_size
+	= htab->lazy_plt->eh_frame_plt_size;
+      htab->plt.eh_frame_plt = htab->lazy_plt->eh_frame_plt;
+    }
+
+  /* Return if there are no normal input files.  */
+  if (dynobj == NULL)
+    return pbfd;
+
+  if (plt_layout->is_vxworks
+      && !elf_vxworks_create_dynamic_sections (dynobj, info,
+					       &htab->srelplt2))
+    {
+      info->callbacks->einfo (_("%F: failed to create VxWorks dynamic sections\n"));
+      return pbfd;
+    }
+
+  /* Since create_dynamic_sections isn't always called, but GOT
+     relocations need GOT relocations, create them here so that we
+     don't need to do it in check_relocs.  */
+  if (htab->elf.sgot == NULL
+      && !_bfd_elf_create_got_section (dynobj, info))
+    info->callbacks->einfo (_("%F: failed to create GOT sections\n"));
+
+  got_align = (bed->target_id == X86_64_ELF_DATA) ? 3 : 2;
+
+  /* Align .got and .got.plt sections to their entry size.  Do it here
+     instead of in create_dynamic_sections so that they are always
+     properly aligned even if create_dynamic_sections isn't called.  */
+  sec = htab->elf.sgot;
+  if (!bfd_set_section_alignment (dynobj, sec, got_align))
+    goto error_alignment;
+
+  sec = htab->elf.sgotplt;
+  if (!bfd_set_section_alignment (dynobj, sec, got_align))
+    goto error_alignment;
+
+  /* Create the ifunc sections here so that check_relocs can be
+     simplified.  */
+  if (!_bfd_elf_create_ifunc_sections (dynobj, info))
+    info->callbacks->einfo (_("%F: failed to create ifunc sections\n"));
+
+  plt_alignment = bfd_log2 (htab->plt.plt_entry_size);
+
+  if (pltsec != NULL)
+    {
+      /* Whe creating executable, set the contents of the .interp
+	 section to the interpreter.  */
+      if (bfd_link_executable (info) && !info->nointerp)
+	{
+	  asection *s = bfd_get_linker_section (dynobj, ".interp");
+	  if (s == NULL)
+	    abort ();
+	  s->size = htab->dynamic_interpreter_size;
+	  s->contents = (unsigned char *) htab->dynamic_interpreter;
+	  htab->interp = s;
+	}
+
+      /* Don't change PLT section alignment for NaCl since it uses
+	 64-byte PLT entry and sets PLT section alignment to 32
+	 bytes.  Don't create additional PLT sections for NaCl.  */
+      if (normal_target)
+	{
+	  flagword pltflags = (bed->dynamic_sec_flags
+			       | SEC_ALLOC
+			       | SEC_CODE
+			       | SEC_LOAD
+			       | SEC_READONLY);
+	  unsigned int non_lazy_plt_alignment
+	    = bfd_log2 (htab->non_lazy_plt->plt_entry_size);
+
+	  sec = pltsec;
+	  if (!bfd_set_section_alignment (sec->owner, sec,
+					  plt_alignment))
+	    goto error_alignment;
+
+	  /* Create the GOT procedure linkage table.  */
+	  sec = bfd_make_section_anyway_with_flags (dynobj,
+						    ".plt.got",
+						    pltflags);
+	  if (sec == NULL)
+	    info->callbacks->einfo (_("%F: failed to create GOT PLT section\n"));
+
+	  if (!bfd_set_section_alignment (dynobj, sec,
+					  non_lazy_plt_alignment))
+	    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;
+		}
+	      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;
+	    }
+	}
+
+      if (!info->no_ld_generated_unwind_info)
+	{
+	  flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+			    | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+			    | SEC_LINKER_CREATED);
+
+	  sec = bfd_make_section_anyway_with_flags (dynobj,
+						    ".eh_frame",
+						    flags);
+	  if (sec == NULL)
+	    info->callbacks->einfo (_("%F: failed to create PLT .eh_frame section\n"));
+
+	  if (!bfd_set_section_alignment (dynobj, sec, class_align))
+	    goto error_alignment;
+
+	  htab->plt_eh_frame = sec;
+
+	  if (htab->plt_got != NULL)
+	    {
+	      sec = bfd_make_section_anyway_with_flags (dynobj,
+							".eh_frame",
+							flags);
+	      if (sec == NULL)
+		info->callbacks->einfo (_("%F: failed to create GOT PLT .eh_frame section\n"));
+
+	      if (!bfd_set_section_alignment (dynobj, sec, class_align))
+		goto error_alignment;
+
+	      htab->plt_got_eh_frame = sec;
+	    }
+
+	  if (htab->plt_second != NULL)
+	    {
+	      sec = bfd_make_section_anyway_with_flags (dynobj,
+							".eh_frame",
+							flags);
+	      if (sec == NULL)
+		info->callbacks->einfo (_("%F: failed to create the second PLT .eh_frame section\n"));
+
+	      if (!bfd_set_section_alignment (dynobj, sec, class_align))
+		goto error_alignment;
+
+	      htab->plt_second_eh_frame = sec;
+	    }
+	}
+    }
+
+  if (normal_target)
+    {
+      /* The .iplt section is used for IFUNC symbols in static
+	 executables.  */
+      sec = htab->elf.iplt;
+      if (sec != NULL
+	  && !bfd_set_section_alignment (sec->owner, sec,
+					 plt_alignment))
+	goto error_alignment;
+    }
+
+  return pbfd;
+}
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index 45f2458cc2..f0240b3474 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -159,11 +159,11 @@ struct elf_x86_lazy_plt_layout
   unsigned int plt_lazy_offset;
 
   /* The first entry in a PIC lazy procedure linkage table looks like
-     this.  This is used for i386 only.  */
+     this.  */
   const bfd_byte *pic_plt0_entry;
 
   /* Subsequent entries in a PIC lazy procedure linkage table look
-     like this.  This is used for i386 only.  */
+     like this.  */
   const bfd_byte *pic_plt_entry;
 
   /* .eh_frame covering the lazy .plt section.  */
@@ -176,8 +176,7 @@ struct elf_x86_non_lazy_plt_layout
   /* Entries in an absolute 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.
-     This is used for i386 only.  */
+  /* Entries in a PIC non-lazy procedure linkage table look like this.  */
   const bfd_byte *pic_plt_entry;
 
   unsigned int plt_entry_size;          /* Size of each PLT entry.  */
@@ -304,6 +303,27 @@ struct elf_x86_link_hash_table
   const char *tls_get_addr;
 };
 
+struct elf_x86_plt_layout_table
+{
+  /* The lazy PLT layout.  */
+  const struct elf_x86_lazy_plt_layout *lazy_plt;
+
+  /* The non-lazy PLT layout.  */
+  const struct elf_x86_non_lazy_plt_layout *non_lazy_plt;
+
+  /* The lazy PLT layout for IBT.  */
+  const struct elf_x86_lazy_plt_layout *lazy_ibt_plt;
+
+  /* The non-lazy PLT layout for IBT.  */
+  const struct elf_x86_non_lazy_plt_layout *non_lazy_ibt_plt;
+
+  /* TRUE if this is an normal x86 target.  */
+  bfd_boolean normal_target;
+
+  /* TRUE if this is a VxWorks x86 target.  */
+  bfd_boolean is_vxworks;
+};
+
 struct elf_x86_obj_tdata
 {
   struct elf_obj_tdata root;
@@ -403,6 +423,9 @@ extern enum elf_property_kind _bfd_x86_elf_parse_gnu_properties
 extern bfd_boolean _bfd_x86_elf_merge_gnu_properties
   (struct bfd_link_info *, bfd *, elf_property *, elf_property *);
 
+extern bfd * _bfd_x86_elf_link_setup_gnu_properties
+  (struct bfd_link_info *, struct elf_x86_plt_layout_table *);
+
 #define bfd_elf64_bfd_link_hash_table_create \
   _bfd_x86_elf_link_hash_table_create
 #define bfd_elf32_bfd_link_hash_table_create \
-- 
2.13.5



More information about the Binutils mailing list