]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elf32-i386.c
Fix: Null pointer dereference in elf32-i386.c
[thirdparty/binutils-gdb.git] / bfd / elf32-i386.c
index a6ea113f0d8ecf8151a173ddafc6c329eff0dc3b..abfba406a81d117ea0fba687d224a732d6597f9b 100644 (file)
@@ -1,5 +1,5 @@
 /* Intel 80386/80486-specific support for 32-bit ELF
-   Copyright (C) 1993-2018 Free Software Foundation, Inc.
+   Copyright (C) 1993-2023 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -19,7 +19,6 @@
    MA 02110-1301, USA.  */
 
 #include "elfxx-x86.h"
-#include "elf-nacl.h"
 #include "elf-vxworks.h"
 #include "dwarf2.h"
 #include "opcode/i386.h"
 /* 386 uses REL relocations instead of RELA.  */
 #define USE_REL        1
 
-#include "elf/i386.h"
-
 static reloc_howto_type elf_howto_table[]=
 {
-  HOWTO(R_386_NONE, 0, 3, 0, FALSE, 0, complain_overflow_dont,
+  HOWTO(R_386_NONE, 0, 0, 0, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_NONE",
-       TRUE, 0x00000000, 0x00000000, FALSE),
-  HOWTO(R_386_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0x00000000, 0x00000000, false),
+  HOWTO(R_386_32, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_32",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_PC32, 0, 2, 32, TRUE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_PC32, 0, 4, 32, true, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_PC32",
-       TRUE, 0xffffffff, 0xffffffff, TRUE),
-  HOWTO(R_386_GOT32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, true),
+  HOWTO(R_386_GOT32, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_GOT32",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_PLT32, 0, 2, 32, TRUE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_PLT32, 0, 4, 32, true, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_PLT32",
-       TRUE, 0xffffffff, 0xffffffff, TRUE),
-  HOWTO(R_386_COPY, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, true),
+  HOWTO(R_386_COPY, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_COPY",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_GLOB_DAT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_GLOB_DAT, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_GLOB_DAT",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_JUMP_SLOT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_JUMP_SLOT, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_JUMP_SLOT",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_RELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_RELATIVE, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_RELATIVE",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_GOTOFF, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_GOTOFF, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_GOTOFF",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_GOTPC, 0, 2, 32, TRUE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_GOTPC, 0, 4, 32, true, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_GOTPC",
-       TRUE, 0xffffffff, 0xffffffff, TRUE),
+       true, 0xffffffff, 0xffffffff, true),
 
   /* We have a gap in the reloc numbers here.
      R_386_standard counts the number up to this point, and
@@ -73,76 +70,76 @@ static reloc_howto_type elf_howto_table[]=
 #define R_386_ext_offset (R_386_TLS_TPOFF - R_386_standard)
 
   /* These relocs are a GNU extension.  */
-  HOWTO(R_386_TLS_TPOFF, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+  HOWTO(R_386_TLS_TPOFF, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_TPOFF",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_TLS_IE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_TLS_IE, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_IE",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_TLS_GOTIE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_TLS_GOTIE, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_GOTIE",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_TLS_LE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_TLS_LE, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_LE",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_TLS_GD, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_TLS_GD, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_GD",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_TLS_LDM, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_TLS_LDM, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_LDM",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_16, 0, 2, 16, false, 0, complain_overflow_bitfield,
        bfd_elf_generic_reloc, "R_386_16",
-       TRUE, 0xffff, 0xffff, FALSE),
-  HOWTO(R_386_PC16, 0, 1, 16, TRUE, 0, complain_overflow_bitfield,
+       true, 0xffff, 0xffff, false),
+  HOWTO(R_386_PC16, 0, 2, 16, true, 0, complain_overflow_bitfield,
        bfd_elf_generic_reloc, "R_386_PC16",
-       TRUE, 0xffff, 0xffff, TRUE),
-  HOWTO(R_386_8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffff, 0xffff, true),
+  HOWTO(R_386_8, 0, 1, 8, false, 0, complain_overflow_bitfield,
        bfd_elf_generic_reloc, "R_386_8",
-       TRUE, 0xff, 0xff, FALSE),
-  HOWTO(R_386_PC8, 0, 0, 8, TRUE, 0, complain_overflow_signed,
+       true, 0xff, 0xff, false),
+  HOWTO(R_386_PC8, 0, 1, 8, true, 0, complain_overflow_signed,
        bfd_elf_generic_reloc, "R_386_PC8",
-       TRUE, 0xff, 0xff, TRUE),
+       true, 0xff, 0xff, true),
 
 #define R_386_ext (R_386_PC8 + 1 - R_386_ext_offset)
 #define R_386_tls_offset (R_386_TLS_LDO_32 - R_386_ext)
   /* These are common with Solaris TLS implementation.  */
-  HOWTO(R_386_TLS_LDO_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+  HOWTO(R_386_TLS_LDO_32, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_LDO_32",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_TLS_IE_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_TLS_IE_32, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_IE_32",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_TLS_LE_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_TLS_LE_32, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_LE_32",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_TLS_DTPMOD32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_TLS_DTPMOD32, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_DTPMOD32",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_TLS_DTPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_TLS_DTPOFF32, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_DTPOFF32",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_TLS_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_TLS_TPOFF32, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_TPOFF32",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_SIZE32, 0, 2, 32, FALSE, 0, complain_overflow_unsigned,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_SIZE32, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_SIZE32",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_TLS_GOTDESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_TLS_GOTDESC, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_GOTDESC",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_TLS_DESC_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_TLS_DESC_CALL, 0, 0, 0, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_DESC_CALL",
-       FALSE, 0, 0, FALSE),
-  HOWTO(R_386_TLS_DESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       false, 0, 0, false),
+  HOWTO(R_386_TLS_DESC, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_TLS_DESC",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_IRELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_IRELATIVE, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_IRELATIVE",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
-  HOWTO(R_386_GOT32X, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+       true, 0xffffffff, 0xffffffff, false),
+  HOWTO(R_386_GOT32X, 0, 4, 32, false, 0, complain_overflow_dont,
        bfd_elf_generic_reloc, "R_386_GOT32X",
-       TRUE, 0xffffffff, 0xffffffff, FALSE),
+       true, 0xffffffff, 0xffffffff, false),
 
   /* Another gap.  */
 #define R_386_ext2 (R_386_GOT32X + 1 - R_386_tls_offset)
@@ -151,41 +148,37 @@ static reloc_howto_type elf_howto_table[]=
 /* GNU extension to record C++ vtable hierarchy.  */
   HOWTO (R_386_GNU_VTINHERIT,  /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         0,                     /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         NULL,                  /* special_function */
         "R_386_GNU_VTINHERIT", /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0,                     /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
 /* GNU extension to record C++ vtable member usage.  */
   HOWTO (R_386_GNU_VTENTRY,    /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         0,                     /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_elf_rel_vtable_reloc_fn, /* special_function */
         "R_386_GNU_VTENTRY",   /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0,                     /* dst_mask */
-        FALSE)                 /* pcrel_offset */
+        false)                 /* pcrel_offset */
 
 #define R_386_vt (R_386_GNU_VTENTRY + 1 - R_386_vt_offset)
 
 };
 
-#define X86_PCREL_TYPE_P(TYPE) ((TYPE) == R_386_PC32)
-
-#define X86_SIZE_TYPE_P(TYPE) ((TYPE) == R_386_SIZE32)
-
 #ifdef DEBUG_GEN_RELOC
 #define TRACE(str) \
   fprintf (stderr, "i386 bfd reloc lookup %d (%s)\n", code, str)
@@ -194,7 +187,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 +339,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 +363,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 +374,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 (_("%pB: 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 bool
+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
@@ -406,18 +406,18 @@ elf_i386_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
    If so, we should move the .X recognition into
    _bfd_elf_is_local_label_name.  */
 
-static bfd_boolean
+static bool
 elf_i386_is_local_label_name (bfd *abfd, const char *name)
 {
   if (name[0] == '.' && name[1] == 'X')
-    return TRUE;
+    return true;
 
   return _bfd_elf_is_local_label_name (abfd, name);
 }
 \f
 /* Support for core dump NOTE sections.  */
 
-static bfd_boolean
+static bool
 elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 {
   int offset;
@@ -428,7 +428,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);
@@ -445,7 +445,7 @@ elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
       switch (note->descsz)
        {
        default:
-         return FALSE;
+         return false;
 
        case 144:               /* Linux/i386 */
          /* pr_cursig */
@@ -467,7 +467,7 @@ elf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
                                          size, note->descpos + offset);
 }
 
-static bfd_boolean
+static bool
 elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 {
   if (note->namesz == 8 && strcmp (note->namedata, "FreeBSD") == 0)
@@ -475,7 +475,7 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
       int pr_version = bfd_get_32 (abfd, note->descdata);
 
       if (pr_version != 1)
-       return FALSE;
+       return false;
 
       elf_tdata (abfd)->core->program
        = _bfd_elfcore_strndup (abfd, note->descdata + 8, 17);
@@ -487,7 +487,7 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
       switch (note->descsz)
        {
        default:
-         return FALSE;
+         return false;
 
        case 124:               /* Linux/i386 elf_prpsinfo.  */
          elf_tdata (abfd)->core->pid
@@ -510,7 +510,7 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
       command[n - 1] = '\0';
   }
 
-  return TRUE;
+  return true;
 }
 \f
 /* Functions for the i386 ELF linker.
@@ -522,7 +522,7 @@ elf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
    Functions named elf_i386_* are called by external routines, other
    functions are only called locally.  elf_i386_* functions appear
    in this file more or less in the order in which they are called
-   from external routines.  eg. elf_i386_check_relocs is called
+   from external routines.  eg. elf_i386_scan_relocs is called
    early in the link process, elf_i386_finish_dynamic_sections is
    one of the last functions.  */
 
@@ -759,6 +759,12 @@ static const struct elf_x86_lazy_plt_layout elf_i386_lazy_plt =
     sizeof (elf_i386_lazy_plt0_entry), /* plt0_entry_size */
     elf_i386_lazy_plt_entry,           /* plt_entry */
     LAZY_PLT_ENTRY_SIZE,               /* plt_entry_size */
+    NULL,                              /* plt_tlsdesc_entry */
+    0,                                 /* plt_tlsdesc_entry_size*/
+    0,                                 /* plt_tlsdesc_got1_offset */
+    0,                                 /* plt_tlsdesc_got2_offset */
+    0,                                 /* plt_tlsdesc_got1_insn_end */
+    0,                                 /* plt_tlsdesc_got2_insn_end */
     2,                                 /* plt0_got1_offset */
     8,                                 /* plt0_got2_offset */
     0,                                 /* plt0_got2_insn_end */
@@ -791,6 +797,12 @@ static const struct elf_x86_lazy_plt_layout elf_i386_lazy_ibt_plt =
     sizeof (elf_i386_lazy_ibt_plt0_entry), /* plt0_entry_size */
     elf_i386_lazy_ibt_plt_entry,       /* plt_entry */
     LAZY_PLT_ENTRY_SIZE,               /* plt_entry_size */
+    NULL,                              /* plt_tlsdesc_entry */
+    0,                                 /* plt_tlsdesc_entry_size*/
+    0,                                 /* plt_tlsdesc_got1_offset */
+    0,                                 /* plt_tlsdesc_got2_offset */
+    0,                                 /* plt_tlsdesc_got1_insn_end */
+    0,                                 /* plt_tlsdesc_got2_insn_end */
     2,                                 /* plt0_got1_offset */
     8,                                 /* plt0_got2_offset */
     0,                                 /* plt0_got2_insn_end */
@@ -824,18 +836,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
 
-/* These are the standard parameters.  */
-static const struct elf_x86_backend_data elf_i386_arch_bed =
-  {
-    is_normal                          /* os */
-  };
-
-#define        elf_backend_arch_data   &elf_i386_arch_bed
-
 /* Return TRUE if the TLS access code sequence support transition
    from R_TYPE.  */
 
-static bfd_boolean
+static bool
 elf_i386_check_tls_transition (asection *sec,
                               bfd_byte *contents,
                               Elf_Internal_Shdr *symtab_hdr,
@@ -849,7 +853,7 @@ elf_i386_check_tls_transition (asection *sec,
   struct elf_link_hash_entry *h;
   bfd_vma offset;
   bfd_byte *call;
-  bfd_boolean indirect_call;
+  bool indirect_call;
 
   offset = rel->r_offset;
   switch (r_type)
@@ -857,9 +861,9 @@ elf_i386_check_tls_transition (asection *sec,
     case R_386_TLS_GD:
     case R_386_TLS_LDM:
       if (offset < 2 || (rel + 1) >= relend)
-       return FALSE;
+       return false;
 
-      indirect_call = FALSE;
+      indirect_call = false;
       call = contents + offset + 4;
       val = *(call - 5);
       type = *(call - 6);
@@ -880,19 +884,19 @@ elf_i386_check_tls_transition (asection *sec,
             can transit to different access model.  */
          if ((offset + 10) > sec->size
              || (type != 0x8d && type != 0x04))
-           return FALSE;
+           return false;
 
          if (type == 0x04)
            {
              /* leal foo@tlsgd(,%ebx,1), %eax
                 call ___tls_get_addr@PLT  */
              if (offset < 3)
-               return FALSE;
+               return false;
 
              if (*(call - 7) != 0x8d
                  || val != 0x1d
                  || call[0] != 0xe8)
-               return FALSE;
+               return false;
            }
          else
            {
@@ -910,7 +914,7 @@ elf_i386_check_tls_transition (asection *sec,
                 is used to pass parameter to ___tls_get_addr.  */
              reg = val & 7;
              if ((val & 0xf8) != 0x80 || reg == 4 || reg == 0)
-               return FALSE;
+               return false;
 
              indirect_call = call[0] == 0xff;
              if (!(reg == 3 && call[0] == 0xe8 && call[5] == 0x90)
@@ -918,7 +922,7 @@ elf_i386_check_tls_transition (asection *sec,
                  && !(indirect_call
                       && (call[1] & 0xf8) == 0x90
                       && (call[1] & 0x7) == reg))
-               return FALSE;
+               return false;
            }
        }
       else
@@ -933,13 +937,13 @@ elf_i386_check_tls_transition (asection *sec,
                addr32 call ___tls_get_addr
             can transit to different access model.  */
          if (type != 0x8d || (offset + 9) > sec->size)
-           return FALSE;
+           return false;
 
          /* %eax can't be used as the GOT base register since it is
             used to pass parameter to ___tls_get_addr.  */
          reg = val & 7;
          if ((val & 0xf8) != 0x80 || reg == 4 || reg == 0)
-           return FALSE;
+           return false;
 
          indirect_call = call[0] == 0xff;
          if (!(reg == 3 && call[0] == 0xe8)
@@ -947,19 +951,20 @@ elf_i386_check_tls_transition (asection *sec,
              && !(indirect_call
                   && (call[1] & 0xf8) == 0x90
                   && (call[1] & 0x7) == reg))
-           return FALSE;
+           return false;
        }
 
       r_symndx = ELF32_R_SYM (rel[1].r_info);
       if (r_symndx < symtab_hdr->sh_info)
-       return FALSE;
+       return false;
 
       h = sym_hashes[r_symndx - symtab_hdr->sh_info];
       if (h == NULL
          || !((struct elf_x86_link_hash_entry *) h)->tls_get_addr)
-       return FALSE;
+       return false;
       else if (indirect_call)
-       return (ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32X);
+       return (ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32X
+               || ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32);
       else
        return (ELF32_R_TYPE (rel[1].r_info) == R_386_PC32
                || ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
@@ -972,15 +977,15 @@ elf_i386_check_tls_transition (asection *sec,
        */
 
       if (offset < 1 || (offset + 4) > sec->size)
-       return FALSE;
+       return false;
 
       /* Check "movl foo@tpoff(%rip), %eax" first.  */
       val = bfd_get_8 (abfd, contents + offset - 1);
       if (val == 0xa1)
-       return TRUE;
+       return true;
 
       if (offset < 2)
-       return FALSE;
+       return false;
 
       /* Check movl|addl foo@tpoff(%rip), %reg.   */
       type = bfd_get_8 (abfd, contents + offset - 2);
@@ -996,11 +1001,11 @@ elf_i386_check_tls_transition (asection *sec,
        */
 
       if (offset < 2 || (offset + 4) > sec->size)
-       return FALSE;
+       return false;
 
       val = bfd_get_8 (abfd, contents + offset - 1);
       if ((val & 0xc0) != 0x80 || (val & 7) == 4)
-       return FALSE;
+       return false;
 
       type = bfd_get_8 (abfd, contents + offset - 2);
       return type == 0x8b || type == 0x2b || type == 0x03;
@@ -1014,10 +1019,10 @@ elf_i386_check_tls_transition (asection *sec,
         going to be eax.  */
 
       if (offset < 2 || (offset + 4) > sec->size)
-       return FALSE;
+       return false;
 
       if (bfd_get_8 (abfd, contents + offset - 2) != 0x8d)
-       return FALSE;
+       return false;
 
       val = bfd_get_8 (abfd, contents + offset - 1);
       return (val & 0xc7) == 0x83;
@@ -1033,7 +1038,7 @@ elf_i386_check_tls_transition (asection *sec,
          return call[0] == 0xff && call[1] == 0x10;
        }
 
-      return FALSE;
+      return false;
 
     default:
       abort ();
@@ -1043,7 +1048,7 @@ elf_i386_check_tls_transition (asection *sec,
 /* Return TRUE if the TLS access transition is OK or no transition
    will be performed.  Update R_TYPE if there is a transition.  */
 
-static bfd_boolean
+static bool
 elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
                         asection *sec, bfd_byte *contents,
                         Elf_Internal_Shdr *symtab_hdr,
@@ -1053,17 +1058,30 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
                         const Elf_Internal_Rela *relend,
                         struct elf_link_hash_entry *h,
                         unsigned long r_symndx,
-                        bfd_boolean from_relocate_section)
+                        bool from_relocate_section)
 {
   unsigned int from_type = *r_type;
   unsigned int to_type = from_type;
-  bfd_boolean check = TRUE;
+  bool check = true;
+  unsigned int to_le_type, to_ie_type;
 
   /* Skip TLS transition for functions.  */
   if (h != NULL
       && (h->type == STT_FUNC
          || h->type == STT_GNU_IFUNC))
-    return TRUE;
+    return true;
+
+  if (get_elf_backend_data (abfd)->target_os == is_solaris)
+    {
+      /* NB: Solaris only supports R_386_TLS_LE and R_386_TLS_IE.  */
+      to_le_type = R_386_TLS_LE;
+      to_ie_type = R_386_TLS_IE;
+    }
+  else
+    {
+      to_le_type = R_386_TLS_LE_32;
+      to_ie_type = R_386_TLS_IE_32;
+    }
 
   switch (from_type)
     {
@@ -1076,10 +1094,10 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
       if (bfd_link_executable (info))
        {
          if (h == NULL)
-           to_type = R_386_TLS_LE_32;
+           to_type = to_le_type;
          else if (from_type != R_386_TLS_IE
                   && from_type != R_386_TLS_GOTIE)
-           to_type = R_386_TLS_IE_32;
+           to_type = to_ie_type;
        }
 
       /* When we are called from elf_i386_relocate_section, there may
@@ -1089,7 +1107,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
          unsigned int new_to_type = to_type;
 
          if (TLS_TRANSITION_IE_TO_LE_P (info, h, tls_type))
-           new_to_type = R_386_TLS_LE_32;
+           new_to_type = to_le_type;
 
          if (to_type == R_386_TLS_GD
              || to_type == R_386_TLS_GOTDESC
@@ -1098,11 +1116,11 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
              if (tls_type == GOT_TLS_IE_POS)
                new_to_type = R_386_TLS_GOTIE;
              else if (tls_type & GOT_TLS_IE)
-               new_to_type = R_386_TLS_IE_32;
+               new_to_type = to_ie_type;
            }
 
          /* We checked the transition before when we were called from
-            elf_i386_check_relocs.  We only want to check the new
+            elf_i386_scan_relocs.  We only want to check the new
             transition which hasn't been checked before.  */
          check = new_to_type != to_type && from_type == to_type;
          to_type = new_to_type;
@@ -1112,16 +1130,16 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
 
     case R_386_TLS_LDM:
       if (bfd_link_executable (info))
-       to_type = R_386_TLS_LE_32;
+       to_type = to_le_type;
       break;
 
     default:
-      return TRUE;
+      return true;
     }
 
   /* Return TRUE if there is no transition.  */
   if (from_type == to_type)
-    return TRUE;
+    return true;
 
   /* Check if the transition can be performed.  */
   if (check
@@ -1132,8 +1150,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;
@@ -1148,7 +1166,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
            {
              Elf_Internal_Sym *isym;
 
-             isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+             isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
                                            abfd, r_symndx);
              name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
            }
@@ -1156,16 +1174,16 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
 
       _bfd_error_handler
        /* xgettext:c-format */
-       (_("%pB: TLS transition from %s to %s against `%s' at %#Lx "
-          "in section `%pA' 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;
+      return false;
     }
 
   *r_type = to_type;
-  return TRUE;
+  return true;
 }
 
 /* With the local symbol, foo, we convert
@@ -1188,40 +1206,47 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
    instructions.  */
 
 static
-bfd_boolean
+bool
 elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
                             bfd_byte *contents,
                             unsigned int *r_type_p,
                             Elf_Internal_Rela *irel,
                             struct elf_link_hash_entry *h,
-                            bfd_boolean *converted,
+                            bool *converted,
                             struct bfd_link_info *link_info)
 {
   struct elf_x86_link_hash_table *htab;
   unsigned int opcode;
   unsigned int modrm;
-  bfd_boolean baseless;
+  bool baseless;
   Elf_Internal_Sym *isym;
   unsigned int addend;
   unsigned int nop;
   bfd_vma nop_offset;
-  bfd_boolean is_pic;
-  bfd_boolean to_reloc_32;
+  bool is_pic;
+  bool to_reloc_32;
+  bool abs_symbol;
   unsigned int r_type;
   unsigned int r_symndx;
   bfd_vma roff = irel->r_offset;
-  bfd_boolean local_ref;
+  bool local_ref;
   struct elf_x86_link_hash_entry *eh;
 
   if (roff < 2)
-    return TRUE;
+    return true;
 
   /* Addend for R_386_GOT32X relocations must be 0.  */
   addend = bfd_get_32 (abfd, contents + roff);
   if (addend != 0)
-    return TRUE;
+    return true;
 
   htab = elf_x86_hash_table (link_info, I386_ELF_DATA);
+  if (htab == NULL || ! is_x86_elf (abfd, htab))
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return false;
+    }
+
   is_pic = bfd_link_pic (link_info);
 
   r_type = *r_type_p;
@@ -1230,6 +1255,21 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
   modrm = bfd_get_8 (abfd, contents + roff - 1);
   baseless = (modrm & 0xc7) == 0x5;
 
+  if (h)
+    {
+      /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P.  */
+      local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h);
+      isym = NULL;
+      abs_symbol = ABS_SYMBOL_P (h);
+    }
+  else
+    {
+      local_ref = true;
+      isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd,
+                                   r_symndx);
+      abs_symbol = isym->st_shndx == SHN_ABS;
+    }
+
   if (baseless && is_pic)
     {
       /* For PIC, disallow R_386_GOT32X without a base register
@@ -1237,11 +1277,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
       const char *name;
 
       if (h == NULL)
-       {
-         isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd,
-                                       r_symndx);
-         name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
-       }
+       name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
       else
        name = h->root.root.string;
 
@@ -1250,7 +1286,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
        (_("%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;
+      return false;
     }
 
   opcode = bfd_get_8 (abfd, contents + roff - 2);
@@ -1275,9 +1311,6 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
        goto convert_load;
     }
 
-  /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P.  */
-  local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h);
-
   /* Undefined weak symbol is only bound locally in executable
      and its reference is resolved as 0.  */
   if (h->root.type == bfd_link_hash_undefweak
@@ -1288,14 +1321,14 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
        {
          /* No direct branch to 0 for PIC.  */
          if (is_pic)
-           return TRUE;
+           return true;
          else
            goto convert_branch;
        }
       else
        {
          /* We can convert load of address 0 to R_386_32.  */
-         to_reloc_32 = TRUE;
+         to_reloc_32 = true;
          goto convert_load;
        }
     }
@@ -1308,7 +1341,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)
            {
@@ -1324,8 +1357,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;
@@ -1350,7 +1383,7 @@ convert_branch:
          bfd_put_32 (abfd, -4, contents + irel->r_offset);
          irel->r_info = ELF32_R_INFO (r_symndx, R_386_PC32);
          *r_type_p = R_386_PC32;
-         *converted = TRUE;
+         *converted = true;
        }
     }
   else
@@ -1362,7 +1395,7 @@ convert_branch:
         Avoid optimizing _DYNAMIC since ld.so may use its
         link-time address.  */
       if (h == htab->elf.hdynamic)
-       return TRUE;
+       return true;
 
       /* def_regular is set by an assignment in a linker script in
         bfd_elf_record_link_assignment.  start_stop is set on
@@ -1374,9 +1407,12 @@ convert_branch:
               || h->root.type == bfd_link_hash_defweak)
              && local_ref))
        {
-convert_load:
+       convert_load:
          if (opcode == 0x8b)
            {
+             if (abs_symbol && local_ref)
+               to_reloc_32 = true;
+
              if (to_reloc_32)
                {
                  /* Convert "mov foo@GOT[(%reg1)], %reg2" to
@@ -1398,7 +1434,7 @@ convert_load:
            {
              /* Only R_386_32 is supported.  */
              if (!to_reloc_32)
-               return TRUE;
+               return true;
 
              if (opcode == 0x85)
                {
@@ -1423,53 +1459,39 @@ convert_load:
          bfd_put_8 (abfd, opcode, contents + roff - 2);
          irel->r_info = ELF32_R_INFO (r_symndx, r_type);
          *r_type_p = r_type;
-         *converted = TRUE;
+         *converted = true;
        }
     }
 
-  return TRUE;
+  return true;
 }
 
-/* Rename some of the generic section flags to better document how they
-   are used here.  */
-#define check_relocs_failed    sec_flg0
-
 /* Look through the relocs for a section during the first phase, and
-   calculate needed space in the global offset table, procedure linkage
-   table, and dynamic reloc sections.  */
-
-static bfd_boolean
-elf_i386_check_relocs (bfd *abfd,
-                      struct bfd_link_info *info,
-                      asection *sec,
-                      const Elf_Internal_Rela *relocs)
+   calculate needed space in the global offset table, and procedure
+   linkage table.  */
+
+static bool
+elf_i386_scan_relocs (bfd *abfd,
+                     struct bfd_link_info *info,
+                     asection *sec,
+                     const Elf_Internal_Rela *relocs)
 {
   struct elf_x86_link_hash_table *htab;
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
-  asection *sreloc;
   bfd_byte *contents;
-  bfd_boolean converted;
+  bool converted;
 
   if (bfd_link_relocatable (info))
-    return TRUE;
-
-  /* Don't do anything special with non-loaded, non-alloced sections.
-     In particular, any relocs in such sections should not affect GOT
-     and PLT reference counting (ie. we don't allow them to create GOT
-     or PLT entries), there's no possibility or desire to optimize TLS
-     relocs, and there's not much point in propagating relocs to shared
-     libs that the dynamic linker won't relocate.  */
-  if ((sec->flags & SEC_ALLOC) == 0)
-    return TRUE;
+    return true;
 
   htab = elf_x86_hash_table (info, I386_ELF_DATA);
   if (htab == NULL)
     {
       sec->check_relocs_failed = 1;
-      return FALSE;
+      return false;
     }
 
   BFD_ASSERT (is_x86_elf (abfd, htab));
@@ -1480,15 +1502,13 @@ elf_i386_check_relocs (bfd *abfd,
   else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
     {
       sec->check_relocs_failed = 1;
-      return FALSE;
+      return false;
     }
 
   symtab_hdr = &elf_symtab_hdr (abfd);
   sym_hashes = elf_sym_hashes (abfd);
 
-  converted = FALSE;
-
-  sreloc = NULL;
+  converted = false;
 
   rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; rel++)
@@ -1499,7 +1519,8 @@ elf_i386_check_relocs (bfd *abfd,
       struct elf_x86_link_hash_entry *eh;
       Elf_Internal_Sym *isym;
       const char *name;
-      bfd_boolean size_reloc;
+      bool size_reloc;
+      bool no_dynreloc;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
       r_type = ELF32_R_TYPE (rel->r_info);
@@ -1515,7 +1536,7 @@ elf_i386_check_relocs (bfd *abfd,
       if (r_symndx < symtab_hdr->sh_info)
        {
          /* A local symbol.  */
-         isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+         isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
                                        abfd, r_symndx);
          if (isym == NULL)
            goto error_return;
@@ -1523,7 +1544,7 @@ elf_i386_check_relocs (bfd *abfd,
          /* Check relocation against local STT_GNU_IFUNC symbol.  */
          if (ELF32_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
            {
-             h = _bfd_elf_x86_get_local_sym_hash (htab, abfd, rel, TRUE);
+             h = _bfd_elf_x86_get_local_sym_hash (htab, abfd, rel, true);
              if (h == NULL)
                goto error_return;
 
@@ -1556,10 +1577,6 @@ elf_i386_check_relocs (bfd *abfd,
 
          /* It is referenced by a non-shared object. */
          h->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
@@ -1572,15 +1589,19 @@ elf_i386_check_relocs (bfd *abfd,
            goto error_return;
        }
 
+      if (!_bfd_elf_x86_valid_reloc_p (sec, info, htab, rel, h, isym,
+                                      symtab_hdr, &no_dynreloc))
+       return false;
+
       if (! elf_i386_tls_transition (info, abfd, sec, contents,
                                     symtab_hdr, sym_hashes,
                                     &r_type, GOT_UNKNOWN,
-                                    rel, rel_end, h, r_symndx, FALSE))
+                                    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;
+       htab->got_referenced = true;
 
       switch (r_type)
        {
@@ -1607,7 +1628,7 @@ elf_i386_check_relocs (bfd *abfd,
          break;
 
        case R_386_SIZE32:
-         size_reloc = TRUE;
+         size_reloc = true;
          goto do_size;
 
        case R_386_TLS_IE_32:
@@ -1659,25 +1680,12 @@ elf_i386_check_relocs (bfd *abfd,
              {
                bfd_signed_vma *local_got_refcounts;
 
+               if (!elf_x86_allocate_local_got_info (abfd,
+                                                     symtab_hdr->sh_info))
+                     goto error_return;
+
                /* This is a global offset table entry for a local symbol.  */
                local_got_refcounts = elf_local_got_refcounts (abfd);
-               if (local_got_refcounts == NULL)
-                 {
-                   bfd_size_type size;
-
-                   size = symtab_hdr->sh_info;
-                   size *= (sizeof (bfd_signed_vma)
-                            + sizeof (bfd_vma) + sizeof(char));
-                   local_got_refcounts = (bfd_signed_vma *)
-                       bfd_zalloc (abfd, size);
-                   if (local_got_refcounts == NULL)
-                     goto error_return;
-                   elf_local_got_refcounts (abfd) = local_got_refcounts;
-                   elf_x86_local_tlsdesc_gotent (abfd)
-                     = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
-                   elf_x86_local_got_tls_type (abfd)
-                     = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info);
-                 }
                local_got_refcounts[r_symndx] = 1;
                old_tls_type = elf_x86_local_got_tls_type (abfd) [r_symndx];
              }
@@ -1724,7 +1732,7 @@ elf_i386_check_relocs (bfd *abfd,
 
        case R_386_GOTOFF:
        case R_386_GOTPC:
-create_got:
+       create_got:
          if (r_type != R_386_TLS_IE)
            {
              if (eh != NULL)
@@ -1735,7 +1743,7 @@ create_got:
                  if (r_type == R_386_GOTOFF
                      && h->root.type == bfd_link_hash_undefweak
                      && bfd_link_executable (info))
-                   htab->got_referenced = TRUE;
+                   htab->got_referenced = true;
                }
              break;
            }
@@ -1754,7 +1762,7 @@ create_got:
        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.  */
@@ -1762,7 +1770,7 @@ do_relocation:
              && (bfd_link_executable (info)
                  || h->type == STT_GNU_IFUNC))
            {
-             bfd_boolean func_pointer_ref = FALSE;
+             bool func_pointer_ref = false;
 
              if (r_type == R_386_PC32)
                {
@@ -1784,11 +1792,20 @@ do_relocation:
                }
              else
                {
-                 h->pointer_equality_needed = 1;
-                 /* R_386_32 can be resolved at run-time.  */
+                 /* R_386_32 can be resolved at run-time.  Function
+                    pointer reference doesn't need PLT for pointer
+                    equality.  */
                  if (r_type == R_386_32
                      && (sec->flags & SEC_READONLY) == 0)
-                   func_pointer_ref = TRUE;
+                   func_pointer_ref = true;
+
+                 /* IFUNC symbol needs pointer equality in PDE so that
+                    function pointer reference will be resolved to its
+                    PLT entry directly.  */
+                 if (!func_pointer_ref
+                     || (bfd_link_pde (info)
+                         && h->type == STT_GNU_IFUNC))
+                   h->pointer_equality_needed = 1;
                }
 
              if (!func_pointer_ref)
@@ -1801,40 +1818,51 @@ do_relocation:
                     adjust_dynamic_symbol.  */
                  h->non_got_ref = 1;
 
+                 if (!elf_has_indirect_extern_access (sec->owner))
+                   eh->non_got_ref_without_indirect_extern_access = 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;
+
+                 if (htab->elf.target_os != is_solaris
+                     && h->pointer_equality_needed
+                     && h->type == STT_FUNC
+                     && eh->def_protected
+                     && !SYMBOL_DEFINED_NON_SHARED_P (h)
+                     && h->def_dynamic)
+                   {
+                     /* Disallow non-canonical reference to canonical
+                        protected function.  */
+                     _bfd_error_handler
+                       /* xgettext:c-format */
+                       (_("%pB: non-canonical reference to canonical "
+                          "protected function `%s' in %pB"),
+                        abfd, h->root.root.string,
+                        h->root.u.def.section->owner);
+                     bfd_set_error (bfd_error_bad_value);
+                     goto error_return;
+                   }
                }
            }
 
-         size_reloc = FALSE;
-do_size:
-         if (NEED_DYNAMIC_RELOCATION_P (info, FALSE, h, sec, r_type,
-                                        R_386_32))
+         size_reloc = false;
+       do_size:
+         if (!no_dynreloc
+             && NEED_DYNAMIC_RELOCATION_P (false, info, false, h, sec,
+                                           r_type, R_386_32))
            {
              struct elf_dyn_relocs *p;
              struct elf_dyn_relocs **head;
 
-             /* We must copy these reloc types into the output file.
-                Create a reloc section in dynobj and make room for
-                this reloc.  */
-             if (sreloc == NULL)
-               {
-                 sreloc = _bfd_elf_make_dynamic_reloc_section
-                   (sec, htab->elf.dynobj, 2, abfd, /*rela?*/ FALSE);
-
-                 if (sreloc == NULL)
-                   goto error_return;
-               }
-
              /* If this is a global symbol, we count the number of
                 relocations we need for this symbol.  */
              if (h != NULL)
                {
-                 head = &eh->dyn_relocs;
+                 head = &h->dyn_relocs;
                }
              else
                {
@@ -1844,7 +1872,7 @@ do_size:
                  void **vpp;
                  asection *s;
 
-                 isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+                 isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
                                                abfd, r_symndx);
                  if (isym == NULL)
                    goto error_return;
@@ -1860,7 +1888,7 @@ 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);
                  if (p == NULL)
@@ -1889,9 +1917,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;
 
@@ -1902,13 +1928,14 @@ do_size:
 
   if (elf_section_data (sec)->this_hdr.contents != contents)
     {
-      if (!converted && !info->keep_memory)
+      if (!converted && !_bfd_link_keep_memory (info))
        free (contents);
       else
        {
          /* Cache the section contents for elf_link_input_bfd if any
             load is converted or --no-keep-memory isn't used.  */
          elf_section_data (sec)->this_hdr.contents = contents;
+         info->cache_size += sec->size;
        }
     }
 
@@ -1916,26 +1943,44 @@ do_size:
   if (elf_section_data (sec)->relocs != relocs && converted)
     elf_section_data (sec)->relocs = (Elf_Internal_Rela *) relocs;
 
-  return TRUE;
+  return true;
 
-error_return:
+ error_return:
   if (elf_section_data (sec)->this_hdr.contents != contents)
     free (contents);
   sec->check_relocs_failed = 1;
-  return FALSE;
+  return false;
+}
+
+static bool
+elf_i386_always_size_sections (bfd *output_bfd,
+                              struct bfd_link_info *info)
+{
+  bfd *abfd;
+
+  /* Scan relocations after rel_from_abs has been set on __ehdr_start.  */
+  for (abfd = info->input_bfds;
+       abfd != (bfd *) NULL;
+       abfd = abfd->link.next)
+    if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+       && !_bfd_elf_link_iterate_on_relocs (abfd, info,
+                                            elf_i386_scan_relocs))
+      return false;
+
+  return _bfd_x86_elf_always_size_sections (output_bfd, info);
 }
 
 /* Set the correct type for an x86 ELF section.  We do this by the
    section name, which is a hack, but ought to work.  */
 
-static bfd_boolean
+static bool
 elf_i386_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
                        Elf_Internal_Shdr *hdr,
                        asection *sec)
 {
   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
@@ -1956,7 +2001,7 @@ elf_i386_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
   if (strcmp (name, ".reloc") == 0)
     hdr->sh_type = SHT_PROGBITS;
 
-  return TRUE;
+  return true;
 }
 
 /* Return the relocation value for @tpoff relocation
@@ -1980,7 +2025,7 @@ elf_i386_tpoff (struct bfd_link_info *info, bfd_vma address)
 
 /* Relocate an i386 ELF section.  */
 
-static bfd_boolean
+static int
 elf_i386_relocate_section (bfd *output_bfd,
                           struct bfd_link_info *info,
                           bfd *input_bfd,
@@ -1998,18 +2043,23 @@ elf_i386_relocate_section (bfd *output_bfd,
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *wrel;
   Elf_Internal_Rela *relend;
-  bfd_boolean is_vxworks_tls;
+  bool is_vxworks_tls;
+  unsigned expected_tls_le;
   unsigned plt_entry_size;
 
-  /* Skip if check_relocs failed.  */
+  /* Skip if check_relocs or scan_relocs failed.  */
   if (input_section->check_relocs_failed)
-    return FALSE;
+    return false;
 
   htab = elf_x86_hash_table (info, I386_ELF_DATA);
   if (htab == NULL)
-    return FALSE;
+    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);
@@ -2017,7 +2067,7 @@ 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->target_os == is_vxworks
+  is_vxworks_tls = (htab->elf.target_os == is_vxworks
                    && bfd_link_pic (info)
                    && !strcmp (input_section->output_section->name,
                                ".tls_vars"));
@@ -2039,14 +2089,14 @@ elf_i386_relocate_section (bfd *output_bfd,
       asection *sec;
       bfd_vma off, offplt, plt_offset;
       bfd_vma relocation;
-      bfd_boolean unresolved_reloc;
+      bool unresolved_reloc;
       bfd_reloc_status_type r;
       unsigned int indx;
       int tls_type;
       bfd_vma st_size;
       asection *resolved_plt;
-      bfd_boolean resolved_to_zero;
-      bfd_boolean relative_reloc;
+      bool resolved_to_zero;
+      bool relative_reloc;
 
       r_type = ELF32_R_TYPE (rel->r_info);
       if (r_type == R_386_GNU_VTINHERIT
@@ -2057,20 +2107,15 @@ 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;
       sec = NULL;
-      unresolved_reloc = FALSE;
+      unresolved_reloc = false;
       if (r_symndx < symtab_hdr->sh_info)
        {
          sym = local_syms + r_symndx;
@@ -2088,9 +2133,9 @@ elf_i386_relocate_section (bfd *output_bfd,
              bfd_vma addend;
              bfd_byte *where = contents + rel->r_offset;
 
-             switch (howto->size)
+             switch (bfd_get_reloc_size (howto))
                {
-               case 0:
+               case 1:
                  addend = bfd_get_8 (input_bfd, where);
                  if (howto->pc_relative)
                    {
@@ -2098,7 +2143,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                      addend += 1;
                    }
                  break;
-               case 1:
+               case 2:
                  addend = bfd_get_16 (input_bfd, where);
                  if (howto->pc_relative)
                    {
@@ -2106,7 +2151,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                      addend += 2;
                    }
                  break;
-               case 2:
+               case 4:
                  addend = bfd_get_32 (input_bfd, where);
                  if (howto->pc_relative)
                    {
@@ -2129,20 +2174,20 @@ elf_i386_relocate_section (bfd *output_bfd,
                  addend += msec->output_section->vma + msec->output_offset;
                }
 
-             switch (howto->size)
+             switch (bfd_get_reloc_size (howto))
                {
-               case 0:
+               case 1:
                  /* FIXME: overflow checks.  */
                  if (howto->pc_relative)
                    addend -= 1;
                  bfd_put_8 (input_bfd, addend, where);
                  break;
-               case 1:
+               case 2:
                  if (howto->pc_relative)
                    addend -= 2;
                  bfd_put_16 (input_bfd, addend, where);
                  break;
-               case 2:
+               case 4:
                  if (howto->pc_relative)
                    addend -= 4;
                  bfd_put_32 (input_bfd, addend, where);
@@ -2154,7 +2199,7 @@ elf_i386_relocate_section (bfd *output_bfd,
            {
              /* Relocate against local STT_GNU_IFUNC symbol.  */
              h = _bfd_elf_x86_get_local_sym_hash (htab, input_bfd, rel,
-                                                  FALSE);
+                                                  false);
              if (h == NULL)
                abort ();
 
@@ -2165,8 +2210,8 @@ elf_i386_relocate_section (bfd *output_bfd,
        }
       else
        {
-         bfd_boolean warned ATTRIBUTE_UNUSED;
-         bfd_boolean ignored ATTRIBUTE_UNUSED;
+         bool warned ATTRIBUTE_UNUSED;
+         bool ignored ATTRIBUTE_UNUSED;
 
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
                                   r_symndx, symtab_hdr, sym_hashes,
@@ -2178,7 +2223,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;
@@ -2214,6 +2259,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.  */
@@ -2286,7 +2335,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                    {
                      /* This references the local defitionion.  We must
                         initialize this entry in the global offset table.
-                        Since the offset must always be a multiple of 8,
+                        Since the offset must always be a multiple of 4,
                         we use the least significant bit to record
                         whether we have initialized it already.
 
@@ -2346,7 +2395,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
@@ -2358,7 +2407,7 @@ bad_ifunc_reloc:
                   "symbol `%s' isn't supported"), input_bfd,
                 howto->name, name);
              bfd_set_error (bfd_error_bad_value);
-             return FALSE;
+             return false;
 
            case R_386_32:
              /* Generate dynamic relcoation only when there is a
@@ -2370,7 +2419,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,
@@ -2393,6 +2442,12 @@ do_ifunc_pointer:
 
                      /* This symbol is resolved locally.  */
                      outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
+
+                     if (htab->params->report_relative_reloc)
+                       _bfd_x86_elf_link_report_relative_reloc
+                         (info, input_section, h, sym,
+                          "R_386_IRELATIVE", &outrel);
+
                      bfd_put_32 (output_bfd,
                                  (h->root.u.def.value
                                   + h->root.u.def.section->output_section->vma
@@ -2427,84 +2482,31 @@ do_ifunc_pointer:
              goto do_relocation;
 
            case R_386_GOTOFF:
+             /* NB: We can't use the PLT entry as the function address
+                for PIC since the PIC register may not be set up
+                properly for indirect call. */
+             if (bfd_link_pic (info))
+               goto bad_ifunc_reloc;
              relocation -= (gotplt->output_section->vma
                             + gotplt->output_offset);
              goto do_relocation;
            }
        }
 
+    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)
            abort ();
 
-         relative_reloc = FALSE;
+         relative_reloc = false;
          if (h != NULL)
            {
              off = h->got.offset;
@@ -2525,18 +2527,20 @@ r_386_got32:
                      bfd_put_32 (output_bfd, relocation,
                                  htab->elf.sgot->contents + off);
                      h->got.offset |= 1;
-
-                     if (GENERATE_RELATIVE_RELOC_P (info, h))
+                     /* NB: Don't generate relative relocation here if
+                        it has been generated by DT_RELR.  */
+                     if (!info->enable_dt_relr
+                         && GENERATE_RELATIVE_RELOC_P (info, h))
                        {
                          /* PR ld/21402: If this symbol isn't dynamic
                             in PIC, generate R_386_RELATIVE here.  */
                          eh->no_finish_dynamic_symbol = 1;
-                         relative_reloc = TRUE;
+                         relative_reloc = true;
                        }
                    }
                }
              else
-               unresolved_reloc = FALSE;
+               unresolved_reloc = false;
            }
          else
            {
@@ -2556,8 +2560,10 @@ r_386_got32:
                              htab->elf.sgot->contents + off);
                  local_got_offsets[r_symndx] |= 1;
 
-                 if (bfd_link_pic (info))
-                   relative_reloc = TRUE;
+                 /* NB: Don't generate relative relocation here if it
+                    has been generated by DT_RELR.  */
+                 if (!info->enable_dt_relr && bfd_link_pic (info))
+                   relative_reloc = true;
                }
            }
 
@@ -2574,6 +2580,12 @@ r_386_got32:
                                 + htab->elf.sgot->output_offset
                                 + off);
              outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+
+             if (htab->params->report_relative_reloc)
+               _bfd_x86_elf_link_report_relative_reloc
+                 (info, input_section, h, sym, "R_386_RELATIVE",
+                  &outrel);
+
              elf_append_rel (output_bfd, s, &outrel);
            }
 
@@ -2593,7 +2605,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 +2619,7 @@ disallow_got32:
                       " when making a shared object"),
                     input_bfd, howto->name, name);
                  bfd_set_error (bfd_error_bad_value);
-                 return FALSE;
+                 return false;
                }
            }
          else
@@ -2656,7 +2668,7 @@ disallow_got32:
                       " `%s' can not be used when making a shared object"),
                     input_bfd, v, h->root.root.string);
                  bfd_set_error (bfd_error_bad_value);
-                 return FALSE;
+                 return false;
                }
              else if (!SYMBOL_REFERENCES_LOCAL_P (info, h)
                       && (h->type == STT_FUNC
@@ -2671,7 +2683,7 @@ disallow_got32:
                     h->type == STT_FUNC ? "function" : "data",
                     h->root.root.string);
                  bfd_set_error (bfd_error_bad_value);
-                 return FALSE;
+                 return false;
                }
            }
 
@@ -2688,7 +2700,7 @@ disallow_got32:
          /* Use global offset table as symbol value.  */
          relocation = htab->elf.sgotplt->output_section->vma
                       + htab->elf.sgotplt->output_offset;
-         unresolved_reloc = FALSE;
+         unresolved_reloc = false;
          break;
 
        case R_386_PLT32:
@@ -2732,7 +2744,7 @@ disallow_got32:
          relocation = (resolved_plt->output_section->vma
                        + resolved_plt->output_offset
                        + plt_offset);
-         unresolved_reloc = FALSE;
+         unresolved_reloc = false;
          break;
 
        case R_386_SIZE32:
@@ -2746,51 +2758,68 @@ disallow_got32:
              || is_vxworks_tls)
            break;
 
-         if (GENERATE_DYNAMIC_RELOCATION_P (info, eh, r_type,
-                                            FALSE, resolved_to_zero,
+         if (GENERATE_DYNAMIC_RELOCATION_P (false, info, eh, r_type,
+                                            sec, false,
+                                            resolved_to_zero,
                                             (r_type == R_386_PC32)))
            {
              Elf_Internal_Rela outrel;
-             bfd_boolean skip, relocate;
+             bool skip, relocate;
+             bool generate_dynamic_reloc = true;
              asection *sreloc;
 
              /* When generating a shared object, these relocations
                 are copied into the output file to be resolved at run
                 time.  */
 
-             skip = FALSE;
-             relocate = FALSE;
+             skip = false;
+             relocate = false;
 
              outrel.r_offset =
                _bfd_elf_section_offset (output_bfd, info, input_section,
                                         rel->r_offset);
              if (outrel.r_offset == (bfd_vma) -1)
-               skip = TRUE;
+               skip = true;
              else if (outrel.r_offset == (bfd_vma) -2)
-               skip = TRUE, relocate = TRUE;
+               skip = true, relocate = true;
              outrel.r_offset += (input_section->output_section->vma
                                  + input_section->output_offset);
 
              if (skip)
                memset (&outrel, 0, sizeof outrel);
-             else if (COPY_INPUT_RELOC_P (info, h, r_type))
+             else if (COPY_INPUT_RELOC_P (false, info, h, r_type))
                outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
              else
                {
                  /* This symbol is local, or marked to become local.  */
-                 relocate = TRUE;
-                 outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
-               }
+                 relocate = true;
+                 /* NB: Don't generate relative relocation here if it
+                    has been generated by DT_RELR.  */
+                 if (info->enable_dt_relr)
+                   generate_dynamic_reloc = false;
+                 else
+                   {
+                     outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
 
-             sreloc = elf_section_data (input_section)->sreloc;
+                     if (htab->params->report_relative_reloc)
+                       _bfd_x86_elf_link_report_relative_reloc
+                         (info, input_section, h, sym, "R_386_RELATIVE",
+                          &outrel);
+                   }
+               }
 
-             if (sreloc == NULL || sreloc->contents == NULL)
+             if (generate_dynamic_reloc)
                {
-                 r = bfd_reloc_notsupported;
-                 goto check_relocation_error;
-               }
+                 sreloc = elf_section_data (input_section)->sreloc;
 
-             elf_append_rel (output_bfd, sreloc, &outrel);
+                 if (sreloc == NULL || sreloc->contents == NULL)
+                   {
+                     r = bfd_reloc_notsupported;
+                     goto check_relocation_error;
+                   }
+
+                 elf_append_rel (output_bfd, sreloc, &outrel);
+               }
 
              /* If this reloc is against an external symbol, we do
                 not want to fiddle with the addend.  Otherwise, we
@@ -2811,6 +2840,12 @@ disallow_got32:
                                + input_section->output_section->vma
                                + input_section->output_offset;
              outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+
+             if (htab->params->report_relative_reloc)
+               _bfd_x86_elf_link_report_relative_reloc
+                 (info, input_section, h, sym, "R_386_RELATIVE",
+                  &outrel);
+
              sreloc = elf_section_data (input_section)->sreloc;
              if (sreloc == NULL)
                abort ();
@@ -2836,12 +2871,20 @@ disallow_got32:
                                         input_section, contents,
                                         symtab_hdr, sym_hashes,
                                         &r_type_tls, tls_type, rel,
-                                        relend, h, r_symndx, TRUE))
-           return FALSE;
+                                        relend, h, r_symndx, true))
+           return false;
 
-         if (r_type_tls == R_386_TLS_LE_32)
+         expected_tls_le = htab->elf.target_os == is_solaris
+           ? R_386_TLS_LE : R_386_TLS_LE_32;
+         if (r_type_tls == expected_tls_le)
            {
-             BFD_ASSERT (! unresolved_reloc);
+             /* NB: Solaris only supports R_386_TLS_GD->R_386_TLS_LE.  */
+             BFD_ASSERT (! unresolved_reloc
+                         && (htab->elf.target_os != is_solaris
+                             || (htab->elf.target_os == is_solaris
+                                 && (r_type == R_386_TLS_GD
+                                     || r_type == R_386_TLS_IE
+                                     || r_type == R_386_TLS_GOTIE))));
              if (r_type == R_386_TLS_GD)
                {
                  unsigned int type;
@@ -3166,7 +3209,7 @@ disallow_got32:
              || r_type_tls == R_386_TLS_DESC_CALL)
            {
              relocation = htab->sgotplt_jump_table_size + offplt;
-             unresolved_reloc = FALSE;
+             unresolved_reloc = false;
            }
          else if (r_type_tls == r_type)
            {
@@ -3179,7 +3222,7 @@ disallow_got32:
                relocation += 4;
              if (r_type == R_386_TLS_IE)
                relocation += g_o_t;
-             unresolved_reloc = FALSE;
+             unresolved_reloc = false;
            }
          else if (r_type == R_386_TLS_GD)
            {
@@ -3310,7 +3353,7 @@ disallow_got32:
              continue;
            }
          else
-           BFD_ASSERT (FALSE);
+           BFD_ASSERT (false);
          break;
 
        case R_386_TLS_LDM:
@@ -3318,8 +3361,8 @@ disallow_got32:
                                         input_section, contents,
                                         symtab_hdr, sym_hashes,
                                         &r_type, GOT_UNKNOWN, rel,
-                                        relend, h, r_symndx, TRUE))
-           return FALSE;
+                                        relend, h, r_symndx, true))
+           return false;
 
          if (r_type != R_386_TLS_LDM)
            {
@@ -3338,7 +3381,9 @@ disallow_got32:
                 into:
                        movl %gs:0, %eax
                        leal 0(%esi), %esi  */
-             BFD_ASSERT (r_type == R_386_TLS_LE_32);
+             expected_tls_le = htab->elf.target_os == is_solaris
+               ? R_386_TLS_LE : R_386_TLS_LE_32;
+             BFD_ASSERT (r_type == expected_tls_le);
              if (*(contents + rel->r_offset + 4) == 0xff
                  || *(contents + rel->r_offset + 4) == 0x67)
                memcpy (contents + rel->r_offset - 2,
@@ -3380,7 +3425,7 @@ disallow_got32:
                       + htab->elf.sgot->output_offset + off
                       - htab->elf.sgotplt->output_section->vma
                       - htab->elf.sgotplt->output_offset;
-         unresolved_reloc = FALSE;
+         unresolved_reloc = false;
          break;
 
        case R_386_TLS_LDO_32:
@@ -3442,21 +3487,21 @@ disallow_got32:
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%pB(%pA+%#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;
+         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;
@@ -3469,9 +3514,9 @@ check_relocation_error:
                                                      symtab_hdr->sh_link,
                                                      sym->st_name);
              if (name == NULL)
-               return FALSE;
+               return false;
              if (*name == '\0')
-               name = bfd_section_name (input_bfd, sec);
+               name = bfd_section_name (sec);
            }
 
          if (r == bfd_reloc_overflow)
@@ -3482,10 +3527,10 @@ check_relocation_error:
            {
              _bfd_error_handler
                /* xgettext:c-format */
-               (_("%pB(%pA+%#Lx): reloc against `%s': error %d"),
+               (_("%pB(%pA+%#" PRIx64 "): reloc against `%s': error %d"),
                 input_bfd, input_section,
-                rel->r_offset, name, (int) r);
-             return FALSE;
+                (uint64_t) rel->r_offset, name, (int) r);
+             return false;
            }
        }
 
@@ -3513,13 +3558,13 @@ check_relocation_error:
       input_section->reloc_count -= deleted;
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
 
-static bfd_boolean
+static bool
 elf_i386_finish_dynamic_symbol (bfd *output_bfd,
                                struct bfd_link_info *info,
                                struct elf_link_hash_entry *h,
@@ -3528,12 +3573,12 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
   struct elf_x86_link_hash_table *htab;
   unsigned plt_entry_size;
   struct elf_x86_link_hash_entry *eh;
-  bfd_boolean local_undefweak;
-  bfd_boolean use_plt_second;
+  bool local_undefweak;
+  bool use_plt_second;
 
   htab = elf_x86_hash_table (info, I386_ELF_DATA);
   if (htab == NULL)
-    return FALSE;
+    return false;
 
   plt_entry_size = htab->plt.plt_entry_size;
 
@@ -3630,7 +3675,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
                      resolved_plt->contents + plt_offset
                      + htab->plt.plt_got_offset);
 
-         if (htab->target_os == is_vxworks)
+         if (htab->elf.target_os == is_vxworks)
            {
              int s, k, reloc_index;
 
@@ -3706,6 +3751,11 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
                           + h->root.u.def.section->output_offset),
                          gotplt->contents + got_offset);
              rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
+
+             if (htab->params->report_relative_reloc)
+               _bfd_x86_elf_link_report_relative_reloc
+                 (info, relplt, h, sym, "R_386_IRELATIVE", &rel);
+
              /* R_386_IRELATIVE comes last.  */
              plt_index = htab->next_irelative_index--;
            }
@@ -3793,6 +3843,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
@@ -3802,6 +3854,8 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
     {
       Elf_Internal_Rela rel;
       asection *relgot = htab->elf.srelgot;
+      const char *relative_reloc_name = NULL;
+      bool generate_dynamic_reloc = true;
 
       /* This symbol has an entry in the global offset table.  Set it
         up.  */
@@ -3842,6 +3896,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
                               + h->root.u.def.section->output_offset),
                              htab->elf.sgot->contents + h->got.offset);
                  rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
+                 relative_reloc_name = "R_386_IRELATIVE";
                }
              else
                goto do_glob_dat;
@@ -3876,25 +3931,39 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
                          (plt->output_section->vma
                           + plt->output_offset + plt_offset),
                          htab->elf.sgot->contents + h->got.offset);
-             return TRUE;
+             return true;
            }
        }
       else if (bfd_link_pic (info)
               && SYMBOL_REFERENCES_LOCAL_P (info, h))
        {
          BFD_ASSERT((h->got.offset & 1) != 0);
-         rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+         if (info->enable_dt_relr)
+           generate_dynamic_reloc = false;
+         else
+           {
+             rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+             relative_reloc_name = "R_386_RELATIVE";
+           }
        }
       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);
        }
 
-      elf_append_rel (output_bfd, relgot, &rel);
+      if (generate_dynamic_reloc)
+       {
+         if (relative_reloc_name != NULL
+             && htab->params->report_relative_reloc)
+           _bfd_x86_elf_link_report_relative_reloc
+             (info, relgot, h, sym, relative_reloc_name, &rel);
+
+         elf_append_rel (output_bfd, relgot, &rel);
+       }
     }
 
   if (h->needs_copy)
@@ -3916,13 +3985,13 @@ do_glob_dat:
       elf_append_rel (output_bfd, s, &rel);
     }
 
-  return TRUE;
+  return true;
 }
 
 /* Finish up local dynamic symbol handling.  We set the contents of
    various dynamic sections here.  */
 
-static bfd_boolean
+static int
 elf_i386_finish_local_dynamic_symbol (void **slot, void *inf)
 {
   struct elf_link_hash_entry *h
@@ -3938,7 +4007,7 @@ elf_i386_finish_local_dynamic_symbol (void **slot, void *inf)
    here since undefined weak symbol may not be dynamic and may not be
    called for elf_i386_finish_dynamic_symbol.  */
 
-static bfd_boolean
+static bool
 elf_i386_pie_finish_undefweak_symbol (struct bfd_hash_entry *bh,
                                      void *inf)
 {
@@ -3947,7 +4016,7 @@ elf_i386_pie_finish_undefweak_symbol (struct bfd_hash_entry *bh,
 
   if (h->root.type != bfd_link_hash_undefweak
       || h->dynindx != -1)
-    return TRUE;
+    return true;
 
   return elf_i386_finish_dynamic_symbol (info->output_bfd,
                                         info, h, NULL);
@@ -4002,7 +4071,7 @@ elf_i386_reloc_type_class (const struct bfd_link_info *info,
 
 /* Finish up the dynamic sections.  */
 
-static bfd_boolean
+static bool
 elf_i386_finish_dynamic_sections (bfd *output_bfd,
                                  struct bfd_link_info *info)
 {
@@ -4010,13 +4079,21 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
 
   htab = _bfd_x86_elf_finish_dynamic_sections (output_bfd, info);
   if (htab == NULL)
-    return FALSE;
+    return false;
 
   if (!htab->elf.dynamic_sections_created)
-    return TRUE;
+    return true;
 
   if (htab->elf.splt && htab->elf.splt->size > 0)
     {
+      if (bfd_is_abs_section (htab->elf.splt->output_section))
+       {
+         info->callbacks->einfo
+           (_("%F%P: discarded output section: `%pA'\n"),
+            htab->elf.splt);
+         return false;
+       }
+
       /* 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)
@@ -4046,7 +4123,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
                          htab->elf.splt->contents
                          + htab->lazy_plt->plt0_got2_offset);
 
-             if (htab->target_os == is_vxworks)
+             if (htab->elf.target_os == is_vxworks)
                {
                  Elf_Internal_Rela rel;
                  int num_plts = (htab->elf.splt->size
@@ -4106,7 +4183,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
                       elf_i386_pie_finish_undefweak_symbol,
                       info);
 
-  return TRUE;
+  return true;
 }
 
 /* Fill PLT/GOT entries and allocate dynamic relocations for local
@@ -4114,7 +4191,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
    It has to be done before elf_link_sort_relocs is called so that
    dynamic relocations are properly sorted.  */
 
-static bfd_boolean
+static bool
 elf_i386_output_arch_local_syms
   (bfd *output_bfd ATTRIBUTE_UNUSED,
    struct bfd_link_info *info,
@@ -4127,19 +4204,16 @@ elf_i386_output_arch_local_syms
   struct elf_x86_link_hash_table *htab
     = elf_x86_hash_table (info, I386_ELF_DATA);
   if (htab == NULL)
-    return FALSE;
+    return false;
 
   /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols.  */
   htab_traverse (htab->loc_hash_table,
                 elf_i386_finish_local_dynamic_symbol,
                 info);
 
-  return TRUE;
+  return true;
 }
 
-/* Forward declaration.  */
-static const struct elf_x86_lazy_plt_layout elf_i386_nacl_plt;
-
 /* Similar to _bfd_elf_get_synthetic_symtab.  Support PLTs with all
    dynamic relocations.   */
 
@@ -4187,7 +4261,7 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
   lazy_plt = NULL;
   non_lazy_ibt_plt = NULL;
   lazy_ibt_plt = NULL;
-  switch (get_elf_x86_backend_data (abfd)->target_os)
+  switch (get_elf_backend_data (abfd)->target_os)
     {
     case is_normal:
     case is_solaris:
@@ -4198,9 +4272,8 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
     case is_vxworks:
       lazy_plt = &elf_i386_lazy_plt;
       break;
-    case is_nacl:
-      lazy_plt = &elf_i386_nacl_plt;
-      break;
+    default:
+      abort ();
     }
 
   got_addr = 0;
@@ -4347,7 +4420,7 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
 {
   struct elf_x86_init_table init_table;
 
-  switch (get_elf_x86_backend_data (info->output_bfd)->target_os)
+  switch (get_elf_backend_data (info->output_bfd)->target_os)
     {
     case is_normal:
     case is_solaris:
@@ -4364,13 +4437,8 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
       init_table.lazy_ibt_plt = NULL;
       init_table.non_lazy_ibt_plt = NULL;
       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;
-      init_table.non_lazy_ibt_plt = NULL;
-      break;
+    default:
+      abort ();
     }
 
   init_table.r_info = elf32_r_info;
@@ -4394,7 +4462,6 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
 #define elf_backend_got_header_size    12
 #define elf_backend_plt_alignment      4
 #define elf_backend_dtrel_excludes_plt 1
-#define elf_backend_extern_protected_data 1
 #define elf_backend_caches_rawsize     1
 #define elf_backend_want_dynrelro      1
 
@@ -4408,7 +4475,7 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
 #define bfd_elf32_get_synthetic_symtab       elf_i386_get_synthetic_symtab
 
 #define elf_backend_relocs_compatible        _bfd_elf_relocs_compatible
-#define elf_backend_check_relocs             elf_i386_check_relocs
+#define elf_backend_always_size_sections      elf_i386_always_size_sections
 #define elf_backend_create_dynamic_sections   _bfd_elf_create_dynamic_sections
 #define elf_backend_fake_sections            elf_i386_fake_sections
 #define elf_backend_finish_dynamic_sections   elf_i386_finish_dynamic_sections
@@ -4421,7 +4488,9 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info)
 #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 elf_backend_linux_prpsinfo32_ugid16    true
+
+#define        elf32_bed                             elf32_i386_bed
 
 #include "elf32-target.h"
 
@@ -4438,10 +4507,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 bool
+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
   {
@@ -4450,10 +4520,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
 
@@ -4461,6 +4532,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
@@ -4468,15 +4541,8 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
 #undef TARGET_LITTLE_NAME
 #define        TARGET_LITTLE_NAME              "elf32-i386-sol2"
 
-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
-
-#undef elf_backend_post_process_headers
+#undef ELF_TARGET_OS
+#define        ELF_TARGET_OS                   is_solaris
 
 /* Restore default: we cannot use ELFOSABI_SOLARIS, otherwise ELFOSABI_NONE
    objects won't be recognized.  */
@@ -4505,7 +4571,7 @@ static const struct elf_x86_backend_data elf_i386_solaris_arch_bed =
    FALSE otherwise.  ISECTION is the best guess matching section from the
    input bfd IBFD, but it might be NULL.  */
 
-static bfd_boolean
+static bool
 elf32_i386_copy_solaris_special_section_fields (const bfd *ibfd ATTRIBUTE_UNUSED,
                                                bfd *obfd ATTRIBUTE_UNUSED,
                                                const Elf_Internal_Shdr *isection ATTRIBUTE_UNUSED,
@@ -4513,7 +4579,7 @@ elf32_i386_copy_solaris_special_section_fields (const bfd *ibfd ATTRIBUTE_UNUSED
 {
   /* PR 19938: FIXME: Need to add code for setting the sh_info
      and sh_link fields of Solaris specific section types.  */
-  return FALSE;
+  return false;
 
   /* Based upon Oracle Solaris 11.3 Linkers and Libraries Guide, Ch. 13,
      Object File Format, Table 13-9  ELF sh_link and sh_info Interpretation:
@@ -4584,12 +4650,12 @@ SHT_SUNW_versym      The section header index of    0
 
 /* Intel MCU support.  */
 
-static bfd_boolean
+static bool
 elf32_iamcu_elf_object_p (bfd *abfd)
 {
   /* Set the right machine number for an IAMCU elf32 file.  */
   bfd_default_set_arch_mach (abfd, bfd_arch_iamcu, bfd_mach_i386_iamcu);
-  return TRUE;
+  return true;
 }
 
 #undef  TARGET_LITTLE_SYM
@@ -4602,9 +4668,7 @@ 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_TARGET_OS
 #undef ELF_OSABI
 
 #undef  elf32_bed
@@ -4628,196 +4692,7 @@ elf32_iamcu_elf_object_p (bfd *abfd)
 #define ELF_ARCH                       bfd_arch_i386
 #undef ELF_MACHINE_CODE
 #define ELF_MACHINE_CODE               EM_386
-
-/* Native Client support.  */
-
-#undef TARGET_LITTLE_SYM
-#define        TARGET_LITTLE_SYM               i386_elf32_nacl_vec
-#undef TARGET_LITTLE_NAME
-#define        TARGET_LITTLE_NAME              "elf32-i386-nacl"
-#undef elf32_bed
-#define        elf32_bed                       elf32_i386_nacl_bed
-
-#undef ELF_MAXPAGESIZE
-#define        ELF_MAXPAGESIZE                 0x10000
-
-/* Restore defaults.  */
-#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.  */
-
-#undef elf_backend_plt_alignment
-#define elf_backend_plt_alignment      5
-#define NACL_PLT_ENTRY_SIZE            64
-#define        NACLMASK                        0xe0 /* 32-byte alignment mask.  */
-
-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.  */
-    0x83, 0xe1, NACLMASK,        /* andl $NACLMASK, %ecx */
-    0xff, 0xe1                   /* jmp *%ecx */
-  };
-
-static const bfd_byte elf_i386_nacl_plt_entry[NACL_PLT_ENTRY_SIZE] =
-  {
-    0x8b, 0x0d,                                /* movl contents of address, %ecx */
-    0, 0, 0, 0,                                /* replaced with GOT slot address.  */
-    0x83, 0xe1, NACLMASK,              /* andl $NACLMASK, %ecx */
-    0xff, 0xe1,                                /* jmp *%ecx */
-
-    /* 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 reloc offset.  */
-    0xe9,                             /* jmp relative */
-    0, 0, 0, 0,                               /* replaced with offset to .plt.  */
-
-    /* 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
-  };
-
-static const bfd_byte
-elf_i386_nacl_pic_plt0_entry[sizeof (elf_i386_nacl_plt0_entry)] =
-  {
-    0xff, 0x73, 0x04,          /* pushl 4(%ebx) */
-    0x8b, 0x4b, 0x08,          /* mov 0x8(%ebx), %ecx */
-    0x83, 0xe1, 0xe0,          /* and $NACLMASK, %ecx */
-    0xff, 0xe1,                        /* jmp *%ecx */
-
-    /* This is expected to be the same size as elf_i386_nacl_plt0_entry,
-       so pad to that size with nop instructions.  */
-    0x90, 0x90, 0x90, 0x90, 0x90, 0x90
-  };
-
-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 */
-
-    /* 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.  */
-
-    /* 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
-  };
-
-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 \
-     || PLT_FDE_LEN_OFFSET != 4 + PLT_CIE_LENGTH + 12)
-# 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 */
-    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_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 */
-    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
-  };
-
-static const struct elf_x86_lazy_plt_layout elf_i386_nacl_plt =
-  {
-    elf_i386_nacl_plt0_entry,          /* plt0_entry */
-    sizeof (elf_i386_nacl_plt0_entry), /* plt0_entry_size */
-    elf_i386_nacl_plt_entry,           /* plt_entry */
-    NACL_PLT_ENTRY_SIZE,               /* plt_entry_size */
-    2,                                 /* plt0_got1_offset */
-    8,                                 /* plt0_got2_offset */
-    0,                                 /* plt0_got2_insn_end */
-    2,                                 /* plt_got_offset */
-    33,                                        /* plt_reloc_offset */
-    38,                                        /* plt_plt_offset */
-    0,                                 /* plt_got_insn_size */
-    0,                                 /* plt_plt_insn_end */
-    32,                                        /* plt_lazy_offset */
-    elf_i386_nacl_pic_plt0_entry,      /* pic_plt0_entry */
-    elf_i386_nacl_pic_plt_entry,       /* pic_plt_entry */
-    elf_i386_nacl_eh_frame_plt,                /* eh_frame_plt */
-    sizeof (elf_i386_nacl_eh_frame_plt) /* eh_frame_plt_size */
-  };
-
-static const struct elf_x86_backend_data elf_i386_nacl_arch_bed =
-  {
-    is_nacl                            /* os */
-  };
-
-static bfd_boolean
-elf32_i386_nacl_elf_object_p (bfd *abfd)
-{
-  /* Set the right machine number for a NaCl i386 ELF32 file.  */
-  bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i386_nacl);
-  return TRUE;
-}
-
-#undef elf_backend_arch_data
-#define elf_backend_arch_data  &elf_i386_nacl_arch_bed
-
-#undef elf_backend_object_p
-#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_final_write_processing
-#define elf_backend_final_write_processing     nacl_final_write_processing
-
-#include "elf32-target.h"
-
-/* Restore defaults.  */
 #undef elf_backend_object_p
-#undef elf_backend_modify_segment_map
-#undef elf_backend_modify_program_headers
-#undef elf_backend_final_write_processing
 
 /* VxWorks support.  */
 
@@ -4831,13 +4706,8 @@ elf32_i386_nacl_elf_object_p (bfd *abfd)
 #undef elf_backend_plt_alignment
 #define elf_backend_plt_alignment      4
 
-static const struct elf_x86_backend_data elf_i386_vxworks_arch_bed =
-  {
-    is_vxworks                         /* os */
-  };
-
-#undef elf_backend_arch_data
-#define        elf_backend_arch_data   &elf_i386_vxworks_arch_bed
+#undef ELF_TARGET_OS
+#define ELF_TARGET_OS          is_vxworks
 
 #undef elf_backend_relocs_compatible
 #undef elf_backend_add_symbol_hook