x86: Add _bfd_x86_elf_link_setup_gnu_properties
authorH.J. Lu <hjl.tools@gmail.com>
Fri, 1 Sep 2017 15:00:36 +0000 (08:00 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Fri, 1 Sep 2017 15:00:51 +0000 (08:00 -0700)
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.

* 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/ChangeLog
bfd/elf32-i386.c
bfd/elf64-x86-64.c
bfd/elfxx-x86.c
bfd/elfxx-x86.h

index 20bdf16b291e536cf1430148781d1d8757d5f4bf..cf2c530a65c1aeb714aa63b0ee0e33c7402cb7f1 100644 (file)
@@ -1,3 +1,28 @@
+2017-09-01  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * 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.
+
 2017-09-01  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/22061
index a983301bfbab2e60f93c342d41184b136cc283be..a0d428565960a5dc4e742eab3b8385d76b8ffa85 100644 (file)
@@ -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
index 969a053e0b63211fade2f2c68ab6d32338b33bd9..547173b0a700cc8e6a125278defaf53bacd0c370 100644 (file)
@@ -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 */
   };
index eb02ed24bcca21dcf74d7f62090abe8f1e99ac40..d43fe31ede64e907b1224849cd83e81c6986e8dd 100644 (file)
@@ -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;
+}
index 45f2458cc22b325cbae2024243d24ab5446ac3e4..f0240b3474661676b65e3d8d869d821f346f3f27 100644 (file)
@@ -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 \