]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elf32-i386.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / bfd / elf32-i386.c
index bcb219ebe4dfcbaddadd0261ae86f852953e07fa..eb7e1f8b34e2f64706d1764a91159590c03f928f 100644 (file)
@@ -1,5 +1,5 @@
 /* Intel 80386/80486-specific support for 32-bit ELF
-   Copyright (C) 1993-2017 Free Software Foundation, Inc.
+   Copyright (C) 1993-2020 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -194,7 +194,7 @@ static reloc_howto_type elf_howto_table[]=
 #endif
 
 static reloc_howto_type *
-elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+elf_i386_reloc_type_lookup (bfd *abfd,
                            bfd_reloc_code_real_type code)
 {
   switch (code)
@@ -346,11 +346,13 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       return &elf_howto_table[R_386_GNU_VTENTRY - R_386_vt_offset];
 
     default:
-      break;
+      TRACE ("Unknown");
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unsupported relocation type: %#x"),
+                         abfd, (int) code);
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
     }
-
-  TRACE ("Unknown");
-  return 0;
 }
 
 static reloc_howto_type *
@@ -368,7 +370,7 @@ elf_i386_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 }
 
 static reloc_howto_type *
-elf_i386_rtype_to_howto (bfd *abfd, unsigned r_type)
+elf_i386_rtype_to_howto (unsigned r_type)
 {
   unsigned int indx;
 
@@ -379,25 +381,30 @@ elf_i386_rtype_to_howto (bfd *abfd, unsigned r_type)
          >= R_386_ext2 - R_386_ext)
       && ((indx = r_type - R_386_vt_offset) - R_386_ext2
          >= R_386_vt - R_386_ext2))
-    {
-      /* xgettext:c-format */
-      _bfd_error_handler (_("%B: invalid relocation type %d"),
-                         abfd, (int) r_type);
-      indx = R_386_NONE;
-    }
+      return NULL;
   /* PR 17512: file: 0f67f69d.  */
   if (elf_howto_table [indx].type != r_type)
     return NULL;
   return &elf_howto_table[indx];
 }
 
-static void
-elf_i386_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
+static bfd_boolean
+elf_i386_info_to_howto_rel (bfd *abfd,
                            arelent *cache_ptr,
                            Elf_Internal_Rela *dst)
 {
   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
-  cache_ptr->howto = elf_i386_rtype_to_howto (abfd, r_type);
+
+  if ((cache_ptr->howto = elf_i386_rtype_to_howto (r_type)) == NULL)
+    {
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+                         abfd, r_type);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
+  return TRUE;
 }
 
 /* Return whether a symbol name implies a local label.  The UnixWare
@@ -428,7 +435,7 @@ elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
       int pr_version = bfd_get_32 (abfd, note->descdata);
 
       if (pr_version != 1)
-       return FALSE;
+       return FALSE;
 
       /* pr_cursig */
       elf_tdata (abfd)->core->signal = bfd_get_32 (abfd, note->descdata + 20);
@@ -607,9 +614,9 @@ static const bfd_byte elf_i386_pic_non_lazy_plt_entry[NON_LAZY_PLT_ENTRY_SIZE] =
 
 static const bfd_byte elf_i386_lazy_ibt_plt0_entry[LAZY_PLT_ENTRY_SIZE] =
 {
-  0xff, 0x35, 0, 0, 0, 0,      /* pushl GOT[1]       */
-  0xff, 0x25, 0, 0, 0, 0,      /* jmp *GOT[2]        */
-  0x0f, 0x1f, 0x40, 0x00       /* nopl 0(%rax)       */
+  0xff, 0x35, 0, 0, 0, 0,      /* pushl GOT[1]       */
+  0xff, 0x25, 0, 0, 0, 0,      /* jmp *GOT[2]        */
+  0x0f, 0x1f, 0x40, 0x00       /* nopl 0(%rax)       */
 };
 
 /* Subsequent entries for an absolute IBT-enabled lazy procedure linkage
@@ -618,10 +625,10 @@ static const bfd_byte elf_i386_lazy_ibt_plt0_entry[LAZY_PLT_ENTRY_SIZE] =
 
 static const bfd_byte elf_i386_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] =
 {
-  0xf3, 0x0f, 0x1e, 0xfb,       /* endbr32                    */
-  0x68, 0, 0, 0, 0,             /* pushl immediate            */
-  0xe9, 0, 0, 0, 0,             /* jmp relative               */
-  0x66, 0x90                   /* xchg %ax,%ax               */
+  0xf3, 0x0f, 0x1e, 0xfb,      /* endbr32                    */
+  0x68, 0, 0, 0, 0,            /* pushl immediate            */
+  0xe9, 0, 0, 0, 0,            /* jmp relative               */
+  0x66, 0x90                   /* xchg %ax,%ax               */
 };
 
 /* The first entry in a PIC IBT-enabled lazy procedure linkage table
@@ -630,8 +637,8 @@ static const bfd_byte elf_i386_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] =
 static const bfd_byte elf_i386_pic_lazy_ibt_plt0_entry[LAZY_PLT_ENTRY_SIZE] =
 {
   0xff, 0xb3, 4, 0, 0, 0,      /* pushl 4(%ebx)      */
-  0xff, 0xa3, 8, 0, 0, 0,      /* jmp *8(%ebx)       */
-  0x0f, 0x1f, 0x40, 0x00       /* nopl 0(%rax)       */
+  0xff, 0xa3, 8, 0, 0, 0,      /* jmp *8(%ebx)       */
+  0x0f, 0x1f, 0x40, 0x00       /* nopl 0(%rax)       */
 };
 
 /* Entries for branches with IBT-enabled in the absolute non-lazey
@@ -640,7 +647,7 @@ static const bfd_byte elf_i386_pic_lazy_ibt_plt0_entry[LAZY_PLT_ENTRY_SIZE] =
 
 static const bfd_byte elf_i386_non_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] =
 {
-  0xf3, 0x0f, 0x1e, 0xfb,            /* endbr32               */
+  0xf3, 0x0f, 0x1e, 0xfb,           /* endbr32               */
   0xff, 0x25, 0, 0, 0, 0,           /* jmp *name@GOT         */
   0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 /* nopw 0x0(%rax,%rax,1) */
 };
@@ -651,7 +658,7 @@ static const bfd_byte elf_i386_non_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] =
 
 static const bfd_byte elf_i386_pic_non_lazy_ibt_plt_entry[LAZY_PLT_ENTRY_SIZE] =
 {
-  0xf3, 0x0f, 0x1e, 0xfb,            /* endbr32               */
+  0xf3, 0x0f, 0x1e, 0xfb,           /* endbr32               */
   0xff, 0xa3, 0, 0, 0, 0,           /* jmp *name@GOT(%ebx)   */
   0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 /* nopw 0x0(%rax,%rax,1) */
 };
@@ -755,65 +762,77 @@ static const bfd_byte elf_i386_eh_frame_non_lazy_plt[] =
 /* These are the standard parameters.  */
 static const struct elf_x86_lazy_plt_layout elf_i386_lazy_plt =
   {
-    elf_i386_lazy_plt0_entry,           /* plt0_entry */
-    sizeof (elf_i386_lazy_plt0_entry),  /* plt0_entry_size */
-    elf_i386_lazy_plt_entry,            /* plt_entry */
-    LAZY_PLT_ENTRY_SIZE,                /* plt_entry_size */
-    2,                                  /* plt0_got1_offset */
-    8,                                  /* plt0_got2_offset */
-    0,                                  /* plt0_got2_insn_end */
-    2,                                  /* plt_got_offset */
-    7,                                  /* plt_reloc_offset */
-    12,                                 /* plt_plt_offset */
-    0,                                  /* plt_got_insn_size */
-    0,                                  /* plt_plt_insn_end */
-    6,                                  /* plt_lazy_offset */
-    elf_i386_pic_lazy_plt0_entry,       /* pic_plt0_entry */
-    elf_i386_pic_lazy_plt_entry,        /* pic_plt_entry */
-    elf_i386_eh_frame_lazy_plt,         /* eh_frame_plt */
+    elf_i386_lazy_plt0_entry,          /* plt0_entry */
+    sizeof (elf_i386_lazy_plt0_entry), /* plt0_entry_size */
+    elf_i386_lazy_plt_entry,           /* plt_entry */
+    LAZY_PLT_ENTRY_SIZE,               /* plt_entry_size */
+    NULL,                              /* plt_tlsdesc_entry */
+    0,                                 /* plt_tlsdesc_entry_size*/
+    0,                                 /* plt_tlsdesc_got1_offset */
+    0,                                 /* plt_tlsdesc_got2_offset */
+    0,                                 /* plt_tlsdesc_got1_insn_end */
+    0,                                 /* plt_tlsdesc_got2_insn_end */
+    2,                                 /* plt0_got1_offset */
+    8,                                 /* plt0_got2_offset */
+    0,                                 /* plt0_got2_insn_end */
+    2,                                 /* plt_got_offset */
+    7,                                 /* plt_reloc_offset */
+    12,                                        /* plt_plt_offset */
+    0,                                 /* plt_got_insn_size */
+    0,                                 /* plt_plt_insn_end */
+    6,                                 /* plt_lazy_offset */
+    elf_i386_pic_lazy_plt0_entry,      /* pic_plt0_entry */
+    elf_i386_pic_lazy_plt_entry,       /* pic_plt_entry */
+    elf_i386_eh_frame_lazy_plt,                /* eh_frame_plt */
     sizeof (elf_i386_eh_frame_lazy_plt) /* eh_frame_plt_size */
   };
 
 static const struct elf_x86_non_lazy_plt_layout elf_i386_non_lazy_plt =
   {
-    elf_i386_non_lazy_plt_entry,        /* plt_entry */
-    elf_i386_pic_non_lazy_plt_entry,    /* pic_plt_entry */
-    NON_LAZY_PLT_ENTRY_SIZE,            /* plt_entry_size */
-    2,                                  /* plt_got_offset */
-    0,                                  /* plt_got_insn_size */
-    elf_i386_eh_frame_non_lazy_plt,     /* eh_frame_plt */
+    elf_i386_non_lazy_plt_entry,       /* plt_entry */
+    elf_i386_pic_non_lazy_plt_entry,   /* pic_plt_entry */
+    NON_LAZY_PLT_ENTRY_SIZE,           /* plt_entry_size */
+    2,                                 /* plt_got_offset */
+    0,                                 /* plt_got_insn_size */
+    elf_i386_eh_frame_non_lazy_plt,    /* eh_frame_plt */
     sizeof (elf_i386_eh_frame_non_lazy_plt) /* eh_frame_plt_size */
   };
 
 static const struct elf_x86_lazy_plt_layout elf_i386_lazy_ibt_plt =
   {
-    elf_i386_lazy_ibt_plt0_entry,       /* plt0_entry */
+    elf_i386_lazy_ibt_plt0_entry,      /* plt0_entry */
     sizeof (elf_i386_lazy_ibt_plt0_entry), /* plt0_entry_size */
-    elf_i386_lazy_ibt_plt_entry,        /* plt_entry */
-    LAZY_PLT_ENTRY_SIZE,                /* plt_entry_size */
-    2,                                  /* plt0_got1_offset */
-    8,                                  /* plt0_got2_offset */
-    0,                                  /* plt0_got2_insn_end */
-    4+2,                                /* plt_got_offset */
-    4+1,                                /* plt_reloc_offset */
-    4+6,                                /* plt_plt_offset */
-    0,                                  /* plt_got_insn_size */
-    0,                                  /* plt_plt_insn_end */
-    0,                                  /* plt_lazy_offset */
-    elf_i386_pic_lazy_ibt_plt0_entry,   /* pic_plt0_entry */
-    elf_i386_lazy_ibt_plt_entry,        /* pic_plt_entry */
-    elf_i386_eh_frame_lazy_ibt_plt,     /* eh_frame_plt */
+    elf_i386_lazy_ibt_plt_entry,       /* plt_entry */
+    LAZY_PLT_ENTRY_SIZE,               /* plt_entry_size */
+    NULL,                              /* plt_tlsdesc_entry */
+    0,                                 /* plt_tlsdesc_entry_size*/
+    0,                                 /* plt_tlsdesc_got1_offset */
+    0,                                 /* plt_tlsdesc_got2_offset */
+    0,                                 /* plt_tlsdesc_got1_insn_end */
+    0,                                 /* plt_tlsdesc_got2_insn_end */
+    2,                                 /* plt0_got1_offset */
+    8,                                 /* plt0_got2_offset */
+    0,                                 /* plt0_got2_insn_end */
+    4+2,                               /* plt_got_offset */
+    4+1,                               /* plt_reloc_offset */
+    4+6,                               /* plt_plt_offset */
+    0,                                 /* plt_got_insn_size */
+    0,                                 /* plt_plt_insn_end */
+    0,                                 /* plt_lazy_offset */
+    elf_i386_pic_lazy_ibt_plt0_entry,  /* pic_plt0_entry */
+    elf_i386_lazy_ibt_plt_entry,       /* pic_plt_entry */
+    elf_i386_eh_frame_lazy_ibt_plt,    /* eh_frame_plt */
     sizeof (elf_i386_eh_frame_lazy_ibt_plt) /* eh_frame_plt_size */
   };
 
 static const struct elf_x86_non_lazy_plt_layout elf_i386_non_lazy_ibt_plt =
   {
-    elf_i386_non_lazy_ibt_plt_entry,    /* plt_entry */
+    elf_i386_non_lazy_ibt_plt_entry,   /* plt_entry */
     elf_i386_pic_non_lazy_ibt_plt_entry,/* pic_plt_entry */
-    LAZY_PLT_ENTRY_SIZE,                /* plt_entry_size */
-    4+2,                                /* plt_got_offset */
-    0,                                  /* plt_got_insn_size */
-    elf_i386_eh_frame_non_lazy_plt,     /* eh_frame_plt */
+    LAZY_PLT_ENTRY_SIZE,               /* plt_entry_size */
+    4+2,                               /* plt_got_offset */
+    0,                                 /* plt_got_insn_size */
+    elf_i386_eh_frame_non_lazy_plt,    /* eh_frame_plt */
     sizeof (elf_i386_eh_frame_non_lazy_plt) /* eh_frame_plt_size */
   };
 \f
@@ -824,31 +843,10 @@ static const struct elf_x86_non_lazy_plt_layout elf_i386_non_lazy_ibt_plt =
 #define PLTRESOLVE_RELOCS 2
 #define PLT_NON_JUMP_SLOT_RELOCS 2
 
-/* Architecture-specific backend data for i386.  */
-
-struct elf_i386_backend_data
-{
-  /* Value used to fill the unused bytes of the first PLT entry.  */
-  bfd_byte plt0_pad_byte;
-
-  /* Target system.  */
-  enum
-    {
-      is_normal,
-      is_vxworks,
-      is_nacl
-    } os;
-};
-
-#define get_elf_i386_backend_data(abfd) \
-  ((const struct elf_i386_backend_data *) \
-   get_elf_backend_data (abfd)->arch_data)
-
 /* These are the standard parameters.  */
-static const struct elf_i386_backend_data elf_i386_arch_bed =
+static const struct elf_x86_backend_data elf_i386_arch_bed =
   {
-    0,                                  /* plt0_pad_byte */
-    is_normal                           /* os */
+    is_normal                          /* os */
   };
 
 #define        elf_backend_arch_data   &elf_i386_arch_bed
@@ -1153,8 +1151,8 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
       reloc_howto_type *from, *to;
       const char *name;
 
-      from = elf_i386_rtype_to_howto (abfd, from_type);
-      to = elf_i386_rtype_to_howto (abfd, to_type);
+      from = elf_i386_rtype_to_howto (from_type);
+      to = elf_i386_rtype_to_howto (to_type);
 
       if (h)
        name = h->root.root.string;
@@ -1177,10 +1175,10 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
 
       _bfd_error_handler
        /* xgettext:c-format */
-       (_("%B: TLS transition from %s to %s against `%s' at %#Lx "
-          "in section `%A' failed"),
+       (_("%pB: TLS transition from %s to %s against `%s'"
+          " at %#" PRIx64 " in section `%pA' failed"),
         abfd, from->name, to->name, name,
-        rel->r_offset, sec);
+        (uint64_t) rel->r_offset, sec);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
     }
@@ -1268,7 +1266,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
 
       _bfd_error_handler
        /* xgettext:c-format */
-       (_("%B: direct GOT relocation R_386_GOT32X against `%s' without base"
+       (_("%pB: direct GOT relocation R_386_GOT32X against `%s' without base"
           " register can not be used when making a shared object"),
         abfd, name);
       return FALSE;
@@ -1329,7 +1327,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
          && local_ref)
        {
          /* The function is locally defined.   */
-convert_branch:
+       convert_branch:
          /* Convert R_386_GOT32X to R_386_PC32.  */
          if (modrm == 0x15 || (modrm & 0xf8) == 0x90)
            {
@@ -1345,8 +1343,8 @@ convert_branch:
                }
              else
                {
-                 nop = link_info->call_nop_byte;
-                 if (link_info->call_nop_as_suffix)
+                 nop = htab->params->call_nop_byte;
+                 if (htab->params->call_nop_as_suffix)
                    {
                      nop_offset = roff + 3;
                      irel->r_offset -= 1;
@@ -1395,7 +1393,7 @@ convert_branch:
               || h->root.type == bfd_link_hash_defweak)
              && local_ref))
        {
-convert_load:
+       convert_load:
          if (opcode == 0x8b)
            {
              if (to_reloc_32)
@@ -1528,7 +1526,7 @@ elf_i386_check_relocs (bfd *abfd,
       if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
        {
          /* xgettext:c-format */
-         _bfd_error_handler (_("%B: bad symbol index: %d"),
+         _bfd_error_handler (_("%pB: bad symbol index: %d"),
                              abfd, r_symndx);
          goto error_return;
        }
@@ -1577,11 +1575,6 @@ elf_i386_check_relocs (bfd *abfd,
 
          /* It is referenced by a non-shared object. */
          h->ref_regular = 1;
-         h->root.non_ir_ref_regular = 1;
-
-         if (h->type == STT_GNU_IFUNC)
-           elf_tdata (info->output_bfd)->has_gnu_symbols
-             |= elf_gnu_symbol_ifunc;
        }
 
       if (r_type == R_386_GOT32X
@@ -1600,6 +1593,10 @@ elf_i386_check_relocs (bfd *abfd,
                                     rel, rel_end, h, r_symndx, FALSE))
        goto error_return;
 
+      /* Check if _GLOBAL_OFFSET_TABLE_ is referenced.  */
+      if (h == htab->elf.hgot)
+       htab->got_referenced = TRUE;
+
       switch (r_type)
        {
        case R_386_TLS_LDM:
@@ -1621,7 +1618,7 @@ elf_i386_check_relocs (bfd *abfd,
 
          eh->zero_undefweak &= 0x2;
          h->needs_plt = 1;
-         h->plt.refcount += 1;
+         h->plt.refcount = 1;
          break;
 
        case R_386_SIZE32:
@@ -1687,7 +1684,7 @@ elf_i386_check_relocs (bfd *abfd,
                    size *= (sizeof (bfd_signed_vma)
                             + sizeof (bfd_vma) + sizeof(char));
                    local_got_refcounts = (bfd_signed_vma *)
-                        bfd_zalloc (abfd, size);
+                       bfd_zalloc (abfd, size);
                    if (local_got_refcounts == NULL)
                      goto error_return;
                    elf_local_got_refcounts (abfd) = local_got_refcounts;
@@ -1722,7 +1719,7 @@ elf_i386_check_relocs (bfd *abfd,
                                             NULL);
                    _bfd_error_handler
                      /* xgettext:c-format */
-                     (_("%B: `%s' accessed both as normal and "
+                     (_("%pB: `%s' accessed both as normal and "
                         "thread local symbol"),
                       abfd, name);
                    bfd_set_error (bfd_error_bad_value);
@@ -1746,7 +1743,15 @@ elf_i386_check_relocs (bfd *abfd,
          if (r_type != R_386_TLS_IE)
            {
              if (eh != NULL)
-               eh->zero_undefweak &= 0x2;
+               {
+                 eh->zero_undefweak &= 0x2;
+
+                 /* Need GOT to resolve undefined weak symbol to 0.  */
+                 if (r_type == R_386_GOTOFF
+                     && h->root.type == bfd_link_hash_undefweak
+                     && bfd_link_executable (info))
+                   htab->got_referenced = TRUE;
+               }
              break;
            }
          /* Fall through */
@@ -1764,7 +1769,7 @@ elf_i386_check_relocs (bfd *abfd,
        case R_386_PC32:
          if (eh != NULL && (sec->flags & SEC_CODE) != 0)
            eh->zero_undefweak |= 0x2;
-do_relocation:
+       do_relocation:
          /* We are called after all symbols have been resolved.  Only
             relocation against STT_GNU_IFUNC symbol must go through
             PLT.  */
@@ -1772,20 +1777,7 @@ do_relocation:
              && (bfd_link_executable (info)
                  || h->type == STT_GNU_IFUNC))
            {
-             /* If this reloc is in a read-only section, we might
-                need a copy reloc.  We can't check reliably at this
-                stage whether the section is read-only, as input
-                sections have not yet been mapped to output sections.
-                Tentatively set the flag for now, and correct in
-                adjust_dynamic_symbol.  */
-             h->non_got_ref = 1;
-
-             /* We may need a .plt entry if the symbol is a function
-                defined in a shared lib or is a STT_GNU_IFUNC function
-                referenced from the code or read-only section.  */
-             if (!h->def_regular
-                 || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
-               h->plt.refcount += 1;
+             bfd_boolean func_pointer_ref = FALSE;
 
              if (r_type == R_386_PC32)
                {
@@ -1799,7 +1791,7 @@ do_relocation:
                    {
                      _bfd_error_handler
                        /* xgettext:c-format */
-                       (_("%B: unsupported non-PIC call to IFUNC `%s'"),
+                       (_("%pB: unsupported non-PIC call to IFUNC `%s'"),
                         abfd, h->root.root.string);
                      bfd_set_error (bfd_error_bad_value);
                      goto error_return;
@@ -1811,13 +1803,31 @@ do_relocation:
                  /* R_386_32 can be resolved at run-time.  */
                  if (r_type == R_386_32
                      && (sec->flags & SEC_READONLY) == 0)
-                   eh->func_pointer_refcount += 1;
+                   func_pointer_ref = TRUE;
+               }
+
+             if (!func_pointer_ref)
+               {
+                 /* If this reloc is in a read-only section, we might
+                    need a copy reloc.  We can't check reliably at this
+                    stage whether the section is read-only, as input
+                    sections have not yet been mapped to output sections.
+                    Tentatively set the flag for now, and correct in
+                    adjust_dynamic_symbol.  */
+                 h->non_got_ref = 1;
+
+                 /* We may need a .plt entry if the symbol is a function
+                    defined in a shared lib or is a function referenced
+                    from the code or read-only section.  */
+                 if (!h->def_regular
+                     || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
+                   h->plt.refcount = 1;
                }
            }
 
          size_reloc = FALSE;
-do_size:
-         if (NEED_DYNAMIC_RELOCATION_P (info, h, sec, r_type,
+       do_size:
+         if (NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type,
                                         R_386_32))
            {
              struct elf_dyn_relocs *p;
@@ -1865,9 +1875,9 @@ do_size:
              p = *head;
              if (p == NULL || p->sec != sec)
                {
-                 bfd_size_type amt = sizeof *p;
+                 size_t amt = sizeof *p;
                  p = (struct elf_dyn_relocs *) bfd_alloc (htab->elf.dynobj,
-                                                           amt);
+                                                          amt);
                  if (p == NULL)
                    goto error_return;
                  p->next = *head;
@@ -1894,9 +1904,7 @@ do_size:
          /* This relocation describes which C++ vtable entries are actually
             used.  Record for later use during GC.  */
        case R_386_GNU_VTENTRY:
-         BFD_ASSERT (h != NULL);
-         if (h != NULL
-             && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+         if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
            goto error_return;
          break;
 
@@ -1923,7 +1931,7 @@ do_size:
 
   return TRUE;
 
-error_return:
+ error_return:
   if (elf_section_data (sec)->this_hdr.contents != contents)
     free (contents);
   sec->check_relocs_failed = 1;
@@ -1940,7 +1948,7 @@ elf_i386_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
 {
   const char *name;
 
-  name = bfd_get_section_name (abfd, sec);
+  name = bfd_section_name (sec);
 
   /* This is an ugly, but unfortunately necessary hack that is
      needed when producing EFI binaries on x86. It tells
@@ -2014,7 +2022,11 @@ elf_i386_relocate_section (bfd *output_bfd,
   if (htab == NULL)
     return FALSE;
 
-  BFD_ASSERT (is_x86_elf (input_bfd, htab));
+  if (!is_x86_elf (input_bfd, htab))
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return FALSE;
+    }
 
   symtab_hdr = &elf_symtab_hdr (input_bfd);
   sym_hashes = elf_sym_hashes (input_bfd);
@@ -2022,8 +2034,8 @@ elf_i386_relocate_section (bfd *output_bfd,
   local_tlsdesc_gotents = elf_x86_local_tlsdesc_gotent (input_bfd);
   /* We have to handle relocations in vxworks .tls_vars sections
      specially, because the dynamic loader is 'weird'.  */
-  is_vxworks_tls = (htab->is_vxworks
-                    && bfd_link_pic (info)
+  is_vxworks_tls = (htab->target_os == is_vxworks
+                   && bfd_link_pic (info)
                    && !strcmp (input_section->output_section->name,
                                ".tls_vars"));
 
@@ -2062,15 +2074,10 @@ elf_i386_relocate_section (bfd *output_bfd,
          continue;
        }
 
-      if ((indx = r_type) >= R_386_standard
-         && ((indx = r_type - R_386_ext_offset) - R_386_standard
-             >= R_386_ext - R_386_standard)
-         && ((indx = r_type - R_386_tls_offset) - R_386_ext
-             >= R_386_ext2 - R_386_ext))
+      howto = elf_i386_rtype_to_howto (r_type);
+      if (howto == NULL)
        return _bfd_unrecognized_reloc (input_bfd, input_section, r_type);
 
-      howto = elf_howto_table + indx;
-
       r_symndx = ELF32_R_SYM (rel->r_info);
       h = NULL;
       sym = NULL;
@@ -2183,7 +2190,7 @@ elf_i386_relocate_section (bfd *output_bfd,
       if (sec != NULL && discarded_section (sec))
        {
          _bfd_clear_contents (howto, input_bfd, input_section,
-                              contents + rel->r_offset);
+                              contents, rel->r_offset);
          wrel->r_offset = rel->r_offset;
          wrel->r_info = 0;
          wrel->r_addend = 0;
@@ -2219,6 +2226,10 @@ elf_i386_relocate_section (bfd *output_bfd,
 
          if ((input_section->flags & SEC_ALLOC) == 0)
            {
+             /* If this is a SHT_NOTE section without SHF_ALLOC, treat
+                STT_GNU_IFUNC symbol as STT_FUNC.  */
+             if (elf_section_type (input_section) == SHT_NOTE)
+               goto skip_ifunc;
              /* Dynamic relocs are not propagated for SEC_DEBUGGING
                 sections because such sections are not SEC_ALLOC and
                 thus ld.so will not process them.  */
@@ -2351,7 +2362,7 @@ elf_i386_relocate_section (bfd *output_bfd,
          switch (r_type)
            {
            default:
-bad_ifunc_reloc:
+           bad_ifunc_reloc:
              if (h->root.root.string)
                name = h->root.root.string;
              else
@@ -2359,7 +2370,7 @@ bad_ifunc_reloc:
                                         NULL);
              _bfd_error_handler
                /* xgettext:c-format */
-               (_("%B: relocation %s against STT_GNU_IFUNC "
+               (_("%pB: relocation %s against STT_GNU_IFUNC "
                   "symbol `%s' isn't supported"), input_bfd,
                 howto->name, name);
              bfd_set_error (bfd_error_bad_value);
@@ -2375,7 +2386,7 @@ bad_ifunc_reloc:
                  asection *sreloc;
                  bfd_vma offset;
 
-do_ifunc_pointer:
+               do_ifunc_pointer:
                  /* Need a dynamic relocation to get the real function
                     adddress.  */
                  offset = _bfd_elf_section_offset (output_bfd,
@@ -2392,7 +2403,7 @@ do_ifunc_pointer:
 
                  if (POINTER_LOCAL_IFUNC_P (info, h))
                    {
-                     info->callbacks->minfo (_("Local IFUNC function `%s' in %B\n"),
+                     info->callbacks->minfo (_("Local IFUNC function `%s' in %pB\n"),
                                              h->root.root.string,
                                              h->root.u.def.section->owner);
 
@@ -2438,72 +2449,14 @@ do_ifunc_pointer:
            }
        }
 
+    skip_ifunc:
       resolved_to_zero = (eh != NULL
                          && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh));
 
       switch (r_type)
        {
        case R_386_GOT32X:
-         /* Avoid optimizing _DYNAMIC since ld.so may use its
-            link-time address.  */
-         if (h == htab->elf.hdynamic)
-           goto r_386_got32;
-
-         if (bfd_link_pic (info))
-           {
-             /* It is OK to convert mov to lea and convert indirect
-                branch to direct branch.  It is OK to convert adc,
-                add, and, cmp, or, sbb, sub, test, xor only when PIC
-                is false.   */
-             unsigned int opcode, addend;
-             addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
-             if (addend != 0)
-               goto r_386_got32;
-             opcode = bfd_get_8 (input_bfd, contents + rel->r_offset - 2);
-             if (opcode != 0x8b && opcode != 0xff)
-               goto r_386_got32;
-           }
-
-         /* Resolve "mov GOT[(%reg)], %reg",
-            "call/jmp *GOT[(%reg)]", "test %reg, foo@GOT[(%reg)]"
-            and "binop foo@GOT[(%reg)], %reg".  */
-         if (h == NULL
-             || (h->plt.offset == (bfd_vma) -1
-                 && h->got.offset == (bfd_vma) -1)
-             || htab->elf.sgotplt == NULL)
-           abort ();
-
-         offplt = (htab->elf.sgotplt->output_section->vma
-                   + htab->elf.sgotplt->output_offset);
-
-         /* It is relative to .got.plt section.  */
-         if (h->got.offset != (bfd_vma) -1)
-           /* Use GOT entry.  Mask off the least significant bit in
-              GOT offset which may be set by R_386_GOT32 processing
-              below.  */
-           relocation = (htab->elf.sgot->output_section->vma
-                         + htab->elf.sgot->output_offset
-                         + (h->got.offset & ~1) - offplt);
-         else
-           /* Use GOTPLT entry.  */
-           relocation = (h->plt.offset / plt_entry_size
-                         - htab->plt.has_plt0 + 3) * 4;
-
-         if (!bfd_link_pic (info))
-           {
-             /* If not PIC, add the .got.plt section address for
-                baseless addressing.  */
-             unsigned int modrm;
-             modrm = bfd_get_8 (input_bfd, contents + rel->r_offset - 1);
-             if ((modrm & 0xc7) == 0x5)
-               relocation += offplt;
-           }
-
-         unresolved_reloc = FALSE;
-         break;
-
        case R_386_GOT32:
-r_386_got32:
          /* Relocation is to the entry for this symbol in the global
             offset table.  */
          if (htab->elf.sgot == NULL)
@@ -2598,7 +2551,7 @@ r_386_got32:
                     we don't know what the GOT base is.  */
                  const char *name;
 
-disallow_got32:
+               disallow_got32:
                  if (h == NULL || h->root.root.string == NULL)
                    name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
                                             NULL);
@@ -2607,7 +2560,7 @@ disallow_got32:
 
                  _bfd_error_handler
                    /* xgettext:c-format */
-                   (_("%B: direct GOT relocation %s against `%s'"
+                   (_("%pB: direct GOT relocation %s against `%s'"
                       " without base register can not be used"
                       " when making a shared object"),
                     input_bfd, howto->name, name);
@@ -2657,7 +2610,7 @@ disallow_got32:
 
                  _bfd_error_handler
                    /* xgettext:c-format */
-                   (_("%B: relocation R_386_GOTOFF against undefined %s"
+                   (_("%pB: relocation R_386_GOTOFF against undefined %s"
                       " `%s' can not be used when making a shared object"),
                     input_bfd, v, h->root.root.string);
                  bfd_set_error (bfd_error_bad_value);
@@ -2670,7 +2623,7 @@ disallow_got32:
                {
                  _bfd_error_handler
                    /* xgettext:c-format */
-                   (_("%B: relocation R_386_GOTOFF against protected %s"
+                   (_("%pB: relocation R_386_GOTOFF against protected %s"
                       " `%s' can not be used when making a shared object"),
                     input_bfd,
                     h->type == STT_FUNC ? "function" : "data",
@@ -3130,7 +3083,7 @@ disallow_got32:
                {
                  if (indx == 0)
                    {
-                     BFD_ASSERT (! unresolved_reloc);
+                     BFD_ASSERT (! unresolved_reloc);
                      bfd_put_32 (output_bfd,
                                  relocation - _bfd_x86_elf_dtpoff_base (info),
                                  htab->elf.sgot->contents + off + 4);
@@ -3447,21 +3400,21 @@ disallow_got32:
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"),
+           (_("%pB(%pA+%#" PRIx64 "): unresolvable %s relocation against symbol `%s'"),
             input_bfd,
             input_section,
-            rel->r_offset,
+            (uint64_t) rel->r_offset,
             howto->name,
             h->root.root.string);
          return FALSE;
        }
 
-do_relocation:
+    do_relocation:
       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
                                    contents, rel->r_offset,
                                    relocation, 0);
 
-check_relocation_error:
+    check_relocation_error:
       if (r != bfd_reloc_ok)
        {
          const char *name;
@@ -3476,7 +3429,7 @@ check_relocation_error:
              if (name == NULL)
                return FALSE;
              if (*name == '\0')
-               name = bfd_section_name (input_bfd, sec);
+               name = bfd_section_name (sec);
            }
 
          if (r == bfd_reloc_overflow)
@@ -3487,9 +3440,9 @@ check_relocation_error:
            {
              _bfd_error_handler
                /* xgettext:c-format */
-               (_("%B(%A+%#Lx): reloc against `%s': error %d"),
+               (_("%pB(%pA+%#" PRIx64 "): reloc against `%s': error %d"),
                 input_bfd, input_section,
-                rel->r_offset, name, (int) r);
+                (uint64_t) rel->r_offset, name, (int) r);
              return FALSE;
            }
        }
@@ -3633,9 +3586,9 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
                       + gotplt->output_offset
                       + got_offset),
                      resolved_plt->contents + plt_offset
-                      + htab->plt.plt_got_offset);
+                     + htab->plt.plt_got_offset);
 
-         if (htab->is_vxworks)
+         if (htab->target_os == is_vxworks)
            {
              int s, k, reloc_index;
 
@@ -3644,7 +3597,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
 
              /* S: Current slot number (zero-based).  */
              s = ((h->plt.offset - htab->plt.plt_entry_size)
-                   / htab->plt.plt_entry_size);
+                  / htab->plt.plt_entry_size);
              /* K: Number of relocations for PLTResolve. */
              if (bfd_link_pic (info))
                k = PLTRESOLVE_RELOCS_SHLIB;
@@ -3676,7 +3629,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
        {
          bfd_put_32 (output_bfd, got_offset,
                      resolved_plt->contents + plt_offset
-                      + htab->plt.plt_got_offset);
+                     + htab->plt.plt_got_offset);
        }
 
       /* Fill in the entry in the global offset table.  Leave the entry
@@ -3698,7 +3651,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
                          + got_offset);
          if (PLT_LOCAL_IFUNC_P (info, h))
            {
-             info->callbacks->minfo (_("Local IFUNC function `%s' in %B\n"),
+             info->callbacks->minfo (_("Local IFUNC function `%s' in %pB\n"),
                                      h->root.root.string,
                                      h->root.u.def.section->owner);
 
@@ -3798,6 +3751,8 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
        sym->st_value = 0;
     }
 
+  _bfd_x86_elf_link_fixup_ifunc_symbol (info, htab, h, sym);
+
   /* Don't generate dynamic GOT relocation against undefined weak
      symbol in executable.  */
   if (h->got.offset != (bfd_vma) -1
@@ -3837,7 +3792,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
                }
              if (SYMBOL_REFERENCES_LOCAL_P (info, h))
                {
-                 info->callbacks->minfo (_("Local IFUNC function `%s' in %B\n"),
+                 info->callbacks->minfo (_("Local IFUNC function `%s' in %pB\n"),
                                          h->root.root.string,
                                          h->root.u.def.section->owner);
 
@@ -3893,7 +3848,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
       else
        {
          BFD_ASSERT((h->got.offset & 1) == 0);
-do_glob_dat:
+       do_glob_dat:
          bfd_put_32 (output_bfd, (bfd_vma) 0,
                      htab->elf.sgot->contents + h->got.offset);
          rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT);
@@ -3974,7 +3929,7 @@ elf_i386_reloc_type_class (const struct bfd_link_info *info,
       && htab->dynsym->contents != NULL)
     {
       /* Check relocation against STT_GNU_IFUNC symbol if there are
-         dynamic symbols.  */
+        dynamic symbols.  */
       unsigned long r_symndx = ELF32_R_SYM (rela->r_info);
       if (r_symndx != STN_UNDEF)
        {
@@ -4012,262 +3967,99 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
                                  struct bfd_link_info *info)
 {
   struct elf_x86_link_hash_table *htab;
-  bfd *dynobj;
-  asection *sdyn;
-  const struct elf_i386_backend_data *abed;
 
-  htab = elf_x86_hash_table (info, I386_ELF_DATA);
+  htab = _bfd_x86_elf_finish_dynamic_sections (output_bfd, info);
   if (htab == NULL)
     return FALSE;
 
-  dynobj = htab->elf.dynobj;
-  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
-  abed = get_elf_i386_backend_data (output_bfd);
+  if (!htab->elf.dynamic_sections_created)
+    return TRUE;
 
-  if (htab->elf.dynamic_sections_created)
+  if (htab->elf.splt && htab->elf.splt->size > 0)
     {
-      Elf32_External_Dyn *dyncon, *dynconend;
-
-      if (sdyn == NULL || htab->elf.sgot == NULL)
-       abort ();
+      /* UnixWare sets the entsize of .plt to 4, although that doesn't
+        really seem like the right value.  */
+      elf_section_data (htab->elf.splt->output_section)
+       ->this_hdr.sh_entsize = 4;
 
-      dyncon = (Elf32_External_Dyn *) sdyn->contents;
-      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
-      for (; dyncon < dynconend; dyncon++)
+      if (htab->plt.has_plt0)
        {
-         Elf_Internal_Dyn dyn;
-         asection *s;
-
-         bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
-
-         switch (dyn.d_tag)
+         /* Fill in the special first entry in the procedure linkage
+            table.  */
+         memcpy (htab->elf.splt->contents, htab->plt.plt0_entry,
+                 htab->lazy_plt->plt0_entry_size);
+         memset (htab->elf.splt->contents + htab->lazy_plt->plt0_entry_size,
+                 htab->plt0_pad_byte,
+                 htab->plt.plt_entry_size - htab->lazy_plt->plt0_entry_size);
+         if (!bfd_link_pic (info))
            {
-           default:
-             if (htab->is_vxworks
-                  && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
-               break;
-             continue;
-
-           case DT_PLTGOT:
-             s = htab->elf.sgotplt;
-             dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
-             break;
-
-           case DT_JMPREL:
-             s = htab->elf.srelplt;
-             dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
-             break;
-
-           case DT_PLTRELSZ:
-             s = htab->elf.srelplt;
-             dyn.d_un.d_val = s->size;
-             break;
-           }
-
-         bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
-       }
-
-      if (htab->elf.splt && htab->elf.splt->size > 0)
-       {
-         /* UnixWare sets the entsize of .plt to 4, although that doesn't
-            really seem like the right value.  */
-         elf_section_data (htab->elf.splt->output_section)
-           ->this_hdr.sh_entsize = 4;
+             bfd_put_32 (output_bfd,
+                         (htab->elf.sgotplt->output_section->vma
+                          + htab->elf.sgotplt->output_offset
+                          + 4),
+                         htab->elf.splt->contents
+                         + htab->lazy_plt->plt0_got1_offset);
+             bfd_put_32 (output_bfd,
+                         (htab->elf.sgotplt->output_section->vma
+                          + htab->elf.sgotplt->output_offset
+                          + 8),
+                         htab->elf.splt->contents
+                         + htab->lazy_plt->plt0_got2_offset);
 
-         if (htab->plt.has_plt0)
-           {
-             /* Fill in the special first entry in the procedure linkage
-                table.  */
-             memcpy (htab->elf.splt->contents, htab->plt.plt0_entry,
-                     htab->lazy_plt->plt0_entry_size);
-             memset (htab->elf.splt->contents + htab->lazy_plt->plt0_entry_size,
-                     abed->plt0_pad_byte,
-                     htab->plt.plt_entry_size - htab->lazy_plt->plt0_entry_size);
-             if (!bfd_link_pic (info))
+             if (htab->target_os == is_vxworks)
                {
-                 bfd_put_32 (output_bfd,
-                             (htab->elf.sgotplt->output_section->vma
-                              + htab->elf.sgotplt->output_offset
-                              + 4),
-                             htab->elf.splt->contents
-                             + htab->lazy_plt->plt0_got1_offset);
-                 bfd_put_32 (output_bfd,
-                             (htab->elf.sgotplt->output_section->vma
-                              + htab->elf.sgotplt->output_offset
-                              + 8),
-                             htab->elf.splt->contents
-                             + htab->lazy_plt->plt0_got2_offset);
+                 Elf_Internal_Rela rel;
+                 int num_plts = (htab->elf.splt->size
+                                 / htab->plt.plt_entry_size) - 1;
+                 unsigned char *p;
+                 asection *srelplt2 = htab->srelplt2;
+
+                 /* Generate a relocation for _GLOBAL_OFFSET_TABLE_
+                    + 4.  On IA32 we use REL relocations so the
+                    addend goes in the PLT directly.  */
+                 rel.r_offset = (htab->elf.splt->output_section->vma
+                                 + htab->elf.splt->output_offset
+                                 + htab->lazy_plt->plt0_got1_offset);
+                 rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
+                                            R_386_32);
+                 bfd_elf32_swap_reloc_out (output_bfd, &rel,
+                                           srelplt2->contents);
+                 /* Generate a relocation for _GLOBAL_OFFSET_TABLE_
+                    + 8.  */
+                 rel.r_offset = (htab->elf.splt->output_section->vma
+                                 + htab->elf.splt->output_offset
+                                 + htab->lazy_plt->plt0_got2_offset);
+                 rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
+                                            R_386_32);
+                 bfd_elf32_swap_reloc_out (output_bfd, &rel,
+                                           srelplt2->contents +
+                                           sizeof (Elf32_External_Rel));
+                 /* Correct the .rel.plt.unloaded relocations.  */
+                 p = srelplt2->contents;
+                 if (bfd_link_pic (info))
+                   p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel);
+                 else
+                   p += PLTRESOLVE_RELOCS * sizeof (Elf32_External_Rel);
 
-                 if (htab->is_vxworks)
+                 for (; num_plts; num_plts--)
                    {
-                     Elf_Internal_Rela rel;
-                     int num_plts = (htab->elf.splt->size
-                                     / htab->plt.plt_entry_size) - 1;
-                     unsigned char *p;
-                     asection *srelplt2 = htab->srelplt2;
-
-                     /* Generate a relocation for _GLOBAL_OFFSET_TABLE_
-                        + 4.  On IA32 we use REL relocations so the
-                        addend goes in the PLT directly.  */
-                     rel.r_offset = (htab->elf.splt->output_section->vma
-                                     + htab->elf.splt->output_offset
-                                     + htab->lazy_plt->plt0_got1_offset);
+                     bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
                      rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
                                                 R_386_32);
-                     bfd_elf32_swap_reloc_out (output_bfd, &rel,
-                                               srelplt2->contents);
-                     /* Generate a relocation for _GLOBAL_OFFSET_TABLE_
-                        + 8.  */
-                     rel.r_offset = (htab->elf.splt->output_section->vma
-                                     + htab->elf.splt->output_offset
-                                     + htab->lazy_plt->plt0_got2_offset);
-                     rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
-                                                R_386_32);
-                     bfd_elf32_swap_reloc_out (output_bfd, &rel,
-                                               srelplt2->contents +
-                                               sizeof (Elf32_External_Rel));
-                     /* Correct the .rel.plt.unloaded relocations.  */
-                     p = srelplt2->contents;
-                     if (bfd_link_pic (info))
-                       p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel);
-                     else
-                       p += PLTRESOLVE_RELOCS * sizeof (Elf32_External_Rel);
+                     bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
+                     p += sizeof (Elf32_External_Rel);
 
-                     for (; num_plts; num_plts--)
-                       {
-                         bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
-                         rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
-                                                    R_386_32);
-                         bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
-                         p += sizeof (Elf32_External_Rel);
-
-                         bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
-                         rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx,
-                                                    R_386_32);
-                         bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
-                         p += sizeof (Elf32_External_Rel);
-                       }
+                     bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
+                     rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx,
+                                                R_386_32);
+                     bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
+                     p += sizeof (Elf32_External_Rel);
                    }
                }
            }
        }
-
-      if (htab->plt_got != NULL && htab->plt_got->size > 0)
-       elf_section_data (htab->plt_got->output_section)
-         ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
-
-      if (htab->plt_second != NULL && htab->plt_second->size > 0)
-       elf_section_data (htab->plt_second->output_section)
-         ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
-    }
-
-  /* Fill in the first three entries in the global offset table.  */
-  if (htab->elf.sgotplt && htab->elf.sgotplt->size > 0)
-    {
-      if (bfd_is_abs_section (htab->elf.sgotplt->output_section))
-       {
-         _bfd_error_handler
-           (_("discarded output section: `%A'"), htab->elf.sgotplt);
-         return FALSE;
-       }
-
-      bfd_put_32 (output_bfd,
-                 (sdyn == NULL ? 0
-                  : sdyn->output_section->vma + sdyn->output_offset),
-                 htab->elf.sgotplt->contents);
-      bfd_put_32 (output_bfd, 0, htab->elf.sgotplt->contents + 4);
-      bfd_put_32 (output_bfd, 0, htab->elf.sgotplt->contents + 8);
-
-      elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize = 4;
-    }
-
-  /* Adjust .eh_frame for .plt section.  */
-  if (htab->plt_eh_frame != NULL
-      && htab->plt_eh_frame->contents != NULL)
-    {
-      if (htab->elf.splt != NULL
-         && htab->elf.splt->size != 0
-         && (htab->elf.splt->flags & SEC_EXCLUDE) == 0
-         && htab->elf.splt->output_section != NULL
-         && htab->plt_eh_frame->output_section != NULL)
-       {
-         bfd_vma plt_start = htab->elf.splt->output_section->vma;
-         bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma
-                                  + htab->plt_eh_frame->output_offset
-                                  + PLT_FDE_START_OFFSET;
-         bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
-                            htab->plt_eh_frame->contents
-                            + PLT_FDE_START_OFFSET);
-       }
-      if (htab->plt_eh_frame->sec_info_type
-         == SEC_INFO_TYPE_EH_FRAME)
-       {
-         if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
-                                                htab->plt_eh_frame,
-                                                htab->plt_eh_frame->contents))
-           return FALSE;
-       }
-    }
-
-  /* Adjust .eh_frame for .plt.got section.  */
-  if (htab->plt_got_eh_frame != NULL
-      && htab->plt_got_eh_frame->contents != NULL)
-    {
-      if (htab->plt_got != NULL
-         && htab->plt_got->size != 0
-         && (htab->plt_got->flags & SEC_EXCLUDE) == 0
-         && htab->plt_got->output_section != NULL
-         && htab->plt_got_eh_frame->output_section != NULL)
-       {
-         bfd_vma plt_start = htab->plt_got->output_section->vma;
-         bfd_vma eh_frame_start = htab->plt_got_eh_frame->output_section->vma
-                                  + htab->plt_got_eh_frame->output_offset
-                                  + PLT_FDE_START_OFFSET;
-         bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
-                            htab->plt_got_eh_frame->contents
-                            + PLT_FDE_START_OFFSET);
-       }
-      if (htab->plt_got_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
-       {
-         if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
-                                                htab->plt_got_eh_frame,
-                                                htab->plt_got_eh_frame->contents))
-           return FALSE;
-       }
     }
 
-  /* Adjust .eh_frame for the second PLT section.  */
-  if (htab->plt_second_eh_frame != NULL
-      && htab->plt_second_eh_frame->contents != NULL)
-    {
-      if (htab->plt_second != NULL
-         && htab->plt_second->size != 0
-         && (htab->plt_second->flags & SEC_EXCLUDE) == 0
-         && htab->plt_second->output_section != NULL
-         && htab->plt_second_eh_frame->output_section != NULL)
-       {
-         bfd_vma plt_start = htab->plt_second->output_section->vma;
-         bfd_vma eh_frame_start
-           = (htab->plt_second_eh_frame->output_section->vma
-              + htab->plt_second_eh_frame->output_offset
-              + PLT_FDE_START_OFFSET);
-         bfd_put_signed_32 (dynobj, plt_start - eh_frame_start,
-                            htab->plt_second_eh_frame->contents
-                            + PLT_FDE_START_OFFSET);
-       }
-      if (htab->plt_second_eh_frame->sec_info_type
-         == SEC_INFO_TYPE_EH_FRAME)
-       {
-         if (! _bfd_elf_write_section_eh_frame (output_bfd, info,
-                                                htab->plt_second_eh_frame,
-                                                htab->plt_second_eh_frame->contents))
-           return FALSE;
-       }
-    }
-
-  if (htab->elf.sgot && htab->elf.sgot->size > 0)
-    elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
-
   /* Fill PLT entries for undefined weak symbols in PIE.  */
   if (bfd_link_pie (info))
     bfd_hash_traverse (&info->hash->table,
@@ -4355,9 +4147,10 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
   lazy_plt = NULL;
   non_lazy_ibt_plt = NULL;
   lazy_ibt_plt = NULL;
-  switch (get_elf_i386_backend_data (abfd)->os)
+  switch (get_elf_x86_backend_data (abfd)->target_os)
     {
     case is_normal:
+    case is_solaris:
       non_lazy_plt = &elf_i386_non_lazy_plt;
       lazy_ibt_plt = &elf_i386_lazy_ibt_plt;
       non_lazy_ibt_plt = &elf_i386_non_lazy_ibt_plt;
@@ -4514,25 +4307,25 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
 {
   struct elf_x86_init_table init_table;
 
-  init_table.normal_target = FALSE;
-  init_table.is_vxworks = FALSE;
-  switch (get_elf_i386_backend_data (info->output_bfd)->os)
+  switch (get_elf_x86_backend_data (info->output_bfd)->target_os)
     {
     case is_normal:
+    case is_solaris:
+      init_table.plt0_pad_byte = 0x0;
       init_table.lazy_plt = &elf_i386_lazy_plt;
       init_table.non_lazy_plt = &elf_i386_non_lazy_plt;
       init_table.lazy_ibt_plt = &elf_i386_lazy_ibt_plt;
       init_table.non_lazy_ibt_plt = &elf_i386_non_lazy_ibt_plt;
-      init_table.normal_target = TRUE;
       break;
     case is_vxworks:
+      init_table.plt0_pad_byte = 0x90;
       init_table.lazy_plt = &elf_i386_lazy_plt;
       init_table.non_lazy_plt = NULL;
       init_table.lazy_ibt_plt = NULL;
       init_table.non_lazy_ibt_plt = NULL;
-      init_table.is_vxworks = TRUE;
       break;
     case is_nacl:
+      init_table.plt0_pad_byte = 0x90;
       init_table.lazy_plt = &elf_i386_nacl_plt;
       init_table.non_lazy_plt = NULL;
       init_table.lazy_ibt_plt = NULL;
@@ -4586,9 +4379,12 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
 #define elf_backend_reloc_type_class         elf_i386_reloc_type_class
 #define elf_backend_relocate_section         elf_i386_relocate_section
 #define elf_backend_setup_gnu_properties      elf_i386_link_setup_gnu_properties
+#define elf_backend_hide_symbol                      _bfd_x86_elf_hide_symbol
 
 #define elf_backend_linux_prpsinfo32_ugid16    TRUE
 
+#define        elf32_bed                             elf32_i386_bed
+
 #include "elf32-target.h"
 
 /* FreeBSD support.  */
@@ -4604,10 +4400,11 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
    "FreeBSD" label in the ELF header.  So we put this label on all
    executables and (for simplicity) also all other object files.  */
 
-static void
-elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
+static bfd_boolean
+elf_i386_fbsd_init_file_header (bfd *abfd, struct bfd_link_info *info)
 {
-  _bfd_elf_post_process_headers (abfd, info);
+  if (!_bfd_elf_init_file_header (abfd, info))
+    return FALSE;
 
 #ifdef OLD_FREEBSD_ABI_LABEL
   {
@@ -4616,10 +4413,11 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
     memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
   }
 #endif
+  return TRUE;
 }
 
-#undef elf_backend_post_process_headers
-#define        elf_backend_post_process_headers        elf_i386_fbsd_post_process_headers
+#undef elf_backend_init_file_header
+#define        elf_backend_init_file_header    elf_i386_fbsd_init_file_header
 #undef elf32_bed
 #define        elf32_bed                               elf32_i386_fbsd_bed
 
@@ -4627,6 +4425,8 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
 
 #include "elf32-target.h"
 
+#undef elf_backend_init_file_header
+
 /* Solaris 2.  */
 
 #undef TARGET_LITTLE_SYM
@@ -4634,7 +4434,13 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
 #undef TARGET_LITTLE_NAME
 #define        TARGET_LITTLE_NAME              "elf32-i386-sol2"
 
-#undef elf_backend_post_process_headers
+static const struct elf_x86_backend_data elf_i386_solaris_arch_bed =
+  {
+    is_solaris                         /* os */
+  };
+
+#undef elf_backend_arch_data
+#define        elf_backend_arch_data           &elf_i386_solaris_arch_bed
 
 /* Restore default: we cannot use ELFOSABI_SOLARIS, otherwise ELFOSABI_NONE
    objects won't be recognized.  */
@@ -4659,7 +4465,7 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
 #define elf_backend_strtab_flags       SHF_STRINGS
 
 /* Called to set the sh_flags, sh_link and sh_info fields of OSECTION which
-   has a type >= SHT_LOOS.  Returns TRUE if these fields were initialised 
+   has a type >= SHT_LOOS.  Returns TRUE if these fields were initialised
    FALSE otherwise.  ISECTION is the best guess matching section from the
    input bfd IBFD, but it might be NULL.  */
 
@@ -4679,60 +4485,60 @@ elf32_i386_copy_solaris_special_section_fields (const bfd *ibfd ATTRIBUTE_UNUSED
 http://docs.oracle.com/cd/E53394_01/html/E54813/chapter6-94076.html#scrolltoc
 
      The following values should be set:
-     
-Type                 Link                           Info
+
+Type                Link                           Info
 -----------------------------------------------------------------------------
 SHT_SUNW_ancillary   The section header index of    0
- [0x6fffffee]        the associated string table.
-       
+ [0x6fffffee]       the associated string table.
+
 SHT_SUNW_capinfo     The section header index of    For a dynamic object, the
- [0x6ffffff0]        the associated symbol table.   section header index of
-                                                    the associated
+ [0x6ffffff0]       the associated symbol table.   section header index of
+                                                   the associated
                                                    SHT_SUNW_capchain table,
                                                    otherwise 0.
 
 SHT_SUNW_symsort     The section header index of    0
- [0x6ffffff1]        the associated symbol table.
+ [0x6ffffff1]       the associated symbol table.
 
 SHT_SUNW_tlssort     The section header index of    0
- [0x6ffffff2]        the associated symbol table.
-       
-SHT_SUNW_LDYNSYM     The section header index of    One greater than the 
- [0x6ffffff3]        the associated string table.   symbol table index of the
-                    This index is the same string  last local symbol, 
+ [0x6ffffff2]       the associated symbol table.
+
+SHT_SUNW_LDYNSYM     The section header index of    One greater than the
+ [0x6ffffff3]       the associated string table.   symbol table index of the
+                    This index is the same string  last local symbol,
                     table used by the SHT_DYNSYM   STB_LOCAL. Since
-                    section.                       SHT_SUNW_LDYNSYM only
-                                                   contains local symbols,
+                    section.                       SHT_SUNW_LDYNSYM only
+                                                   contains local symbols,
                                                    sh_info is equivalent to
                                                    the number of symbols in
                                                    the table.
 
-SHT_SUNW_cap         If symbol capabilities exist,  If any capabilities refer
- [0x6ffffff5]        the section header index of    to named strings, the
-                     the associated                 section header index of
-                    SHT_SUNW_capinfo table,        the associated string 
-                         otherwise 0.              table, otherwise 0.
+SHT_SUNW_cap        If symbol capabilities exist,  If any capabilities refer
+ [0x6ffffff5]       the section header index of    to named strings, the
+                    the associated                 section header index of
+                    SHT_SUNW_capinfo table,        the associated string
+                         otherwise 0.              table, otherwise 0.
 
-SHT_SUNW_move        The section header index of    0
- [0x6ffffffa]        the associated symbol table.
-       
-SHT_SUNW_COMDAT      0                              0
+SHT_SUNW_move       The section header index of    0
+ [0x6ffffffa]       the associated symbol table.
+
+SHT_SUNW_COMDAT             0                              0
  [0x6ffffffb]
 
 SHT_SUNW_syminfo     The section header index of    The section header index
- [0x6ffffffc]        the associated symbol table.   of the associated
-                                                   .dynamic section.
+ [0x6ffffffc]       the associated symbol table.   of the associated
+                                                   .dynamic section.
 
-SHT_SUNW_verdef      The section header index of    The number of version 
- [0x6ffffffd]        the associated string table.   definitions within the
-                                                   section.
+SHT_SUNW_verdef             The section header index of    The number of version
+ [0x6ffffffd]       the associated string table.   definitions within the
+                                                   section.
 
 SHT_SUNW_verneed     The section header index of    The number of version
- [0x6ffffffe]        the associated string table.   dependencies within the
-                                                    section.
+ [0x6ffffffe]       the associated string table.   dependencies within the
+                                                   section.
 
-SHT_SUNW_versym      The section header index of    0
- [0x6fffffff]        the associated symbol table.  */
+SHT_SUNW_versym             The section header index of    0
+ [0x6fffffff]       the associated symbol table.  */
 }
 
 #undef  elf_backend_copy_special_section_fields
@@ -4760,6 +4566,9 @@ elf32_iamcu_elf_object_p (bfd *abfd)
 #undef ELF_MACHINE_CODE
 #define        ELF_MACHINE_CODE                EM_IAMCU
 
+#undef elf_backend_arch_data
+#define        elf_backend_arch_data           &elf_i386_arch_bed
+
 #undef ELF_OSABI
 
 #undef  elf32_bed
@@ -4771,7 +4580,7 @@ elf32_iamcu_elf_object_p (bfd *abfd)
 #undef elf_backend_static_tls_alignment
 
 #undef elf_backend_want_plt_sym
-#define elf_backend_want_plt_sym           0
+#define elf_backend_want_plt_sym       0
 
 #undef  elf_backend_strtab_flags
 #undef  elf_backend_copy_special_section_fields
@@ -4800,7 +4609,6 @@ elf32_iamcu_elf_object_p (bfd *abfd)
 #undef ELF_OSABI
 #undef elf_backend_want_plt_sym
 #define elf_backend_want_plt_sym       0
-#undef elf_backend_post_process_headers
 #undef elf_backend_static_tls_alignment
 
 /* NaCl uses substantially different PLT entries for the same effects.  */
@@ -4813,9 +4621,9 @@ elf32_iamcu_elf_object_p (bfd *abfd)
 static const bfd_byte elf_i386_nacl_plt0_entry[] =
   {
     0xff, 0x35,                          /* pushl contents of address */
-    0, 0, 0, 0,                          /* replaced with address of .got + 4.  */
-    0x8b, 0x0d,                   /* movl contents of address, %ecx */
-    0, 0, 0, 0,                          /* replaced with address of .got + 8.  */
+    0, 0, 0, 0,                          /* replaced with address of .got + 4.  */
+    0x8b, 0x0d,                          /* movl contents of address, %ecx */
+    0, 0, 0, 0,                          /* replaced with address of .got + 8.  */
     0x83, 0xe1, NACLMASK,        /* andl $NACLMASK, %ecx */
     0xff, 0xe1                   /* jmp *%ecx */
   };
@@ -4827,7 +4635,7 @@ static const bfd_byte elf_i386_nacl_plt_entry[NACL_PLT_ENTRY_SIZE] =
     0x83, 0xe1, NACLMASK,              /* andl $NACLMASK, %ecx */
     0xff, 0xe1,                                /* jmp *%ecx */
 
-    /* Pad to the next 32-byte boundary with nop instructions. */
+    /* Pad to the next 32-byte boundary with nop instructions.  */
     0x90,
     0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
     0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
@@ -4836,9 +4644,9 @@ static const bfd_byte elf_i386_nacl_plt_entry[NACL_PLT_ENTRY_SIZE] =
     0x68,                             /* pushl immediate */
     0, 0, 0, 0,                               /* replaced with reloc offset.  */
     0xe9,                             /* jmp relative */
-    0, 0, 0, 0,                               /* replaced with offset to .plt.  */
+    0, 0, 0, 0,                               /* replaced with offset to .plt.  */
 
-    /* Pad to the next 32-byte boundary with nop instructions. */
+    /* Pad to the next 32-byte boundary with nop instructions.  */
     0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
     0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
     0x90, 0x90
@@ -4859,23 +4667,23 @@ elf_i386_nacl_pic_plt0_entry[sizeof (elf_i386_nacl_plt0_entry)] =
 
 static const bfd_byte elf_i386_nacl_pic_plt_entry[NACL_PLT_ENTRY_SIZE] =
   {
-    0x8b, 0x8b,          /* movl offset(%ebx), %ecx */
-    0, 0, 0, 0,          /* replaced with offset of this symbol in .got.  */
-    0x83, 0xe1, 0xe0,    /* andl $NACLMASK, %ecx */
-    0xff, 0xe1,          /* jmp *%ecx */
+    0x8b, 0x8b,                 /* movl offset(%ebx), %ecx */
+    0, 0, 0, 0,                 /* replaced with offset of this symbol in .got.  */
+    0x83, 0xe1, 0xe0,   /* andl $NACLMASK, %ecx */
+    0xff, 0xe1,                 /* jmp *%ecx */
 
-    /* Pad to the next 32-byte boundary with nop instructions. */
+    /* Pad to the next 32-byte boundary with nop instructions.  */
     0x90,
     0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
     0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
 
     /* Lazy GOT entries point here (32-byte aligned).  */
-    0x68,                /* pushl immediate */
-    0, 0, 0, 0,          /* replaced with offset into relocation table.  */
-    0xe9,                /* jmp relative */
-    0, 0, 0, 0,          /* replaced with offset to start of .plt.  */
+    0x68,               /* pushl immediate */
+    0, 0, 0, 0,                 /* replaced with offset into relocation table.  */
+    0xe9,               /* jmp relative */
+    0, 0, 0, 0,                 /* replaced with offset to start of .plt.  */
 
-    /* Pad to the next 32-byte boundary with nop instructions. */
+    /* Pad to the next 32-byte boundary with nop instructions.  */
     0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
     0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
     0x90, 0x90
@@ -4883,38 +4691,38 @@ static const bfd_byte elf_i386_nacl_pic_plt_entry[NACL_PLT_ENTRY_SIZE] =
 
 static const bfd_byte elf_i386_nacl_eh_frame_plt[] =
   {
-#if (PLT_CIE_LENGTH != 20                               \
-     || PLT_FDE_LENGTH != 36                            \
-     || PLT_FDE_START_OFFSET != 4 + PLT_CIE_LENGTH + 8  \
+#if (PLT_CIE_LENGTH != 20                              \
+     || PLT_FDE_LENGTH != 36                           \
+     || PLT_FDE_START_OFFSET != 4 + PLT_CIE_LENGTH + 8 \
      || PLT_FDE_LEN_OFFSET != 4 + PLT_CIE_LENGTH + 12)
-# error "Need elf_i386_backend_data parameters for eh_frame_plt offsets!"
+# error "Need elf_x86_backend_data parameters for eh_frame_plt offsets!"
 #endif
     PLT_CIE_LENGTH, 0, 0, 0,           /* CIE length */
-    0, 0, 0, 0,                         /* CIE ID */
-    1,                                  /* CIE version */
-    'z', 'R', 0,                        /* Augmentation string */
-    1,                                  /* Code alignment factor */
-    0x7c,                               /* Data alignment factor: -4 */
-    8,                                  /* Return address column */
+    0, 0, 0, 0,                                /* CIE ID */
+    1,                                 /* CIE version */
+    'z', 'R', 0,                       /* Augmentation string */
+    1,                                 /* Code alignment factor */
+    0x7c,                              /* Data alignment factor: -4 */
+    8,                                 /* Return address column */
     1,                                 /* Augmentation size */
     DW_EH_PE_pcrel | DW_EH_PE_sdata4,  /* FDE encoding */
     DW_CFA_def_cfa, 4, 4,              /* DW_CFA_def_cfa: r4 (esp) ofs 4 */
     DW_CFA_offset + 8, 1,              /* DW_CFA_offset: r8 (eip) at cfa-4 */
     DW_CFA_nop, DW_CFA_nop,
 
-    PLT_FDE_LENGTH, 0, 0, 0,     /* FDE length */
+    PLT_FDE_LENGTH, 0, 0, 0,    /* FDE length */
     PLT_CIE_LENGTH + 8, 0, 0, 0, /* CIE pointer */
-    0, 0, 0, 0,                  /* R_386_PC32 .plt goes here */
-    0, 0, 0, 0,                  /* .plt size goes here */
-    0,                           /* Augmentation size */
-    DW_CFA_def_cfa_offset, 8,    /* DW_CFA_def_cfa_offset: 8 */
-    DW_CFA_advance_loc + 6,      /* DW_CFA_advance_loc: 6 to __PLT__+6 */
-    DW_CFA_def_cfa_offset, 12,   /* DW_CFA_def_cfa_offset: 12 */
-    DW_CFA_advance_loc + 58,     /* DW_CFA_advance_loc: 58 to __PLT__+64 */
-    DW_CFA_def_cfa_expression,   /* DW_CFA_def_cfa_expression */
-    13,                          /* Block length */
-    DW_OP_breg4, 4,              /* DW_OP_breg4 (esp): 4 */
-    DW_OP_breg8, 0,              /* DW_OP_breg8 (eip): 0 */
+    0, 0, 0, 0,                         /* R_386_PC32 .plt goes here */
+    0, 0, 0, 0,                         /* .plt size goes here */
+    0,                          /* Augmentation size */
+    DW_CFA_def_cfa_offset, 8,   /* DW_CFA_def_cfa_offset: 8 */
+    DW_CFA_advance_loc + 6,     /* DW_CFA_advance_loc: 6 to __PLT__+6 */
+    DW_CFA_def_cfa_offset, 12,  /* DW_CFA_def_cfa_offset: 12 */
+    DW_CFA_advance_loc + 58,    /* DW_CFA_advance_loc: 58 to __PLT__+64 */
+    DW_CFA_def_cfa_expression,  /* DW_CFA_def_cfa_expression */
+    13,                                 /* Block length */
+    DW_OP_breg4, 4,             /* DW_OP_breg4 (esp): 4 */
+    DW_OP_breg8, 0,             /* DW_OP_breg8 (eip): 0 */
     DW_OP_const1u, 63, DW_OP_and, DW_OP_const1u, 37, DW_OP_ge,
     DW_OP_lit2, DW_OP_shl, DW_OP_plus,
     DW_CFA_nop, DW_CFA_nop
@@ -4926,6 +4734,12 @@ static const struct elf_x86_lazy_plt_layout elf_i386_nacl_plt =
     sizeof (elf_i386_nacl_plt0_entry), /* plt0_entry_size */
     elf_i386_nacl_plt_entry,           /* plt_entry */
     NACL_PLT_ENTRY_SIZE,               /* plt_entry_size */
+    NULL,                              /* plt_tlsdesc_entry */
+    0,                                 /* plt_tlsdesc_entry_size*/
+    0,                                 /* plt_tlsdesc_got1_offset */
+    0,                                 /* plt_tlsdesc_got2_offset */
+    0,                                 /* plt_tlsdesc_got1_insn_end */
+    0,                                 /* plt_tlsdesc_got2_insn_end */
     2,                                 /* plt0_got1_offset */
     8,                                 /* plt0_got2_offset */
     0,                                 /* plt0_got2_insn_end */
@@ -4941,10 +4755,9 @@ static const struct elf_x86_lazy_plt_layout elf_i386_nacl_plt =
     sizeof (elf_i386_nacl_eh_frame_plt) /* eh_frame_plt_size */
   };
 
-static const struct elf_i386_backend_data elf_i386_nacl_arch_bed =
+static const struct elf_x86_backend_data elf_i386_nacl_arch_bed =
   {
-    0x90,                               /* plt0_pad_byte: nop insn */
-    is_nacl                             /* os */
+    is_nacl                            /* os */
   };
 
 static bfd_boolean
@@ -4962,8 +4775,8 @@ elf32_i386_nacl_elf_object_p (bfd *abfd)
 #define elf_backend_object_p                   elf32_i386_nacl_elf_object_p
 #undef elf_backend_modify_segment_map
 #define        elf_backend_modify_segment_map          nacl_modify_segment_map
-#undef elf_backend_modify_program_headers
-#define        elf_backend_modify_program_headers      nacl_modify_program_headers
+#undef elf_backend_modify_headers
+#define        elf_backend_modify_headers              nacl_modify_headers
 #undef elf_backend_final_write_processing
 #define elf_backend_final_write_processing     nacl_final_write_processing
 
@@ -4972,7 +4785,7 @@ elf32_i386_nacl_elf_object_p (bfd *abfd)
 /* Restore defaults.  */
 #undef elf_backend_object_p
 #undef elf_backend_modify_segment_map
-#undef elf_backend_modify_program_headers
+#undef elf_backend_modify_headers
 #undef elf_backend_final_write_processing
 
 /* VxWorks support.  */
@@ -4987,10 +4800,9 @@ elf32_i386_nacl_elf_object_p (bfd *abfd)
 #undef elf_backend_plt_alignment
 #define elf_backend_plt_alignment      4
 
-static const struct elf_i386_backend_data elf_i386_vxworks_arch_bed =
+static const struct elf_x86_backend_data elf_i386_vxworks_arch_bed =
   {
-    0x90,                               /* plt0_pad_byte */
-    is_vxworks                          /* os */
+    is_vxworks                         /* os */
   };
 
 #undef elf_backend_arch_data