AArch64: Add gdbserver MTE support
[deliverable/binutils-gdb.git] / bfd / elf32-arm.c
index dbfd838fbe09eaceb905fcaa6b7416fc5c83cbad..bf0be0c881e538a3e7c6a9bd1cba89b60cb10775 100644 (file)
@@ -1,5 +1,5 @@
 /* 32-bit ELF support for ARM
-   Copyright (C) 1998-2018 Free Software Foundation, Inc.
+   Copyright (C) 1998-2021 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
 #include <limits.h>
 
 #include "bfd.h"
-#include "bfd_stdint.h"
 #include "libiberty.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf-nacl.h"
 #include "elf-vxworks.h"
 #include "elf/arm.h"
+#include "elf32-arm.h"
+#include "cpu-arm.h"
 
 /* Return the relocation section associated with NAME.  HTAB is the
    bfd's elf32_arm_link_hash_entry.  */
@@ -1390,7 +1391,7 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
         0,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
-        complain_overflow_bitfield,/* complain_on_overflow */
+        complain_overflow_dont,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_ARM_TLS_DESCSEQ",   /* name */
         FALSE,                 /* partial_inplace */
@@ -1682,7 +1683,7 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
         0,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
-        complain_overflow_bitfield,/* complain_on_overflow */
+        complain_overflow_dont,/* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_ARM_THM_TLS_DESCSEQ",/* name */
         FALSE,                 /* partial_inplace */
@@ -1743,6 +1744,46 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
         0x00000000,            /* src_mask.  */
         0x00000000,            /* dst_mask.  */
         FALSE),                /* pcrel_offset.  */
+  /* Relocations for Armv8.1-M Mainline.  */
+  HOWTO (R_ARM_THM_BF16,       /* type.  */
+        0,                     /* rightshift.  */
+        1,                     /* size (0 = byte, 1 = short, 2 = long).  */
+        16,                    /* bitsize.  */
+        TRUE,                  /* pc_relative.  */
+        0,                     /* bitpos.  */
+        complain_overflow_dont,/* do not complain_on_overflow.  */
+        bfd_elf_generic_reloc, /* special_function.  */
+        "R_ARM_THM_BF16",      /* name.  */
+        FALSE,                 /* partial_inplace.  */
+        0x001f0ffe,            /* src_mask.  */
+        0x001f0ffe,            /* dst_mask.  */
+        TRUE),                 /* pcrel_offset.  */
+  HOWTO (R_ARM_THM_BF12,       /* type.  */
+        0,                     /* rightshift.  */
+        1,                     /* size (0 = byte, 1 = short, 2 = long).  */
+        12,                    /* bitsize.  */
+        TRUE,                  /* pc_relative.  */
+        0,                     /* bitpos.  */
+        complain_overflow_dont,/* do not complain_on_overflow.  */
+        bfd_elf_generic_reloc, /* special_function.  */
+        "R_ARM_THM_BF12",      /* name.  */
+        FALSE,                 /* partial_inplace.  */
+        0x00010ffe,            /* src_mask.  */
+        0x00010ffe,            /* dst_mask.  */
+        TRUE),                 /* pcrel_offset.  */
+  HOWTO (R_ARM_THM_BF18,       /* type.  */
+        0,                     /* rightshift.  */
+        1,                     /* size (0 = byte, 1 = short, 2 = long).  */
+        18,                    /* bitsize.  */
+        TRUE,                  /* pc_relative.  */
+        0,                     /* bitpos.  */
+        complain_overflow_dont,/* do not complain_on_overflow.  */
+        bfd_elf_generic_reloc, /* special_function.  */
+        "R_ARM_THM_BF18",      /* name.  */
+        FALSE,                 /* partial_inplace.  */
+        0x007f0ffe,            /* src_mask.  */
+        0x007f0ffe,            /* dst_mask.  */
+        TRUE),                 /* pcrel_offset.  */
 };
 
 /* 160 onwards: */
@@ -2054,7 +2095,10 @@ static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
     {BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC, R_ARM_THM_ALU_ABS_G3_NC},
     {BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC, R_ARM_THM_ALU_ABS_G2_NC},
     {BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC, R_ARM_THM_ALU_ABS_G1_NC},
-    {BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC, R_ARM_THM_ALU_ABS_G0_NC}
+    {BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC, R_ARM_THM_ALU_ABS_G0_NC},
+    {BFD_RELOC_ARM_THUMB_BF17, R_ARM_THM_BF16},
+    {BFD_RELOC_ARM_THUMB_BF13, R_ARM_THM_BF12},
+    {BFD_RELOC_ARM_THUMB_BF19, R_ARM_THM_BF18}
   };
 
 static reloc_howto_type *
@@ -2174,7 +2218,18 @@ elf32_arm_nabi_write_core_note (bfd *abfd, char *buf, int *bufsiz,
        va_start (ap, note_type);
        memset (data, 0, sizeof (data));
        strncpy (data + 28, va_arg (ap, const char *), 16);
+#if GCC_VERSION == 8000 || GCC_VERSION == 8001
+       DIAGNOSTIC_PUSH;
+       /* GCC 8.0 and 8.1 warn about 80 equals destination size with
+          -Wstringop-truncation:
+          https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85643
+        */
+       DIAGNOSTIC_IGNORE_STRINGOP_TRUNCATION;
+#endif
        strncpy (data + 44, va_arg (ap, const char *), 80);
+#if GCC_VERSION == 8000 || GCC_VERSION == 8001
+       DIAGNOSTIC_POP;
+#endif
        va_end (ap);
 
        return elfcore_write_note (abfd, buf, bufsiz,
@@ -2247,6 +2302,8 @@ typedef unsigned short int insn16;
 
 #define CMSE_PREFIX "__acle_se_"
 
+#define CMSE_STUB_NAME ".gnu.sgstubs"
+
 /* The name of the dynamic interpreter.  This is put in the .interp
    section.  */
 #define ELF_DYNAMIC_INTERPRETER     "/usr/lib/ld.so.1"
@@ -2274,6 +2331,11 @@ static const unsigned long dl_tlsdesc_lazy_trampoline [] =
   0x00000018, /* 4:   .word  _GLOBAL_OFFSET_TABLE_ - 2b - 8 */
 };
 
+/* NOTE: [Thumb nop sequence]
+   When adding code that transitions from Thumb to Arm the instruction that
+   should be used for the alignment padding should be 0xe7fd (b .-2) instead of
+   a nop for performance reasons.  */
+
 /* ARM FDPIC PLT entry.  */
 /* The last 5 words contain PLT lazy fragment code and data.  */
 static const bfd_vma elf32_arm_fdpic_plt_entry [] =
@@ -2391,8 +2453,8 @@ static const bfd_vma elf32_thumb2_plt_entry [] =
   0x0c00f240,          /* movw    ip, #0xNNNN    */
   0x0c00f2c0,          /* movt    ip, #0xNNNN    */
   0xf8dc44fc,          /* add     ip, pc         */
-  0xbf00f000           /* ldr.w   pc, [ip]       */
-                       /* nop                    */
+  0xe7fcf000           /* ldr.w   pc, [ip]       */
+                       /* b      .-4             */
 };
 
 /* The format of the first entry in the procedure linkage table
@@ -2432,15 +2494,7 @@ static const bfd_vma elf32_arm_vxworks_shared_plt_entry[] =
 static const bfd_vma elf32_arm_plt_thumb_stub [] =
 {
   0x4778,              /* bx pc */
-  0x46c0               /* nop   */
-};
-
-/* The entries in a PLT when using a DLL-based target with multiple
-   address spaces.  */
-static const bfd_vma elf32_arm_symbian_plt_entry [] =
-{
-  0xe51ff004,        /* ldr   pc, [pc, #-4] */
-  0x00000000,        /* dcd   R_ARM_GLOB_DAT(X) */
+  0xe7fd               /* b .-2 */
 };
 
 /* The first entry in a procedure linkage table looks like
@@ -2519,6 +2573,8 @@ typedef struct
   int                 reloc_addend;
 }  insn_sequence;
 
+/* See note [Thumb nop sequence] when adding a veneer.  */
+
 /* Arm/Thumb -> Arm/Thumb long branch stub. On V5T and above, use blx
    to reach the stub if necessary.  */
 static const insn_sequence elf32_arm_stub_long_branch_any_any[] =
@@ -2569,7 +2625,7 @@ static const insn_sequence elf32_arm_stub_long_branch_thumb2_only_pure[] =
 static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb[] =
 {
   THUMB16_INSN (0x4778),            /* bx   pc */
-  THUMB16_INSN (0x46c0),            /* nop */
+  THUMB16_INSN (0xe7fd),            /* b   .-2 */
   ARM_INSN (0xe59fc000),            /* ldr  ip, [pc, #0] */
   ARM_INSN (0xe12fff1c),            /* bx   ip */
   DATA_WORD (0, R_ARM_ABS32, 0),     /* dcd  R_ARM_ABS32(X) */
@@ -2580,7 +2636,7 @@ static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb[] =
 static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm[] =
 {
   THUMB16_INSN (0x4778),            /* bx   pc */
-  THUMB16_INSN (0x46c0),            /* nop   */
+  THUMB16_INSN (0xe7fd),            /* b   .-2 */
   ARM_INSN (0xe51ff004),            /* ldr   pc, [pc, #-4] */
   DATA_WORD (0, R_ARM_ABS32, 0),     /* dcd   R_ARM_ABS32(X) */
 };
@@ -2590,7 +2646,7 @@ static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm[] =
 static const insn_sequence elf32_arm_stub_short_branch_v4t_thumb_arm[] =
 {
   THUMB16_INSN (0x4778),            /* bx   pc */
-  THUMB16_INSN (0x46c0),            /* nop   */
+  THUMB16_INSN (0xe7fd),            /* b   .-2 */
   ARM_REL_INSN (0xea000000, -8),     /* b    (X-8) */
 };
 
@@ -2628,7 +2684,7 @@ static const insn_sequence elf32_arm_stub_long_branch_v4t_arm_thumb_pic[] =
 static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm_pic[] =
 {
   THUMB16_INSN (0x4778),            /* bx   pc */
-  THUMB16_INSN (0x46c0),            /* nop  */
+  THUMB16_INSN (0xe7fd),            /* b   .-2 */
   ARM_INSN (0xe59fc000),            /* ldr  ip, [pc, #0] */
   ARM_INSN (0xe08cf00f),            /* add  pc, ip, pc */
   DATA_WORD (0, R_ARM_REL32, -4),     /* dcd  R_ARM_REL32(X) */
@@ -2652,7 +2708,7 @@ static const insn_sequence elf32_arm_stub_long_branch_thumb_only_pic[] =
 static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb_pic[] =
 {
   THUMB16_INSN (0x4778),            /* bx   pc */
-  THUMB16_INSN (0x46c0),            /* nop */
+  THUMB16_INSN (0xe7fd),            /* b   .-2 */
   ARM_INSN (0xe59fc004),            /* ldr  ip, [pc, #4] */
   ARM_INSN (0xe08fc00c),            /* add   ip, pc, ip */
   ARM_INSN (0xe12fff1c),            /* bx   ip */
@@ -2673,7 +2729,7 @@ static const insn_sequence elf32_arm_stub_long_branch_any_tls_pic[] =
 static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_tls_pic[] =
 {
   THUMB16_INSN (0x4778),            /* bx   pc */
-  THUMB16_INSN (0x46c0),            /* nop */
+  THUMB16_INSN (0xe7fd),            /* b   .-2 */
   ARM_INSN (0xe59f1000),            /* ldr  r1, [pc, #0] */
   ARM_INSN (0xe081f00f),            /* add  pc, r1, pc */
   DATA_WORD (0, R_ARM_REL32, -4),    /* dcd  R_ARM_REL32(X) */
@@ -3151,9 +3207,6 @@ struct elf32_arm_link_hash_entry
 {
   struct elf_link_hash_entry root;
 
-  /* Track dynamic relocs copied for this symbol.  */
-  struct elf_dyn_relocs *dyn_relocs;
-
   /* ARM-specific PLT information.  */
   struct arm_plt_info plt;
 
@@ -3194,9 +3247,10 @@ struct elf32_arm_link_hash_entry
     (info)))
 
 /* Get the ARM elf linker hash table from a link_info structure.  */
-#define elf32_arm_hash_table(info) \
-  (elf_hash_table_id ((struct elf_link_hash_table *) ((info)->hash)) \
-  == ARM_ELF_DATA ? ((struct elf32_arm_link_hash_table *) ((info)->hash)) : NULL)
+#define elf32_arm_hash_table(p) \
+  ((is_elf_hash_table ((p)->hash)                                      \
+    && elf_hash_table_id (elf_hash_table (p)) == ARM_ELF_DATA)         \
+   ? (struct elf32_arm_link_hash_table *) (p)->hash : NULL)
 
 #define arm_stub_hash_lookup(table, string, create, copy) \
   ((struct elf32_arm_stub_hash_entry *) \
@@ -3299,15 +3353,6 @@ struct elf32_arm_link_hash_table
   /* The number of bytes in the subsequent PLT etries.  */
   bfd_size_type plt_entry_size;
 
-  /* True if the target system is VxWorks.  */
-  int vxworks_p;
-
-  /* True if the target system is Symbian OS.  */
-  int symbian_p;
-
-  /* True if the target system is Native Client.  */
-  int nacl_p;
-
   /* True if the target uses REL relocations.  */
   bfd_boolean use_rel;
 
@@ -3328,16 +3373,6 @@ struct elf32_arm_link_hash_table
   /* The (unloaded but important) VxWorks .rela.plt.unloaded section.  */
   asection *srelplt2;
 
-  /* The offset into splt of the PLT entry for the TLS descriptor
-     resolver.  Special values are 0, if not necessary (or not found
-     to be necessary yet), and -1 if needed but not determined
-     yet.  */
-  bfd_vma dt_tlsdesc_plt;
-
-  /* The offset into sgot of the GOT entry used by the PLT entry
-     above.  */
-  bfd_vma dt_tlsdesc_got;
-
   /* Offset in .plt section of tls_arm_trampoline.  */
   bfd_vma tls_trampoline;
 
@@ -3348,9 +3383,6 @@ struct elf32_arm_link_hash_table
     bfd_vma offset;
   } tls_ldm_got;
 
-  /* Small local sym cache.  */
-  struct sym_cache sym_cache;
-
   /* For convenience in allocate_dynrelocs.  */
   bfd * obfd;
 
@@ -3518,7 +3550,6 @@ elf32_arm_link_hash_newfunc (struct bfd_hash_entry * entry,
                                     table, string));
   if (ret != NULL)
     {
-      ret->dyn_relocs = NULL;
       ret->tls_type = GOT_UNKNOWN;
       ret->tlsdesc_got = (bfd_vma) -1;
       ret->plt.thumb_refcount = 0;
@@ -3554,27 +3585,40 @@ elf32_arm_allocate_local_sym_info (bfd *abfd)
 
       num_syms = elf_tdata (abfd)->symtab_hdr.sh_info;
       size = num_syms * (sizeof (bfd_signed_vma)
-                        + sizeof (struct arm_local_iplt_info *)
                         + sizeof (bfd_vma)
-                        + sizeof (char)
-                        + sizeof (struct fdpic_local));
+                        + sizeof (struct arm_local_iplt_info *)
+                        + sizeof (struct fdpic_local)
+                        + sizeof (char));
       data = bfd_zalloc (abfd, size);
       if (data == NULL)
        return FALSE;
 
-      elf32_arm_local_fdpic_cnts (abfd) = (struct fdpic_local *) data;
-      data += num_syms * sizeof (struct fdpic_local);
-
+      /* It is important that these all be allocated in descending
+        order of required alignment, so that arrays allocated later
+        will be sufficiently aligned.  */
       elf_local_got_refcounts (abfd) = (bfd_signed_vma *) data;
       data += num_syms * sizeof (bfd_signed_vma);
 
+      elf32_arm_local_tlsdesc_gotent (abfd) = (bfd_vma *) data;
+      data += num_syms * sizeof (bfd_vma);
+
       elf32_arm_local_iplt (abfd) = (struct arm_local_iplt_info **) data;
       data += num_syms * sizeof (struct arm_local_iplt_info *);
 
-      elf32_arm_local_tlsdesc_gotent (abfd) = (bfd_vma *) data;
-      data += num_syms * sizeof (bfd_vma);
+      elf32_arm_local_fdpic_cnts (abfd) = (struct fdpic_local *) data;
+      data += num_syms * sizeof (struct fdpic_local);
 
       elf32_arm_local_got_tls_type (abfd) = data;
+#if GCC_VERSION >= 3000
+      BFD_ASSERT (__alignof__ (*elf32_arm_local_tlsdesc_gotent (abfd))
+                 <= __alignof__ (*elf_local_got_refcounts (abfd)));
+      BFD_ASSERT (__alignof__ (*elf32_arm_local_iplt (abfd))
+                 <= __alignof__ (*elf32_arm_local_tlsdesc_gotent (abfd)));
+      BFD_ASSERT (__alignof__ (*elf32_arm_local_fdpic_cnts (abfd))
+                 <= __alignof__ (*elf32_arm_local_iplt (abfd)));
+      BFD_ASSERT (__alignof__ (*elf32_arm_local_got_tls_type (abfd))
+                 <= __alignof__ (*elf32_arm_local_fdpic_cnts (abfd)));
+#endif
     }
   return TRUE;
 }
@@ -3742,10 +3786,6 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info)
   if (htab == NULL)
     return FALSE;
 
-  /* BPABI objects never have a GOT, or associated sections.  */
-  if (htab->symbian_p)
-    return TRUE;
-
   if (! _bfd_elf_create_got_section (dynobj, info))
     return FALSE;
 
@@ -3755,7 +3795,8 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info)
       htab->srofixup = bfd_make_section_with_flags (dynobj, ".rofixup",
                                                    (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
                                                     | SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_READONLY));
-      if (htab->srofixup == NULL || ! bfd_set_section_alignment (dynobj, htab->srofixup, 2))
+      if (htab->srofixup == NULL
+         || !bfd_set_section_alignment (htab->srofixup, 2))
        return FALSE;
     }
 
@@ -3783,7 +3824,7 @@ create_ifunc_sections (struct bfd_link_info *info)
       s = bfd_make_section_anyway_with_flags (dynobj, ".iplt",
                                              flags | SEC_READONLY | SEC_CODE);
       if (s == NULL
-         || !bfd_set_section_alignment (dynobj, s, bed->plt_alignment))
+         || !bfd_set_section_alignment (s, bed->plt_alignment))
        return FALSE;
       htab->root.iplt = s;
     }
@@ -3794,7 +3835,7 @@ create_ifunc_sections (struct bfd_link_info *info)
                                              RELOC_SECTION (htab, ".iplt"),
                                              flags | SEC_READONLY);
       if (s == NULL
-         || !bfd_set_section_alignment (dynobj, s, bed->s->log_file_align))
+         || !bfd_set_section_alignment (s, bed->s->log_file_align))
        return FALSE;
       htab->root.irelplt = s;
     }
@@ -3803,7 +3844,7 @@ create_ifunc_sections (struct bfd_link_info *info)
     {
       s = bfd_make_section_anyway_with_flags (dynobj, ".igot.plt", flags);
       if (s == NULL
-         || !bfd_set_section_alignment (dynobj, s, bed->s->log_file_align))
+         || !bfd_set_section_alignment (s, bed->s->log_file_align))
        return FALSE;
       htab->root.igotplt = s;
     }
@@ -3825,13 +3866,14 @@ using_thumb_only (struct elf32_arm_link_hash_table *globals)
   arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, Tag_CPU_arch);
 
   /* Force return logic to be reviewed for each new architecture.  */
-  BFD_ASSERT (arch <= TAG_CPU_ARCH_V8M_MAIN);
+  BFD_ASSERT (arch <= TAG_CPU_ARCH_V8_1M_MAIN);
 
   if (arch == TAG_CPU_ARCH_V6_M
       || arch == TAG_CPU_ARCH_V6S_M
       || arch == TAG_CPU_ARCH_V7E_M
       || arch == TAG_CPU_ARCH_V8M_BASE
-      || arch == TAG_CPU_ARCH_V8M_MAIN)
+      || arch == TAG_CPU_ARCH_V8M_MAIN
+      || arch == TAG_CPU_ARCH_V8_1M_MAIN)
     return TRUE;
 
   return FALSE;
@@ -3852,14 +3894,15 @@ using_thumb2 (struct elf32_arm_link_hash_table *globals)
   arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, Tag_CPU_arch);
 
   /* Force return logic to be reviewed for each new architecture.  */
-  BFD_ASSERT (arch <= TAG_CPU_ARCH_V8M_MAIN);
+  BFD_ASSERT (arch <= TAG_CPU_ARCH_V8_1M_MAIN);
 
   return (arch == TAG_CPU_ARCH_V6T2
          || arch == TAG_CPU_ARCH_V7
          || arch == TAG_CPU_ARCH_V7E_M
          || arch == TAG_CPU_ARCH_V8
          || arch == TAG_CPU_ARCH_V8R
-         || arch == TAG_CPU_ARCH_V8M_MAIN);
+         || arch == TAG_CPU_ARCH_V8M_MAIN
+         || arch == TAG_CPU_ARCH_V8_1M_MAIN);
 }
 
 /* Determine whether Thumb-2 BL instruction is available.  */
@@ -3871,7 +3914,7 @@ using_thumb2_bl (struct elf32_arm_link_hash_table *globals)
     bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, Tag_CPU_arch);
 
   /* Force return logic to be reviewed for each new architecture.  */
-  BFD_ASSERT (arch <= TAG_CPU_ARCH_V8M_MAIN);
+  BFD_ASSERT (arch <= TAG_CPU_ARCH_V8_1M_MAIN);
 
   /* Architecture was introduced after ARMv6T2 (eg. ARMv6-M).  */
   return (arch == TAG_CPU_ARCH_V6T2
@@ -3897,7 +3940,7 @@ elf32_arm_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
   if (!_bfd_elf_create_dynamic_sections (dynobj, info))
     return FALSE;
 
-  if (htab->vxworks_p)
+  if (htab->root.target_os == is_vxworks)
     {
       if (!elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2))
        return FALSE;
@@ -3965,37 +4008,6 @@ elf32_arm_copy_indirect_symbol (struct bfd_link_info *info,
   edir = (struct elf32_arm_link_hash_entry *) dir;
   eind = (struct elf32_arm_link_hash_entry *) ind;
 
-  if (eind->dyn_relocs != NULL)
-    {
-      if (edir->dyn_relocs != NULL)
-       {
-         struct elf_dyn_relocs **pp;
-         struct elf_dyn_relocs *p;
-
-         /* Add reloc counts against the indirect sym to the direct sym
-            list.  Merge any entries against the same section.  */
-         for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
-           {
-             struct elf_dyn_relocs *q;
-
-             for (q = edir->dyn_relocs; q != NULL; q = q->next)
-               if (q->sec == p->sec)
-                 {
-                   q->pc_count += p->pc_count;
-                   q->count += p->count;
-                   *pp = p->next;
-                   break;
-                 }
-             if (q == NULL)
-               pp = &p->next;
-           }
-         *pp = edir->dyn_relocs;
-       }
-
-      edir->dyn_relocs = eind->dyn_relocs;
-      eind->dyn_relocs = NULL;
-    }
-
   if (ind->root.type == bfd_link_hash_indirect)
     {
       /* Copy over PLT info.  */
@@ -4043,7 +4055,7 @@ static struct bfd_link_hash_table *
 elf32_arm_link_hash_table_create (bfd *abfd)
 {
   struct elf32_arm_link_hash_table *ret;
-  bfd_size_type amt = sizeof (struct elf32_arm_link_hash_table);
+  size_t amt = sizeof (struct elf32_arm_link_hash_table);
 
   ret = (struct elf32_arm_link_hash_table *) bfd_zmalloc (amt);
   if (ret == NULL)
@@ -4091,7 +4103,7 @@ arch_has_arm_nop (struct elf32_arm_link_hash_table *globals)
                                             Tag_CPU_arch);
 
   /* Force return logic to be reviewed for each new architecture.  */
-  BFD_ASSERT (arch <= TAG_CPU_ARCH_V8M_MAIN);
+  BFD_ASSERT (arch <= TAG_CPU_ARCH_V8_1M_MAIN);
 
   return (arch == TAG_CPU_ARCH_V6T2
          || arch == TAG_CPU_ARCH_V6K
@@ -4451,11 +4463,11 @@ arm_type_of_stub (struct bfd_link_info *info,
                ? (r_type == R_ARM_TLS_CALL
                   /* TLS PIC Stub.  */
                   ? arm_stub_long_branch_any_tls_pic
-                  : (globals->nacl_p
+                  : (globals->root.target_os == is_nacl
                      ? arm_stub_long_branch_arm_nacl_pic
                      : arm_stub_long_branch_any_arm_pic))
                /* non-PIC stubs.  */
-               : (globals->nacl_p
+               : (globals->root.target_os == is_nacl
                   ? arm_stub_long_branch_arm_nacl
                   : arm_stub_long_branch_any_any);
            }
@@ -4528,6 +4540,27 @@ elf32_arm_get_stub_entry (const asection *input_section,
   if ((input_section->flags & SEC_CODE) == 0)
     return NULL;
 
+  /* If the input section is the CMSE stubs one and it needs a long
+     branch stub to reach it's final destination, give up with an
+     error message: this is not supported.  See PR ld/24709.  */
+  if (!strncmp (input_section->name, CMSE_STUB_NAME, strlen(CMSE_STUB_NAME)))
+    {
+      bfd *output_bfd = htab->obfd;
+      asection *out_sec = bfd_get_section_by_name (output_bfd, CMSE_STUB_NAME);
+
+      _bfd_error_handler (_("ERROR: CMSE stub (%s section) too far "
+                           "(%#" PRIx64 ") from destination (%#" PRIx64 ")"),
+                         CMSE_STUB_NAME,
+                         (uint64_t)out_sec->output_section->vma
+                           + out_sec->output_offset,
+                         (uint64_t)sym_sec->output_section->vma
+                           + sym_sec->output_offset
+                           + h->root.root.u.def.value);
+      /* Exit, rather than leave incompletely processed
+        relocations.  */
+      xexit(1);
+    }
+
   /* If this input section is part of a group of sections sharing one
      stub section, then use the id of the first section in the group.
      Stub names need to include a section id, as there may well be
@@ -4621,7 +4654,7 @@ arm_dedicated_stub_output_section_name (enum elf32_arm_stub_type stub_type)
   switch (stub_type)
     {
     case arm_stub_cmse_branch_thumb_only:
-      return ".gnu.sgstubs";
+      return CMSE_STUB_NAME;
 
     default:
       BFD_ASSERT (!arm_dedicated_stub_output_section_required (stub_type));
@@ -4699,7 +4732,7 @@ elf32_arm_create_or_find_stub_sec (asection **link_sec_p, asection *section,
        stub_sec_p = &htab->stub_group[link_sec->id].stub_sec;
       stub_sec_prefix = link_sec->name;
       out_sec = link_sec->output_section;
-      align = htab->nacl_p ? 4 : 3;
+      align = htab->root.target_os == is_nacl ? 4 : 3;
     }
 
   if (*stub_sec_p == NULL)
@@ -4826,7 +4859,7 @@ elf32_arm_tls_transition (struct bfd_link_info *info, int r_type,
 {
   int is_local = (h == NULL);
 
-  if (bfd_link_pic (info)
+  if (bfd_link_dll (info)
       || (h && h->root.type == bfd_link_hash_undefweak))
     return r_type;
 
@@ -4976,6 +5009,14 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
   stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
   info = (struct bfd_link_info *) in_arg;
 
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    info->callbacks->einfo (_("%F%P: Could not assign '%pA' to an output section. "
+                             "Retry without --enable-non-contiguous-regions.\n"),
+                           stub_entry->target_section);
+
   globals = elf32_arm_hash_table (info);
   if (globals == NULL)
     return FALSE;
@@ -5216,7 +5257,7 @@ elf32_arm_setup_section_lists (bfd *output_bfd,
   unsigned int top_id, top_index;
   asection *section;
   asection **input_list, **list;
-  bfd_size_type amt;
+  size_t amt;
   struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
 
   if (htab == NULL)
@@ -5917,12 +5958,12 @@ cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
       if (i < ext_start)
        {
          cmse_sym = &local_syms[i];
-         /* Not a special symbol.  */
-         if (!ARM_GET_SYM_CMSE_SPCL (cmse_sym->st_target_internal))
-           continue;
          sym_name = bfd_elf_string_from_elf_section (input_bfd,
                                                      symtab_hdr->sh_link,
                                                      cmse_sym->st_name);
+         if (!sym_name || !startswith (sym_name, CMSE_PREFIX))
+           continue;
+
          /* Special symbol with local binding.  */
          cmse_invalid = TRUE;
        }
@@ -5930,9 +5971,7 @@ cmse_scan (bfd *input_bfd, struct elf32_arm_link_hash_table *htab,
        {
          cmse_hash = elf32_arm_hash_entry (sym_hashes[i - ext_start]);
          sym_name = (char *) cmse_hash->root.root.root.string;
-
-         /* Not a special symbol.  */
-         if (!ARM_GET_SYM_CMSE_SPCL (cmse_hash->root.target_internal))
+         if (!startswith (sym_name, CMSE_PREFIX))
            continue;
 
          /* Special symbol has incorrect binding or type.  */
@@ -6169,7 +6208,10 @@ set_cmse_veneer_addr_from_implib (struct bfd_link_info *info,
     return FALSE;
 
   /* Read in the input secure gateway import library's symbol table.  */
-  sympp = (asymbol **) xmalloc (symsize);
+  sympp = (asymbol **) bfd_malloc (symsize);
+  if (sympp == NULL)
+    return FALSE;
+
   symcount = bfd_canonicalize_symtab (in_implib_bfd, sympp);
   if (symcount < 0)
     {
@@ -6326,7 +6368,7 @@ set_cmse_veneer_addr_from_implib (struct bfd_link_info *info,
       ret = FALSE;
     }
 
-free_sym_buf:
+ free_sym_buf:
   free (sympp);
   return ret;
 }
@@ -6440,6 +6482,10 @@ elf32_arm_size_stubs (bfd *output_bfd,
 
          if (!is_arm_elf (input_bfd))
            continue;
+         if ((input_bfd->flags & DYNAMIC) != 0
+             && (elf_sym_hashes (input_bfd) == NULL
+                 || (elf_dyn_lib_class (input_bfd) & DYN_AS_NEEDED) != 0))
+           continue;
 
          num_a8_relocs = 0;
 
@@ -6516,9 +6562,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
                        free (internal_relocs);
                    /* Fall through.  */
                    error_ret_free_local:
-                     if (local_syms != NULL
-                         && (symtab_hdr->contents
-                             != (unsigned char *) local_syms))
+                     if (symtab_hdr->contents != (unsigned char *) local_syms)
                        free (local_syms);
                      return FALSE;
                    }
@@ -7055,7 +7099,6 @@ find_arm_glue (struct bfd_link_info *link_info,
 
   tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen (name)
                                  + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1);
-
   BFD_ASSERT (tmp_name);
 
   sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
@@ -7166,7 +7209,7 @@ arm_allocate_glue_section_space (bfd * abfd, bfd_size_type size, const char * na
   s = bfd_get_linker_section (abfd, name);
   BFD_ASSERT (s != NULL);
 
-  contents = (bfd_byte *) bfd_alloc (abfd, size);
+  contents = (bfd_byte *) bfd_zalloc (abfd, size);
 
   BFD_ASSERT (s->size == size);
   s->contents = contents;
@@ -7230,7 +7273,6 @@ record_arm_to_thumb_glue (struct bfd_link_info * link_info,
 
   tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen (name)
                                  + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1);
-
   BFD_ASSERT (tmp_name);
 
   sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
@@ -7308,7 +7350,6 @@ record_arm_bx_glue (struct bfd_link_info * link_info, int reg)
   /* Add symbol for veneer.  */
   tmp_name = (char *)
       bfd_malloc ((bfd_size_type) strlen (ARM_BX_GLUE_ENTRY_NAME) + 1);
-
   BFD_ASSERT (tmp_name);
 
   sprintf (tmp_name, ARM_BX_GLUE_ENTRY_NAME, reg);
@@ -7400,7 +7441,6 @@ record_vfp11_erratum_veneer (struct bfd_link_info *link_info,
 
   tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen
                                  (VFP11_ERRATUM_VENEER_ENTRY_NAME) + 10);
-
   BFD_ASSERT (tmp_name);
 
   sprintf (tmp_name, VFP11_ERRATUM_VENEER_ENTRY_NAME,
@@ -7520,7 +7560,6 @@ record_stm32l4xx_erratum_veneer (struct bfd_link_info *link_info,
 
   tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen
                                  (STM32L4XX_ERRATUM_VENEER_ENTRY_NAME) + 10);
-
   BFD_ASSERT (tmp_name);
 
   sprintf (tmp_name, STM32L4XX_ERRATUM_VENEER_ENTRY_NAME,
@@ -7625,7 +7664,7 @@ arm_make_glue_section (bfd * abfd, const char * name)
   sec = bfd_make_section_anyway_with_flags (abfd, name, ARM_GLUE_SECTION_FLAGS);
 
   if (sec == NULL
-      || !bfd_set_section_alignment (abfd, sec, 2))
+      || !bfd_set_section_alignment (sec, 2))
     return FALSE;
 
   /* Set the gc mark to prevent the section from being removed by garbage
@@ -7890,25 +7929,21 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd,
            }
        }
 
-      if (contents != NULL
-         && elf_section_data (sec)->this_hdr.contents != contents)
+      if (elf_section_data (sec)->this_hdr.contents != contents)
        free (contents);
       contents = NULL;
 
-      if (internal_relocs != NULL
-         && elf_section_data (sec)->relocs != internal_relocs)
+      if (elf_section_data (sec)->relocs != internal_relocs)
        free (internal_relocs);
       internal_relocs = NULL;
     }
 
   return TRUE;
 
-error_return:
-  if (contents != NULL
-      && elf_section_data (sec)->this_hdr.contents != contents)
+ error_return:
+  if (elf_section_data (sec)->this_hdr.contents != contents)
     free (contents);
-  if (internal_relocs != NULL
-      && elf_section_data (sec)->relocs != internal_relocs)
+  if (elf_section_data (sec)->relocs != internal_relocs)
     free (internal_relocs);
 
   return FALSE;
@@ -8413,14 +8448,14 @@ bfd_elf32_arm_vfp11_erratum_scan (bfd *abfd, struct bfd_link_info *link_info)
            {
              unsigned int next_i = i + 4;
              unsigned int insn = bfd_big_endian (abfd)
-               ? (contents[i] << 24)
-                 | (contents[i + 1] << 16)
-                 | (contents[i + 2] << 8)
-                 | contents[i + 3]
-               : (contents[i + 3] << 24)
-                 | (contents[i + 2] << 16)
-                 | (contents[i + 1] << 8)
-                 | contents[i];
+               ? (((unsigned) contents[i] << 24)
+                  | (contents[i + 1] << 16)
+                  | (contents[i + 2] << 8)
+                  | contents[i + 3])
+               : (((unsigned) contents[i + 3] << 24)
+                  | (contents[i + 2] << 16)
+                  | (contents[i + 1] << 8)
+                  | contents[i]);
              unsigned int writemask = 0;
              enum bfd_arm_vfp11_pipe vpipe;
 
@@ -8511,17 +8546,15 @@ bfd_elf32_arm_vfp11_erratum_scan (bfd *abfd, struct bfd_link_info *link_info)
            }
        }
 
-      if (contents != NULL
-         && elf_section_data (sec)->this_hdr.contents != contents)
+      if (elf_section_data (sec)->this_hdr.contents != contents)
        free (contents);
       contents = NULL;
     }
 
   return TRUE;
 
-error_return:
-  if (contents != NULL
-      && elf_section_data (sec)->this_hdr.contents != contents)
+ error_return:
+  if (elf_section_data (sec)->this_hdr.contents != contents)
     free (contents);
 
   return FALSE;
@@ -8551,6 +8584,7 @@ bfd_elf32_arm_vfp11_fix_veneer_locations (bfd *abfd,
 
   tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen
                                  (VFP11_ERRATUM_VENEER_ENTRY_NAME) + 10);
+  BFD_ASSERT (tmp_name);
 
   for (sec = abfd->sections; sec != NULL; sec = sec->next)
     {
@@ -8638,6 +8672,7 @@ bfd_elf32_arm_stm32l4xx_fix_veneer_locations (bfd *abfd,
 
   tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen
                                  (STM32L4XX_ERRATUM_VENEER_ENTRY_NAME) + 10);
+  BFD_ASSERT (tmp_name);
 
   for (sec = abfd->sections; sec != NULL; sec = sec->next)
     {
@@ -8946,17 +8981,15 @@ bfd_elf32_arm_stm32l4xx_erratum_scan (bfd *abfd,
            }
        }
 
-      if (contents != NULL
-         && elf_section_data (sec)->this_hdr.contents != contents)
+      if (elf_section_data (sec)->this_hdr.contents != contents)
        free (contents);
       contents = NULL;
     }
 
   return TRUE;
 
-error_return:
-  if (contents != NULL
-      && elf_section_data (sec)->this_hdr.contents != contents)
+ error_return:
+  if (elf_section_data (sec)->this_hdr.contents != contents)
     free (contents);
 
   return FALSE;
@@ -9471,7 +9504,7 @@ elf32_arm_allocate_plt_entry (struct bfd_link_info *info,
       sgotplt = htab->root.igotplt;
 
       /* NaCl uses a special first entry in .iplt too.  */
-      if (htab->nacl_p && splt->size == 0)
+      if (htab->root.target_os == is_nacl && splt->size == 0)
        splt->size += htab->plt_header_size;
 
       /* Allocate room for an R_ARM_IRELATIVE relocation in .rel.iplt.  */
@@ -9513,20 +9546,17 @@ elf32_arm_allocate_plt_entry (struct bfd_link_info *info,
   root_plt->offset = splt->size;
   splt->size += htab->plt_entry_size;
 
-  if (!htab->symbian_p)
-    {
-      /* We also need to make an entry in the .got.plt section, which
-        will be placed in the .got section by the linker script.  */
-      if (is_iplt_entry)
-       arm_plt->got_offset = sgotplt->size;
-      else
-       arm_plt->got_offset = sgotplt->size - 8 * htab->num_tls_desc;
-      if (htab->fdpic_p)
-       /* Function descriptor takes 64 bits in GOT.  */
-        sgotplt->size += 8;
-      else
-       sgotplt->size += 4;
-    }
+  /* We also need to make an entry in the .got.plt section, which
+     will be placed in the .got section by the linker script.  */
+  if (is_iplt_entry)
+    arm_plt->got_offset = sgotplt->size;
+  else
+    arm_plt->got_offset = sgotplt->size - 8 * htab->num_tls_desc;
+  if (htab->fdpic_p)
+    /* Function descriptor takes 64 bits in GOT.  */
+    sgotplt->size += 8;
+  else
+    sgotplt->size += 4;
 }
 
 static bfd_vma
@@ -9565,7 +9595,6 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info,
   bfd_byte *loc;
   bfd_vma plt_index;
   Elf_Internal_Rela rel;
-  bfd_vma plt_header_size;
   bfd_vma got_header_size;
 
   htab = elf32_arm_hash_table (info);
@@ -9580,7 +9609,6 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info,
       /* There are no reserved entries in .igot.plt, and no special
         first entry in .iplt.  */
       got_header_size = 0;
-      plt_header_size = 0;
     }
   else
     {
@@ -9589,342 +9617,320 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info,
       srel = htab->root.srelplt;
 
       got_header_size = get_elf_backend_data (output_bfd)->got_header_size;
-      plt_header_size = htab->plt_header_size;
     }
   BFD_ASSERT (splt != NULL && srel != NULL);
 
-  /* Fill in the entry in the procedure linkage table.  */
-  if (htab->symbian_p)
+  bfd_vma got_offset, got_address, plt_address;
+  bfd_vma got_displacement, initial_got_entry;
+  bfd_byte * ptr;
+
+  BFD_ASSERT (sgot != NULL);
+
+  /* Get the offset into the .(i)got.plt table of the entry that
+     corresponds to this function.  */
+  got_offset = (arm_plt->got_offset & -2);
+
+  /* Get the index in the procedure linkage table which
+     corresponds to this symbol.  This is the index of this symbol
+     in all the symbols for which we are making plt entries.
+     After the reserved .got.plt entries, all symbols appear in
+     the same order as in .plt.  */
+  if (htab->fdpic_p)
+    /* Function descriptor takes 8 bytes.  */
+    plt_index = (got_offset - got_header_size) / 8;
+  else
+    plt_index = (got_offset - got_header_size) / 4;
+
+  /* Calculate the address of the GOT entry.  */
+  got_address = (sgot->output_section->vma
+                + sgot->output_offset
+                + got_offset);
+
+  /* ...and the address of the PLT entry.  */
+  plt_address = (splt->output_section->vma
+                + splt->output_offset
+                + root_plt->offset);
+
+  ptr = splt->contents + root_plt->offset;
+  if (htab->root.target_os == is_vxworks && bfd_link_pic (info))
     {
-      BFD_ASSERT (dynindx >= 0);
-      put_arm_insn (htab, output_bfd,
-                   elf32_arm_symbian_plt_entry[0],
-                   splt->contents + root_plt->offset);
-      bfd_put_32 (output_bfd,
-                 elf32_arm_symbian_plt_entry[1],
-                 splt->contents + root_plt->offset + 4);
-
-      /* Fill in the entry in the .rel.plt section.  */
-      rel.r_offset = (splt->output_section->vma
-                     + splt->output_offset
-                     + root_plt->offset + 4);
-      rel.r_info = ELF32_R_INFO (dynindx, R_ARM_GLOB_DAT);
-
-      /* Get the index in the procedure linkage table which
-        corresponds to this symbol.  This is the index of this symbol
-        in all the symbols for which we are making plt entries.  The
-        first entry in the procedure linkage table is reserved.  */
-      plt_index = ((root_plt->offset - plt_header_size)
-                  / htab->plt_entry_size);
+      unsigned int i;
+      bfd_vma val;
+
+      for (i = 0; i != htab->plt_entry_size / 4; i++, ptr += 4)
+       {
+         val = elf32_arm_vxworks_shared_plt_entry[i];
+         if (i == 2)
+           val |= got_address - sgot->output_section->vma;
+         if (i == 5)
+           val |= plt_index * RELOC_SIZE (htab);
+         if (i == 2 || i == 5)
+           bfd_put_32 (output_bfd, val, ptr);
+         else
+           put_arm_insn (htab, output_bfd, val, ptr);
+       }
     }
-  else
+  else if (htab->root.target_os == is_vxworks)
     {
-      bfd_vma got_offset, got_address, plt_address;
-      bfd_vma got_displacement, initial_got_entry;
-      bfd_byte * ptr;
+      unsigned int i;
+      bfd_vma val;
 
-      BFD_ASSERT (sgot != NULL);
+      for (i = 0; i != htab->plt_entry_size / 4; i++, ptr += 4)
+       {
+         val = elf32_arm_vxworks_exec_plt_entry[i];
+         if (i == 2)
+           val |= got_address;
+         if (i == 4)
+           val |= 0xffffff & -((root_plt->offset + i * 4 + 8) >> 2);
+         if (i == 5)
+           val |= plt_index * RELOC_SIZE (htab);
+         if (i == 2 || i == 5)
+           bfd_put_32 (output_bfd, val, ptr);
+         else
+           put_arm_insn (htab, output_bfd, val, ptr);
+       }
 
-      /* Get the offset into the .(i)got.plt table of the entry that
-        corresponds to this function.  */
-      got_offset = (arm_plt->got_offset & -2);
+      loc = (htab->srelplt2->contents
+            + (plt_index * 2 + 1) * RELOC_SIZE (htab));
 
-      /* Get the index in the procedure linkage table which
-        corresponds to this symbol.  This is the index of this symbol
-        in all the symbols for which we are making plt entries.
-        After the reserved .got.plt entries, all symbols appear in
-        the same order as in .plt.  */
-      if (htab->fdpic_p)
-        /* Function descriptor takes 8 bytes.  */
-        plt_index = (got_offset - got_header_size) / 8;
-      else
-        plt_index = (got_offset - got_header_size) / 4;
+      /* Create the .rela.plt.unloaded R_ARM_ABS32 relocation
+        referencing the GOT for this PLT entry.  */
+      rel.r_offset = plt_address + 8;
+      rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_ARM_ABS32);
+      rel.r_addend = got_offset;
+      SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
+      loc += RELOC_SIZE (htab);
+
+      /* Create the R_ARM_ABS32 relocation referencing the
+        beginning of the PLT for this GOT entry.  */
+      rel.r_offset = got_address;
+      rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_ARM_ABS32);
+      rel.r_addend = 0;
+      SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
+    }
+  else if (htab->root.target_os == is_nacl)
+    {
+      /* Calculate the displacement between the PLT slot and the
+        common tail that's part of the special initial PLT slot.  */
+      int32_t tail_displacement
+       = ((splt->output_section->vma + splt->output_offset
+           + ARM_NACL_PLT_TAIL_OFFSET)
+          - (plt_address + htab->plt_entry_size + 4));
+      BFD_ASSERT ((tail_displacement & 3) == 0);
+      tail_displacement >>= 2;
 
-      /* Calculate the address of the GOT entry.  */
-      got_address = (sgot->output_section->vma
-                    + sgot->output_offset
-                    + got_offset);
+      BFD_ASSERT ((tail_displacement & 0xff000000) == 0
+                 || (-tail_displacement & 0xff000000) == 0);
 
-      /* ...and the address of the PLT entry.  */
-      plt_address = (splt->output_section->vma
-                    + splt->output_offset
-                    + root_plt->offset);
+      /* Calculate the displacement between the PLT slot and the entry
+        in the GOT.  The offset accounts for the value produced by
+        adding to pc in the penultimate instruction of the PLT stub.  */
+      got_displacement = (got_address
+                         - (plt_address + htab->plt_entry_size));
+
+      /* NaCl does not support interworking at all.  */
+      BFD_ASSERT (!elf32_arm_plt_needs_thumb_stub_p (info, arm_plt));
+
+      put_arm_insn (htab, output_bfd,
+                   elf32_arm_nacl_plt_entry[0]
+                   | arm_movw_immediate (got_displacement),
+                   ptr + 0);
+      put_arm_insn (htab, output_bfd,
+                   elf32_arm_nacl_plt_entry[1]
+                   | arm_movt_immediate (got_displacement),
+                   ptr + 4);
+      put_arm_insn (htab, output_bfd,
+                   elf32_arm_nacl_plt_entry[2],
+                   ptr + 8);
+      put_arm_insn (htab, output_bfd,
+                   elf32_arm_nacl_plt_entry[3]
+                   | (tail_displacement & 0x00ffffff),
+                   ptr + 12);
+    }
+  else if (htab->fdpic_p)
+    {
+      const bfd_vma *plt_entry = using_thumb_only(htab)
+       ? elf32_arm_fdpic_thumb_plt_entry
+       : elf32_arm_fdpic_plt_entry;
 
-      ptr = splt->contents + root_plt->offset;
-      if (htab->vxworks_p && bfd_link_pic (info))
+      /* Fill-up Thumb stub if needed.  */
+      if (elf32_arm_plt_needs_thumb_stub_p (info, arm_plt))
        {
-         unsigned int i;
-         bfd_vma val;
+         put_thumb_insn (htab, output_bfd,
+                         elf32_arm_plt_thumb_stub[0], ptr - 4);
+         put_thumb_insn (htab, output_bfd,
+                         elf32_arm_plt_thumb_stub[1], ptr - 2);
+       }
+      /* As we are using 32 bit instructions even for the Thumb
+        version, we have to use 'put_arm_insn' instead of
+        'put_thumb_insn'.  */
+      put_arm_insn(htab, output_bfd, plt_entry[0], ptr + 0);
+      put_arm_insn(htab, output_bfd, plt_entry[1], ptr + 4);
+      put_arm_insn(htab, output_bfd, plt_entry[2], ptr + 8);
+      put_arm_insn(htab, output_bfd, plt_entry[3], ptr + 12);
+      bfd_put_32 (output_bfd, got_offset, ptr + 16);
 
-         for (i = 0; i != htab->plt_entry_size / 4; i++, ptr += 4)
-           {
-             val = elf32_arm_vxworks_shared_plt_entry[i];
-             if (i == 2)
-               val |= got_address - sgot->output_section->vma;
-             if (i == 5)
-               val |= plt_index * RELOC_SIZE (htab);
-             if (i == 2 || i == 5)
-               bfd_put_32 (output_bfd, val, ptr);
-             else
-               put_arm_insn (htab, output_bfd, val, ptr);
-           }
+      if (!(info->flags & DF_BIND_NOW))
+       {
+         /* funcdesc_value_reloc_offset.  */
+         bfd_put_32 (output_bfd,
+                     htab->root.srelplt->reloc_count * RELOC_SIZE (htab),
+                     ptr + 20);
+         put_arm_insn(htab, output_bfd, plt_entry[6], ptr + 24);
+         put_arm_insn(htab, output_bfd, plt_entry[7], ptr + 28);
+         put_arm_insn(htab, output_bfd, plt_entry[8], ptr + 32);
+         put_arm_insn(htab, output_bfd, plt_entry[9], ptr + 36);
        }
-      else if (htab->vxworks_p)
+    }
+  else if (using_thumb_only (htab))
+    {
+      /* PR ld/16017: Generate thumb only PLT entries.  */
+      if (!using_thumb2 (htab))
        {
-         unsigned int i;
-         bfd_vma val;
-
-         for (i = 0; i != htab->plt_entry_size / 4; i++, ptr += 4)
-           {
-             val = elf32_arm_vxworks_exec_plt_entry[i];
-             if (i == 2)
-               val |= got_address;
-             if (i == 4)
-               val |= 0xffffff & -((root_plt->offset + i * 4 + 8) >> 2);
-             if (i == 5)
-               val |= plt_index * RELOC_SIZE (htab);
-             if (i == 2 || i == 5)
-               bfd_put_32 (output_bfd, val, ptr);
-             else
-               put_arm_insn (htab, output_bfd, val, ptr);
-           }
+         /* FIXME: We ought to be able to generate thumb-1 PLT
+            instructions...  */
+         _bfd_error_handler (_("%pB: warning: thumb-1 mode PLT generation not currently supported"),
+                             output_bfd);
+         return FALSE;
+       }
 
-         loc = (htab->srelplt2->contents
-                + (plt_index * 2 + 1) * RELOC_SIZE (htab));
+      /* Calculate the displacement between the PLT slot and the entry in
+        the GOT.  The 12-byte offset accounts for the value produced by
+        adding to pc in the 3rd instruction of the PLT stub.  */
+      got_displacement = got_address - (plt_address + 12);
 
-         /* Create the .rela.plt.unloaded R_ARM_ABS32 relocation
-            referencing the GOT for this PLT entry.  */
-         rel.r_offset = plt_address + 8;
-         rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_ARM_ABS32);
-         rel.r_addend = got_offset;
-         SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
-         loc += RELOC_SIZE (htab);
+      /* As we are using 32 bit instructions we have to use 'put_arm_insn'
+        instead of 'put_thumb_insn'.  */
+      put_arm_insn (htab, output_bfd,
+                   elf32_thumb2_plt_entry[0]
+                   | ((got_displacement & 0x000000ff) << 16)
+                   | ((got_displacement & 0x00000700) << 20)
+                   | ((got_displacement & 0x00000800) >>  1)
+                   | ((got_displacement & 0x0000f000) >> 12),
+                   ptr + 0);
+      put_arm_insn (htab, output_bfd,
+                   elf32_thumb2_plt_entry[1]
+                   | ((got_displacement & 0x00ff0000)      )
+                   | ((got_displacement & 0x07000000) <<  4)
+                   | ((got_displacement & 0x08000000) >> 17)
+                   | ((got_displacement & 0xf0000000) >> 28),
+                   ptr + 4);
+      put_arm_insn (htab, output_bfd,
+                   elf32_thumb2_plt_entry[2],
+                   ptr + 8);
+      put_arm_insn (htab, output_bfd,
+                   elf32_thumb2_plt_entry[3],
+                   ptr + 12);
+    }
+  else
+    {
+      /* Calculate the displacement between the PLT slot and the
+        entry in the GOT.  The eight-byte offset accounts for the
+        value produced by adding to pc in the first instruction
+        of the PLT stub.  */
+      got_displacement = got_address - (plt_address + 8);
 
-         /* Create the R_ARM_ABS32 relocation referencing the
-            beginning of the PLT for this GOT entry.  */
-         rel.r_offset = got_address;
-         rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_ARM_ABS32);
-         rel.r_addend = 0;
-         SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
+      if (elf32_arm_plt_needs_thumb_stub_p (info, arm_plt))
+       {
+         put_thumb_insn (htab, output_bfd,
+                         elf32_arm_plt_thumb_stub[0], ptr - 4);
+         put_thumb_insn (htab, output_bfd,
+                         elf32_arm_plt_thumb_stub[1], ptr - 2);
        }
-      else if (htab->nacl_p)
+
+      if (!elf32_arm_use_long_plt_entry)
        {
-         /* Calculate the displacement between the PLT slot and the
-            common tail that's part of the special initial PLT slot.  */
-         int32_t tail_displacement
-           = ((splt->output_section->vma + splt->output_offset
-               + ARM_NACL_PLT_TAIL_OFFSET)
-              - (plt_address + htab->plt_entry_size + 4));
-         BFD_ASSERT ((tail_displacement & 3) == 0);
-         tail_displacement >>= 2;
-
-         BFD_ASSERT ((tail_displacement & 0xff000000) == 0
-                     || (-tail_displacement & 0xff000000) == 0);
-
-         /* Calculate the displacement between the PLT slot and the entry
-            in the GOT.  The offset accounts for the value produced by
-            adding to pc in the penultimate instruction of the PLT stub.  */
-         got_displacement = (got_address
-                             - (plt_address + htab->plt_entry_size));
-
-         /* NaCl does not support interworking at all.  */
-         BFD_ASSERT (!elf32_arm_plt_needs_thumb_stub_p (info, arm_plt));
+         BFD_ASSERT ((got_displacement & 0xf0000000) == 0);
 
          put_arm_insn (htab, output_bfd,
-                       elf32_arm_nacl_plt_entry[0]
-                       | arm_movw_immediate (got_displacement),
+                       elf32_arm_plt_entry_short[0]
+                       | ((got_displacement & 0x0ff00000) >> 20),
                        ptr + 0);
          put_arm_insn (htab, output_bfd,
-                       elf32_arm_nacl_plt_entry[1]
-                       | arm_movt_immediate (got_displacement),
-                       ptr + 4);
+                       elf32_arm_plt_entry_short[1]
+                       | ((got_displacement & 0x000ff000) >> 12),
+                       ptr+ 4);
          put_arm_insn (htab, output_bfd,
-                       elf32_arm_nacl_plt_entry[2],
+                       elf32_arm_plt_entry_short[2]
+                       | (got_displacement & 0x00000fff),
                        ptr + 8);
-         put_arm_insn (htab, output_bfd,
-                       elf32_arm_nacl_plt_entry[3]
-                       | (tail_displacement & 0x00ffffff),
-                       ptr + 12);
-       }
-      else if (htab->fdpic_p)
-       {
-         const bfd_vma *plt_entry = using_thumb_only(htab)
-           ? elf32_arm_fdpic_thumb_plt_entry
-           : elf32_arm_fdpic_plt_entry;
-
-         /* Fill-up Thumb stub if needed.  */
-         if (elf32_arm_plt_needs_thumb_stub_p (info, arm_plt))
-           {
-             put_thumb_insn (htab, output_bfd,
-                             elf32_arm_plt_thumb_stub[0], ptr - 4);
-             put_thumb_insn (htab, output_bfd,
-                             elf32_arm_plt_thumb_stub[1], ptr - 2);
-           }
-         /* As we are using 32 bit instructions even for the Thumb
-            version, we have to use 'put_arm_insn' instead of
-            'put_thumb_insn'.  */
-         put_arm_insn(htab, output_bfd, plt_entry[0], ptr + 0);
-         put_arm_insn(htab, output_bfd, plt_entry[1], ptr + 4);
-         put_arm_insn(htab, output_bfd, plt_entry[2], ptr + 8);
-         put_arm_insn(htab, output_bfd, plt_entry[3], ptr + 12);
-         bfd_put_32 (output_bfd, got_offset, ptr + 16);
-
-         if (!(info->flags & DF_BIND_NOW))
-           {
-             /* funcdesc_value_reloc_offset.  */
-             bfd_put_32 (output_bfd,
-                         htab->root.srelplt->reloc_count * RELOC_SIZE (htab),
-                         ptr + 20);
-             put_arm_insn(htab, output_bfd, plt_entry[6], ptr + 24);
-             put_arm_insn(htab, output_bfd, plt_entry[7], ptr + 28);
-             put_arm_insn(htab, output_bfd, plt_entry[8], ptr + 32);
-             put_arm_insn(htab, output_bfd, plt_entry[9], ptr + 36);
-           }
+#ifdef FOUR_WORD_PLT
+         bfd_put_32 (output_bfd, elf32_arm_plt_entry_short[3], ptr + 12);
+#endif
        }
-      else if (using_thumb_only (htab))
+      else
        {
-         /* PR ld/16017: Generate thumb only PLT entries.  */
-         if (!using_thumb2 (htab))
-           {
-             /* FIXME: We ought to be able to generate thumb-1 PLT
-                instructions...  */
-             _bfd_error_handler (_("%pB: warning: thumb-1 mode PLT generation not currently supported"),
-                                 output_bfd);
-             return FALSE;
-           }
-
-         /* Calculate the displacement between the PLT slot and the entry in
-            the GOT.  The 12-byte offset accounts for the value produced by
-            adding to pc in the 3rd instruction of the PLT stub.  */
-         got_displacement = got_address - (plt_address + 12);
-
-         /* As we are using 32 bit instructions we have to use 'put_arm_insn'
-            instead of 'put_thumb_insn'.  */
          put_arm_insn (htab, output_bfd,
-                       elf32_thumb2_plt_entry[0]
-                       | ((got_displacement & 0x000000ff) << 16)
-                       | ((got_displacement & 0x00000700) << 20)
-                       | ((got_displacement & 0x00000800) >>  1)
-                       | ((got_displacement & 0x0000f000) >> 12),
+                       elf32_arm_plt_entry_long[0]
+                       | ((got_displacement & 0xf0000000) >> 28),
                        ptr + 0);
          put_arm_insn (htab, output_bfd,
-                       elf32_thumb2_plt_entry[1]
-                       | ((got_displacement & 0x00ff0000)      )
-                       | ((got_displacement & 0x07000000) <<  4)
-                       | ((got_displacement & 0x08000000) >> 17)
-                       | ((got_displacement & 0xf0000000) >> 28),
+                       elf32_arm_plt_entry_long[1]
+                       | ((got_displacement & 0x0ff00000) >> 20),
                        ptr + 4);
          put_arm_insn (htab, output_bfd,
-                       elf32_thumb2_plt_entry[2],
-                       ptr + 8);
+                       elf32_arm_plt_entry_long[2]
+                       | ((got_displacement & 0x000ff000) >> 12),
+                       ptr+ 8);
          put_arm_insn (htab, output_bfd,
-                       elf32_thumb2_plt_entry[3],
+                       elf32_arm_plt_entry_long[3]
+                       | (got_displacement & 0x00000fff),
                        ptr + 12);
        }
-      else
-       {
-         /* Calculate the displacement between the PLT slot and the
-            entry in the GOT.  The eight-byte offset accounts for the
-            value produced by adding to pc in the first instruction
-            of the PLT stub.  */
-         got_displacement = got_address - (plt_address + 8);
-
-         if (elf32_arm_plt_needs_thumb_stub_p (info, arm_plt))
-           {
-             put_thumb_insn (htab, output_bfd,
-                             elf32_arm_plt_thumb_stub[0], ptr - 4);
-             put_thumb_insn (htab, output_bfd,
-                             elf32_arm_plt_thumb_stub[1], ptr - 2);
-           }
-
-         if (!elf32_arm_use_long_plt_entry)
-           {
-             BFD_ASSERT ((got_displacement & 0xf0000000) == 0);
-
-             put_arm_insn (htab, output_bfd,
-                           elf32_arm_plt_entry_short[0]
-                           | ((got_displacement & 0x0ff00000) >> 20),
-                           ptr + 0);
-             put_arm_insn (htab, output_bfd,
-                           elf32_arm_plt_entry_short[1]
-                           | ((got_displacement & 0x000ff000) >> 12),
-                           ptr+ 4);
-             put_arm_insn (htab, output_bfd,
-                           elf32_arm_plt_entry_short[2]
-                           | (got_displacement & 0x00000fff),
-                           ptr + 8);
-#ifdef FOUR_WORD_PLT
-             bfd_put_32 (output_bfd, elf32_arm_plt_entry_short[3], ptr + 12);
-#endif
-           }
-         else
-           {
-             put_arm_insn (htab, output_bfd,
-                           elf32_arm_plt_entry_long[0]
-                           | ((got_displacement & 0xf0000000) >> 28),
-                           ptr + 0);
-             put_arm_insn (htab, output_bfd,
-                           elf32_arm_plt_entry_long[1]
-                           | ((got_displacement & 0x0ff00000) >> 20),
-                           ptr + 4);
-             put_arm_insn (htab, output_bfd,
-                           elf32_arm_plt_entry_long[2]
-                           | ((got_displacement & 0x000ff000) >> 12),
-                           ptr+ 8);
-             put_arm_insn (htab, output_bfd,
-                           elf32_arm_plt_entry_long[3]
-                           | (got_displacement & 0x00000fff),
-                           ptr + 12);
-           }
-       }
+    }
 
-      /* Fill in the entry in the .rel(a).(i)plt section.  */
-      rel.r_offset = got_address;
-      rel.r_addend = 0;
-      if (dynindx == -1)
+  /* Fill in the entry in the .rel(a).(i)plt section.  */
+  rel.r_offset = got_address;
+  rel.r_addend = 0;
+  if (dynindx == -1)
+    {
+      /* .igot.plt entries use IRELATIVE relocations against SYM_VALUE.
+        The dynamic linker or static executable then calls SYM_VALUE
+        to determine the correct run-time value of the .igot.plt entry.  */
+      rel.r_info = ELF32_R_INFO (0, R_ARM_IRELATIVE);
+      initial_got_entry = sym_value;
+    }
+  else
+    {
+      /* For FDPIC we will have to resolve a R_ARM_FUNCDESC_VALUE
+        used by PLT entry.  */
+      if (htab->fdpic_p)
        {
-         /* .igot.plt entries use IRELATIVE relocations against SYM_VALUE.
-            The dynamic linker or static executable then calls SYM_VALUE
-            to determine the correct run-time value of the .igot.plt entry.  */
-         rel.r_info = ELF32_R_INFO (0, R_ARM_IRELATIVE);
-         initial_got_entry = sym_value;
+         rel.r_info = ELF32_R_INFO (dynindx, R_ARM_FUNCDESC_VALUE);
+         initial_got_entry = 0;
        }
       else
        {
-         /* For FDPIC we will have to resolve a R_ARM_FUNCDESC_VALUE
-            used by PLT entry.  */
-         if (htab->fdpic_p)
-           {
-             rel.r_info = ELF32_R_INFO (dynindx, R_ARM_FUNCDESC_VALUE);
-             initial_got_entry = 0;
-           }
-         else
-           {
-             rel.r_info = ELF32_R_INFO (dynindx, R_ARM_JUMP_SLOT);
-             initial_got_entry = (splt->output_section->vma
-                                  + splt->output_offset);
-           }
+         rel.r_info = ELF32_R_INFO (dynindx, R_ARM_JUMP_SLOT);
+         initial_got_entry = (splt->output_section->vma
+                              + splt->output_offset);
+
+         /* PR ld/16017
+            When thumb only we need to set the LSB for any address that
+            will be used with an interworking branch instruction.  */
+         if (using_thumb_only (htab))
+           initial_got_entry |= 1;
        }
+    }
 
-      /* Fill in the entry in the global offset table.  */
-      bfd_put_32 (output_bfd, initial_got_entry,
-                 sgot->contents + got_offset);
+  /* Fill in the entry in the global offset table.  */
+  bfd_put_32 (output_bfd, initial_got_entry,
+             sgot->contents + got_offset);
 
-      if (htab->fdpic_p && !(info->flags & DF_BIND_NOW))
-       {
-         /* Setup initial funcdesc value.  */
-         /* FIXME: we don't support lazy binding because there is a
-            race condition between both words getting written and
-            some other thread attempting to read them. The ARM
-            architecture does not have an atomic 64 bit load/store
-            instruction that could be used to prevent it; it is
-            recommended that threaded FDPIC applications run with the
-            LD_BIND_NOW environment variable set.  */
-         bfd_put_32(output_bfd, plt_address + 0x18,
-                    sgot->contents + got_offset);
-         bfd_put_32(output_bfd, -1 /*TODO*/,
-                    sgot->contents + got_offset + 4);
-       }
+  if (htab->fdpic_p && !(info->flags & DF_BIND_NOW))
+    {
+      /* Setup initial funcdesc value.  */
+      /* FIXME: we don't support lazy binding because there is a
+        race condition between both words getting written and
+        some other thread attempting to read them. The ARM
+        architecture does not have an atomic 64 bit load/store
+        instruction that could be used to prevent it; it is
+        recommended that threaded FDPIC applications run with the
+        LD_BIND_NOW environment variable set.  */
+      bfd_put_32(output_bfd, plt_address + 0x18,
+                sgot->contents + got_offset);
+      bfd_put_32(output_bfd, -1 /*TODO*/,
+                sgot->contents + got_offset + 4);
     }
 
   if (dynindx == -1)
@@ -10196,7 +10202,7 @@ calculate_group_reloc_mask (bfd_vma value, int n, bfd_vma *final_residual)
          /* Determine the most significant bit in the residual and
             align the resulting value to a 2-bit boundary.  */
          for (msb = 30; msb >= 0; msb -= 2)
-           if (residual & (3 << msb))
+           if (residual & (3u << msb))
              break;
 
          /* The desired shift is now (msb - 6), or zero, whichever
@@ -10310,16 +10316,22 @@ elf32_arm_final_link_relocate (reloc_howto_type *         howto,
 
   if (globals->use_rel)
     {
-      addend = bfd_get_32 (input_bfd, hit_data) & howto->src_mask;
+      bfd_vma sign;
 
-      if (addend & ((howto->src_mask + 1) >> 1))
+      switch (howto->size)
        {
-         signed_addend = -1;
-         signed_addend &= ~ howto->src_mask;
-         signed_addend |= addend;
+       case 0: addend = bfd_get_8 (input_bfd, hit_data); break;
+       case 1: addend = bfd_get_16 (input_bfd, hit_data); break;
+       case 2: addend = bfd_get_32 (input_bfd, hit_data); break;
+       default: addend = 0; break;
        }
-      else
-       signed_addend = addend;
+      /* Note: the addend and signed_addend calculated here are
+        incorrect for any split field.  */
+      addend &= howto->src_mask;
+      sign = howto->src_mask & ~(howto->src_mask >> 1);
+      signed_addend = (addend ^ sign) - sign;
+      signed_addend = (bfd_vma) signed_addend << howto->rightshift;
+      addend <<= howto->rightshift;
     }
   else
     addend = signed_addend = rel->r_addend;
@@ -10406,7 +10418,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
       return bfd_reloc_ok;
 
     case R_ARM_ABS12:
-      if (!globals->vxworks_p)
+      if (globals->root.target_os != is_vxworks)
        return elf32_arm_abs12_reloc (input_bfd, hit_data, value + addend);
       /* Fall through.  */
 
@@ -10454,7 +10466,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
           || globals->root.is_relocatable_executable
           || globals->fdpic_p)
          && (input_section->flags & SEC_ALLOC)
-         && !(globals->vxworks_p
+         && !(globals->root.target_os == is_vxworks
               && strcmp (input_section->output_section->name,
                          ".tls_vars") == 0)
          && ((r_type != R_ARM_REL32 && r_type != R_ARM_REL32_NOI)
@@ -10531,45 +10543,10 @@ elf32_arm_final_link_relocate (reloc_howto_type *         howto,
              /* This symbol is local, or marked to become local.  */
              BFD_ASSERT (r_type == R_ARM_ABS32 || r_type == R_ARM_ABS32_NOI
                          || (globals->fdpic_p && !bfd_link_pic(info)));
-             if (globals->symbian_p)
-               {
-                 asection *osec;
-
-                 /* On Symbian OS, the data segment and text segement
-                    can be relocated independently.  Therefore, we
-                    must indicate the segment to which this
-                    relocation is relative.  The BPABI allows us to
-                    use any symbol in the right segment; we just use
-                    the section symbol as it is convenient.  (We
-                    cannot use the symbol given by "h" directly as it
-                    will not appear in the dynamic symbol table.)
-
-                    Note that the dynamic linker ignores the section
-                    symbol value, so we don't subtract osec->vma
-                    from the emitted reloc addend.  */
-                 if (sym_sec)
-                   osec = sym_sec->output_section;
-                 else
-                   osec = input_section->output_section;
-                 symbol = elf_section_data (osec)->dynindx;
-                 if (symbol == 0)
-                   {
-                     struct elf_link_hash_table *htab = elf_hash_table (info);
-
-                     if ((osec->flags & SEC_READONLY) == 0
-                         && htab->data_index_section != NULL)
-                       osec = htab->data_index_section;
-                     else
-                       osec = htab->text_index_section;
-                     symbol = elf_section_data (osec)->dynindx;
-                   }
-                 BFD_ASSERT (symbol != 0);
-               }
-             else
-               /* On SVR4-ish systems, the dynamic loader cannot
-                  relocate the text and data segments independently,
-                  so the symbol does not matter.  */
-               symbol = 0;
+             /* On SVR4-ish systems, the dynamic loader cannot
+                relocate the text and data segments independently,
+                so the symbol does not matter.  */
+             symbol = 0;
              if (dynreloc_st_type == STT_GNU_IFUNC)
                /* We have an STT_GNU_IFUNC symbol that doesn't resolve
                   to the .iplt entry.  Instead, every non-call reference
@@ -10714,11 +10691,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *          howto,
          value -= (input_section->output_section->vma
                    + input_section->output_offset);
          value -= rel->r_offset;
-         if (globals->use_rel)
-           value += (signed_addend << howto->size);
-         else
-           /* RELA addends do not have to be adjusted by howto->size.  */
-           value += signed_addend;
+         value += signed_addend;
 
          signed_addend = value;
          signed_addend >>= howto->rightshift;
@@ -10822,9 +10795,6 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
       return bfd_reloc_ok;
 
     case R_ARM_ABS8:
-      /* PR 16202: Refectch the addend using the correct size.  */
-      if (globals->use_rel)
-       addend = bfd_get_8 (input_bfd, hit_data);
       value += addend;
 
       /* There is no way to tell whether the user intended to use a signed or
@@ -10837,9 +10807,6 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
       return bfd_reloc_ok;
 
     case R_ARM_ABS16:
-      /* PR 16202: Refectch the addend using the correct size.  */
-      if (globals->use_rel)
-       addend = bfd_get_16 (input_bfd, hit_data);
       value += addend;
 
       /* See comment for R_ARM_ABS8.  */
@@ -10893,7 +10860,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
 
        /* PR 21523: Use an absolute value.  The user of this reloc will
           have already selected an ADD or SUB insn appropriately.  */
-       value = labs (relocation);
+       value = llabs (relocation);
 
        if (value >= 0x1000)
          return bfd_reloc_overflow;
@@ -11318,25 +11285,12 @@ elf32_arm_final_link_relocate (reloc_howto_type *         howto,
 
        /* CZB cannot jump backward.  */
        if (r_type == R_ARM_THM_JUMP6)
-         reloc_signed_min = 0;
-
-       if (globals->use_rel)
          {
-           /* Need to refetch addend.  */
-           addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask;
-           if (addend & ((howto->src_mask + 1) >> 1))
-             {
-               signed_addend = -1;
-               signed_addend &= ~ howto->src_mask;
-               signed_addend |= addend;
-             }
-           else
-             signed_addend = addend;
-           /* The value in the insn has been right shifted.  We need to
-              undo this, so that we can perform the address calculation
-              in terms of bytes.  */
-           signed_addend <<= howto->rightshift;
+           reloc_signed_min = 0;
+           if (globals->use_rel)
+             signed_addend = ((addend & 0x200) >> 3) | ((addend & 0xf8) >> 2);
          }
+
        relocation = value + signed_addend;
 
        relocation -= (input_section->output_section->vma
@@ -11488,40 +11442,41 @@ elf32_arm_final_link_relocate (reloc_howto_type *         howto,
                  if (dynreloc_st_type == STT_GNU_IFUNC)
                    outrel.r_info = ELF32_R_INFO (0, R_ARM_IRELATIVE);
                  else if (bfd_link_pic (info)
-                          && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-                              || h->root.type != bfd_link_hash_undefweak))
+                          && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
                    outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
-                 else if (globals->fdpic_p)
-                   isrofixup = 1;
                  else
-                   outrel.r_info = 0;
+                   {
+                     outrel.r_info = 0;
+                     if (globals->fdpic_p)
+                       isrofixup = 1;
+                   }
                  outrel.r_addend = dynreloc_value;
                }
 
              /* The GOT entry is initialized to zero by default.
                 See if we should install a different value.  */
              if (outrel.r_addend != 0
-                 && (outrel.r_info == 0 || globals->use_rel || isrofixup))
+                 && (globals->use_rel || outrel.r_info == 0))
                {
                  bfd_put_32 (output_bfd, outrel.r_addend,
                              sgot->contents + off);
                  outrel.r_addend = 0;
                }
 
-             if (outrel.r_info != 0 && !isrofixup)
+             if (isrofixup)
+               arm_elf_add_rofixup (output_bfd,
+                                    elf32_arm_hash_table(info)->srofixup,
+                                    sgot->output_section->vma
+                                    + sgot->output_offset + off);
+
+             else if (outrel.r_info != 0)
                {
                  outrel.r_offset = (sgot->output_section->vma
                                     + sgot->output_offset
                                     + off);
                  elf32_arm_add_dynreloc (output_bfd, info, srelgot, &outrel);
                }
-             else if (isrofixup)
-               {
-                 arm_elf_add_rofixup(output_bfd,
-                                     elf32_arm_hash_table(info)->srofixup,
-                                     sgot->output_section->vma
-                                     + sgot->output_offset + off);
-               }
+
              h->got.offset |= 1;
            }
          value = sgot->output_offset + off;
@@ -11542,31 +11497,39 @@ elf32_arm_final_link_relocate (reloc_howto_type *         howto,
            off &= ~1;
          else
            {
-             if (globals->use_rel)
-               bfd_put_32 (output_bfd, dynreloc_value, sgot->contents + off);
+             Elf_Internal_Rela outrel;
+             int isrofixup = 0;
 
-             if (bfd_link_pic (info) || dynreloc_st_type == STT_GNU_IFUNC)
+             if (dynreloc_st_type == STT_GNU_IFUNC)
+               outrel.r_info = ELF32_R_INFO (0, R_ARM_IRELATIVE);
+             else if (bfd_link_pic (info))
+               outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
+             else
                {
-                 Elf_Internal_Rela outrel;
+                 outrel.r_info = 0;
+                 if (globals->fdpic_p)
+                   isrofixup = 1;
+               }
 
-                 outrel.r_addend = addend + dynreloc_value;
+             /* The GOT entry is initialized to zero by default.
+                See if we should install a different value.  */
+             if (globals->use_rel || outrel.r_info == 0)
+               bfd_put_32 (output_bfd, dynreloc_value, sgot->contents + off);
+
+             if (isrofixup)
+               arm_elf_add_rofixup (output_bfd,
+                                    globals->srofixup,
+                                    sgot->output_section->vma
+                                    + sgot->output_offset + off);
+
+             else if (outrel.r_info != 0)
+               {
+                 outrel.r_addend = addend + dynreloc_value;
                  outrel.r_offset = (sgot->output_section->vma
                                     + sgot->output_offset
                                     + off);
-                 if (dynreloc_st_type == STT_GNU_IFUNC)
-                   outrel.r_info = ELF32_R_INFO (0, R_ARM_IRELATIVE);
-                 else
-                   outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
                  elf32_arm_add_dynreloc (output_bfd, info, srelgot, &outrel);
                }
-             else if (globals->fdpic_p)
-               {
-                 /* For FDPIC executables, we use rofixup to fix
-                    address at runtime.  */
-                 arm_elf_add_rofixup(output_bfd, globals->srofixup,
-                                     sgot->output_section->vma + sgot->output_offset
-                                     + off);
-               }
 
              local_got_offsets[r_symndx] |= 1;
            }
@@ -11603,7 +11566,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
          {
            /* If we don't know the module number, create a relocation
               for it.  */
-           if (bfd_link_pic (info))
+           if (bfd_link_dll (info))
              {
                Elf_Internal_Rela outrel;
 
@@ -11707,7 +11670,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
               now, and emit any relocations.  If both an IE GOT and a
               GD GOT are necessary, we emit the GD first.  */
 
-           if ((bfd_link_pic (info) || indx != 0)
+           if ((bfd_link_dll (info) || indx != 0)
                && (h == NULL
                    || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                        && !resolved_to_zero)
@@ -11724,7 +11687,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                /* We should have relaxed, unless this is an undefined
                   weak symbol.  */
                BFD_ASSERT ((h && (h->root.type == bfd_link_hash_undefweak))
-                           || bfd_link_pic (info));
+                           || bfd_link_dll (info));
                BFD_ASSERT (globals->sgotplt_jump_table_size + offplt + 8
                            <= globals->root.sgotplt->size);
 
@@ -11930,9 +11893,9 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
            unsigned long data, insn;
            unsigned thumb;
 
-           data = bfd_get_32 (input_bfd, hit_data);
+           data = bfd_get_signed_32 (input_bfd, hit_data);
            thumb = data & 1;
-           data &= ~1u;
+           data &= ~1ul;
 
            if (thumb)
              {
@@ -12599,7 +12562,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
 
     case R_ARM_GOTOFFFUNCDESC:
       {
-        if (h == NULL)
+       if (h == NULL)
          {
            struct fdpic_local *local_fdpic_cnts = elf32_arm_local_fdpic_cnts(input_bfd);
            int dynindx = elf_section_data (sym_sec->output_section)->dynindx;
@@ -12660,7 +12623,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
 
     case R_ARM_GOTFUNCDESC:
       {
-        if (h != NULL)
+       if (h != NULL)
          {
            Elf_Internal_Rela outrel;
 
@@ -12720,9 +12683,10 @@ elf32_arm_final_link_relocate (reloc_howto_type *          howto,
                outrel.r_addend = 0;
                if (h->dynindx == -1 && !bfd_link_pic(info))
                  if (h->root.type == bfd_link_hash_undefweak)
-                    arm_elf_add_rofixup(output_bfd, globals->srofixup, -1);
+                   arm_elf_add_rofixup(output_bfd, globals->srofixup, -1);
                  else
-                    arm_elf_add_rofixup(output_bfd, globals->srofixup, outrel.r_offset);
+                   arm_elf_add_rofixup(output_bfd, globals->srofixup,
+                                       outrel.r_offset);
                else
                  elf32_arm_add_dynreloc (output_bfd, info, srelgot, &outrel);
                eh->fdpic_cnts.gotfuncdesc_offset |= 1;
@@ -12740,7 +12704,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
 
     case R_ARM_FUNCDESC:
       {
-        if (h == NULL)
+       if (h == NULL)
          {
            struct fdpic_local *local_fdpic_cnts = elf32_arm_local_fdpic_cnts(input_bfd);
            Elf_Internal_Rela outrel;
@@ -12832,6 +12796,131 @@ elf32_arm_final_link_relocate (reloc_howto_type *         howto,
       *unresolved_reloc_p = FALSE;
       return bfd_reloc_ok;
 
+    case R_ARM_THM_BF16:
+      {
+       bfd_vma relocation;
+       bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data);
+       bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2);
+
+       if (globals->use_rel)
+         {
+           bfd_vma immA  = (upper_insn & 0x001f);
+           bfd_vma immB  = (lower_insn & 0x07fe) >> 1;
+           bfd_vma immC  = (lower_insn & 0x0800) >> 11;
+           addend  = (immA << 12);
+           addend |= (immB << 2);
+           addend |= (immC << 1);
+           addend |= 1;
+           /* Sign extend.  */
+           signed_addend = (addend & 0x10000) ? addend - (1 << 17) : addend;
+         }
+
+       relocation  = value + signed_addend;
+       relocation -= (input_section->output_section->vma
+                      + input_section->output_offset
+                      + rel->r_offset);
+
+       /* Put RELOCATION back into the insn.  */
+       {
+         bfd_vma immA = (relocation & 0x0001f000) >> 12;
+         bfd_vma immB = (relocation & 0x00000ffc) >> 2;
+         bfd_vma immC = (relocation & 0x00000002) >> 1;
+
+         upper_insn = (upper_insn & 0xffe0) | immA;
+         lower_insn = (lower_insn & 0xf001) | (immC << 11) | (immB << 1);
+       }
+
+       /* Put the relocated value back in the object file:  */
+       bfd_put_16 (input_bfd, upper_insn, hit_data);
+       bfd_put_16 (input_bfd, lower_insn, hit_data + 2);
+
+       return bfd_reloc_ok;
+      }
+
+    case R_ARM_THM_BF12:
+      {
+       bfd_vma relocation;
+       bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data);
+       bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2);
+
+       if (globals->use_rel)
+         {
+           bfd_vma immA  = (upper_insn & 0x0001);
+           bfd_vma immB  = (lower_insn & 0x07fe) >> 1;
+           bfd_vma immC  = (lower_insn & 0x0800) >> 11;
+           addend  = (immA << 12);
+           addend |= (immB << 2);
+           addend |= (immC << 1);
+           addend |= 1;
+           /* Sign extend.  */
+           addend = (addend & 0x1000) ? addend - (1 << 13) : addend;
+           signed_addend = addend;
+         }
+
+       relocation  = value + signed_addend;
+       relocation -= (input_section->output_section->vma
+                      + input_section->output_offset
+                      + rel->r_offset);
+
+       /* Put RELOCATION back into the insn.  */
+       {
+         bfd_vma immA = (relocation & 0x00001000) >> 12;
+         bfd_vma immB = (relocation & 0x00000ffc) >> 2;
+         bfd_vma immC = (relocation & 0x00000002) >> 1;
+
+         upper_insn = (upper_insn & 0xfffe) | immA;
+         lower_insn = (lower_insn & 0xf001) | (immC << 11) | (immB << 1);
+       }
+
+       /* Put the relocated value back in the object file:  */
+       bfd_put_16 (input_bfd, upper_insn, hit_data);
+       bfd_put_16 (input_bfd, lower_insn, hit_data + 2);
+
+       return bfd_reloc_ok;
+      }
+
+    case R_ARM_THM_BF18:
+      {
+       bfd_vma relocation;
+       bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data);
+       bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2);
+
+       if (globals->use_rel)
+         {
+           bfd_vma immA  = (upper_insn & 0x007f);
+           bfd_vma immB  = (lower_insn & 0x07fe) >> 1;
+           bfd_vma immC  = (lower_insn & 0x0800) >> 11;
+           addend  = (immA << 12);
+           addend |= (immB << 2);
+           addend |= (immC << 1);
+           addend |= 1;
+           /* Sign extend.  */
+           addend = (addend & 0x40000) ? addend - (1 << 19) : addend;
+           signed_addend = addend;
+         }
+
+       relocation  = value + signed_addend;
+       relocation -= (input_section->output_section->vma
+                      + input_section->output_offset
+                      + rel->r_offset);
+
+       /* Put RELOCATION back into the insn.  */
+       {
+         bfd_vma immA = (relocation & 0x0007f000) >> 12;
+         bfd_vma immB = (relocation & 0x00000ffc) >> 2;
+         bfd_vma immC = (relocation & 0x00000002) >> 1;
+
+         upper_insn = (upper_insn & 0xff80) | immA;
+         lower_insn = (lower_insn & 0xf001) | (immC << 11) | (immB << 1);
+       }
+
+       /* Put the relocated value back in the object file:  */
+       bfd_put_16 (input_bfd, upper_insn, hit_data);
+       bfd_put_16 (input_bfd, lower_insn, hit_data + 2);
+
+       return bfd_reloc_ok;
+      }
+
     default:
       return bfd_reloc_notsupported;
     }
@@ -13154,7 +13243,7 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
          name = (bfd_elf_string_from_elf_section
                  (input_bfd, symtab_hdr->sh_link, sym->st_name));
          if (name == NULL || *name == '\0')
-           name = bfd_section_name (input_bfd, sec);
+           name = bfd_section_name (sec);
        }
 
       if (r_symndx != STN_UNDEF
@@ -13332,10 +13421,10 @@ adjust_exidx_size(asection *exidx_sec, int adjust)
   if (!exidx_sec->rawsize)
     exidx_sec->rawsize = exidx_sec->size;
 
-  bfd_set_section_size (exidx_sec->owner, exidx_sec, exidx_sec->size + adjust);
+  bfd_set_section_size (exidx_sec, exidx_sec->size + adjust);
   out_sec = exidx_sec->output_section;
   /* Adjust size of output section.  */
-  bfd_set_section_size (out_sec->owner, out_sec, out_sec->size +adjust);
+  bfd_set_section_size (out_sec, out_sec->size +adjust);
 }
 
 /* Insert an EXIDX_CANTUNWIND marker at the end of a section.  */
@@ -13633,6 +13722,7 @@ bfd_arm_get_mach_from_attributes (bfd * abfd)
 
   switch (arch)
     {
+    case TAG_CPU_ARCH_PRE_V4: return bfd_mach_arm_3M;
     case TAG_CPU_ARCH_V4: return bfd_mach_arm_4;
     case TAG_CPU_ARCH_V4T: return bfd_mach_arm_4T;
     case TAG_CPU_ARCH_V5T: return bfd_mach_arm_5T;
@@ -13670,7 +13760,40 @@ bfd_arm_get_mach_from_attributes (bfd * abfd)
        return bfd_mach_arm_5TE;
       }
 
+    case TAG_CPU_ARCH_V5TEJ:
+       return bfd_mach_arm_5TEJ;
+    case TAG_CPU_ARCH_V6:
+       return bfd_mach_arm_6;
+    case TAG_CPU_ARCH_V6KZ:
+       return bfd_mach_arm_6KZ;
+    case TAG_CPU_ARCH_V6T2:
+       return bfd_mach_arm_6T2;
+    case TAG_CPU_ARCH_V6K:
+       return bfd_mach_arm_6K;
+    case TAG_CPU_ARCH_V7:
+       return bfd_mach_arm_7;
+    case TAG_CPU_ARCH_V6_M:
+       return bfd_mach_arm_6M;
+    case TAG_CPU_ARCH_V6S_M:
+       return bfd_mach_arm_6SM;
+    case TAG_CPU_ARCH_V7E_M:
+       return bfd_mach_arm_7EM;
+    case TAG_CPU_ARCH_V8:
+       return bfd_mach_arm_8;
+    case TAG_CPU_ARCH_V8R:
+       return bfd_mach_arm_8R;
+    case TAG_CPU_ARCH_V8M_BASE:
+       return bfd_mach_arm_8M_BASE;
+    case TAG_CPU_ARCH_V8M_MAIN:
+       return bfd_mach_arm_8M_MAIN;
+    case TAG_CPU_ARCH_V8_1M_MAIN:
+       return bfd_mach_arm_8_1M_MAIN;
+
     default:
+      /* Force entry to be added for any new known Tag_CPU_arch value.  */
+      BFD_ASSERT (arch > MAX_TAG_CPU_ARCH);
+
+      /* Unknown Tag_CPU_arch value.  */
       return bfd_mach_arm_unknown;
     }
 }
@@ -14077,6 +14200,31 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out,
       T(V8M_MAIN),     /* V8-M BASELINE.  */
       T(V8M_MAIN)      /* V8-M MAINLINE.  */
     };
+  const int v8_1m_mainline[] =
+    {
+      -1,              /* PRE_V4.  */
+      -1,              /* V4.  */
+      -1,              /* V4T.  */
+      -1,              /* V5T.  */
+      -1,              /* V5TE.  */
+      -1,              /* V5TEJ.  */
+      -1,              /* V6.  */
+      -1,              /* V6KZ.  */
+      -1,              /* V6T2.  */
+      -1,              /* V6K.  */
+      T(V8_1M_MAIN),   /* V7.  */
+      T(V8_1M_MAIN),   /* V6_M.  */
+      T(V8_1M_MAIN),   /* V6S_M.  */
+      T(V8_1M_MAIN),   /* V7E_M.  */
+      -1,              /* V8.  */
+      -1,              /* V8R.  */
+      T(V8_1M_MAIN),   /* V8-M BASELINE.  */
+      T(V8_1M_MAIN),   /* V8-M MAINLINE.  */
+      -1,              /* Unused (18).  */
+      -1,              /* Unused (19).  */
+      -1,              /* Unused (20).  */
+      T(V8_1M_MAIN)    /* V8.1-M MAINLINE.  */
+    };
   const int v4t_plus_v6_m[] =
     {
       -1,              /* PRE_V4.  */
@@ -14097,6 +14245,10 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out,
       -1,              /* V8R.  */
       T(V8M_BASE),     /* V8-M BASELINE.  */
       T(V8M_MAIN),     /* V8-M MAINLINE.  */
+      -1,              /* Unused (18).  */
+      -1,              /* Unused (19).  */
+      -1,              /* Unused (20).  */
+      T(V8_1M_MAIN),   /* V8.1-M MAINLINE.  */
       T(V4T_PLUS_V6_M) /* V4T plus V6_M.  */
     };
   const int *comb[] =
@@ -14111,6 +14263,10 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out,
       v8r,
       v8m_baseline,
       v8m_mainline,
+      NULL,
+      NULL,
+      NULL,
+      v8_1m_mainline,
       /* Pseudo-architecture.  */
       v4t_plus_v6_m
     };
@@ -14391,6 +14547,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, struct bfd_link_info *info)
        case Tag_CPU_unaligned_access:
        case Tag_T2EE_use:
        case Tag_MPextension_use:
+       case Tag_MVE_arch:
          /* Use the largest value specified.  */
          if (in_attr[i].i > out_attr[i].i)
            out_attr[i].i = in_attr[i].i;
@@ -14823,7 +14980,7 @@ elf32_arm_print_private_bfd_data (bfd *abfd, void * ptr)
   /* Ignore init flag - it may not be set, despite the flags field
      containing valid data.  */
 
-  fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
+  fprintf (file, _("private flags = 0x%lx:"), elf_elfheader (abfd)->e_flags);
 
   switch (EF_ARM_EABI_VERSION (flags))
     {
@@ -14944,7 +15101,7 @@ elf32_arm_print_private_bfd_data (bfd *abfd, void * ptr)
   flags &= ~ (EF_ARM_RELEXEC | EF_ARM_PIC);
 
   if (flags)
-    fprintf (file, _("<Unrecognised flag bits set>"));
+    fprintf (file, _(" <Unrecognised flag bits set>"));
 
   fputc ('\n', file);
 
@@ -15073,7 +15230,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
          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->root.sym_cache,
                                            abfd, r_symndx);
              if (isym == NULL)
                return FALSE;
@@ -15251,7 +15408,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
          case R_ARM_ABS12:
            /* VxWorks uses dynamic R_ARM_ABS12 relocations for
               ldr __GOTT_INDEX__ offsets.  */
-           if (!htab->vxworks_p)
+           if (htab->root.target_os != is_vxworks)
              {
                may_need_local_target_p = TRUE;
                break;
@@ -15326,9 +15483,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
        /* This relocation describes which C++ vtable entries are actually
           used.  Record for later use during GC.  */
        case R_ARM_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))
            return FALSE;
          break;
        }
@@ -15404,22 +15559,12 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
              if (sreloc == NULL)
                return FALSE;
-
-             /* BPABI objects never have dynamic relocations mapped.  */
-             if (htab->symbian_p)
-               {
-                 flagword flags;
-
-                 flags = bfd_get_section_flags (dynobj, sreloc);
-                 flags &= ~(SEC_LOAD | SEC_ALLOC);
-                 bfd_set_section_flags (dynobj, sreloc, flags);
-               }
            }
 
          /* If this is a global symbol, count the number of
             relocations we need for this symbol.  */
          if (h != NULL)
-           head = &((struct elf32_arm_link_hash_entry *) h)->dyn_relocs;
+           head = &h->dyn_relocs;
          else
            {
              head = elf32_arm_get_local_dynreloc_list (abfd, r_symndx, isym);
@@ -15430,7 +15575,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
          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->root.dynobj, amt);
              if (p == NULL)
@@ -15532,7 +15677,7 @@ elf32_arm_update_relocs (asection *o,
          eadi = get_arm_elf_section_data (i);
          edit_list = eadi->u.exidx.unwind_edit_list;
          edit_tail = eadi->u.exidx.unwind_edit_tail;
-         offset = o->vma + i->output_offset;
+         offset = i->output_offset;
 
          if (eadi->elf.rel.hdr &&
              eadi->elf.rel.hdr->sh_entsize == rel_hdr->sh_entsize)
@@ -15645,6 +15790,8 @@ elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info,
   struct elf_link_hash_entry **sym_hashes;
   struct elf32_arm_link_hash_entry *cmse_hash;
   bfd_boolean again, is_v8m, first_bfd_browse = TRUE;
+  bfd_boolean debug_sec_need_to_be_marked = FALSE;
+  asection *isec;
 
   _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook);
 
@@ -15700,13 +15847,31 @@ elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info,
 
                  /* Assume it is a special symbol.  If not, cmse_scan will
                     warn about it and user can do something about it.  */
-                 if (ARM_GET_SYM_CMSE_SPCL (cmse_hash->root.target_internal))
+                 if (startswith (cmse_hash->root.root.root.string,
+                                   CMSE_PREFIX))
                    {
                      cmse_sec = cmse_hash->root.root.u.def.section;
                      if (!cmse_sec->gc_mark
                          && !_bfd_elf_gc_mark (info, cmse_sec, gc_mark_hook))
                        return FALSE;
+                     /* The debug sections related to these secure entry
+                        functions are marked on enabling below flag.  */
+                     debug_sec_need_to_be_marked = TRUE;
+                   }
+               }
+
+             if (debug_sec_need_to_be_marked)
+               {
+                 /* Looping over all the sections of the object file containing
+                    Armv8-M secure entry functions and marking all the debug
+                    sections.  */
+                 for (isec = sub->sections; isec != NULL; isec = isec->next)
+                   {
+                     /* If not a debug sections, skip it.  */
+                     if (!isec->gc_mark && (isec->flags & SEC_DEBUGGING))
+                       isec->gc_mark = 1 ;
                    }
+                 debug_sec_need_to_be_marked = FALSE;
                }
            }
        }
@@ -15725,119 +15890,44 @@ elf32_arm_is_target_special_symbol (bfd * abfd ATTRIBUTE_UNUSED, asymbol * sym)
                                         BFD_ARM_SPECIAL_SYM_TYPE_ANY);
 }
 
-/* This is a copy of elf_find_function() from elf.c except that
-   ARM mapping symbols are ignored when looking for function names
-   and STT_ARM_TFUNC is considered to a function type.  */
+/* If the ELF symbol SYM might be a function in SEC, return the
+   function size and set *CODE_OFF to the function's entry point,
+   otherwise return zero.  */
 
-static bfd_boolean
-arm_elf_find_function (bfd *        abfd ATTRIBUTE_UNUSED,
-                      asymbol **    symbols,
-                      asection *    section,
-                      bfd_vma       offset,
-                      const char ** filename_ptr,
-                      const char ** functionname_ptr)
+static bfd_size_type
+elf32_arm_maybe_function_sym (const asymbol *sym, asection *sec,
+                             bfd_vma *code_off)
 {
-  const char * filename = NULL;
-  asymbol * func = NULL;
-  bfd_vma low_func = 0;
-  asymbol ** p;
-
-  for (p = symbols; *p != NULL; p++)
-    {
-      elf_symbol_type *q;
+  bfd_size_type size;
 
-      q = (elf_symbol_type *) *p;
+  if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT
+                    | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0
+      || sym->section != sec)
+    return 0;
 
-      switch (ELF_ST_TYPE (q->internal_elf_sym.st_info))
-       {
-       default:
-         break;
-       case STT_FILE:
-         filename = bfd_asymbol_name (&q->symbol);
-         break;
+  if (!(sym->flags & BSF_SYNTHETIC))
+    switch (ELF_ST_TYPE (((elf_symbol_type *) sym)->internal_elf_sym.st_info))
+      {
        case STT_FUNC:
        case STT_ARM_TFUNC:
        case STT_NOTYPE:
-         /* Skip mapping symbols.  */
-         if ((q->symbol.flags & BSF_LOCAL)
-             && bfd_is_arm_special_symbol_name (q->symbol.name,
-                   BFD_ARM_SPECIAL_SYM_TYPE_ANY))
-           continue;
-         /* Fall through.  */
-         if (bfd_get_section (&q->symbol) == section
-             && q->symbol.value >= low_func
-             && q->symbol.value <= offset)
-           {
-             func = (asymbol *) q;
-             low_func = q->symbol.value;
-           }
          break;
-       }
-    }
-
-  if (func == NULL)
-    return FALSE;
-
-  if (filename_ptr)
-    *filename_ptr = filename;
-  if (functionname_ptr)
-    *functionname_ptr = bfd_asymbol_name (func);
-
-  return TRUE;
-}
-
-
-/* Find the nearest line to a particular section and offset, for error
-   reporting.   This code is a duplicate of the code in elf.c, except
-   that it uses arm_elf_find_function.  */
-
-static bfd_boolean
-elf32_arm_find_nearest_line (bfd *         abfd,
-                            asymbol **     symbols,
-                            asection *     section,
-                            bfd_vma        offset,
-                            const char **  filename_ptr,
-                            const char **  functionname_ptr,
-                            unsigned int * line_ptr,
-                            unsigned int * discriminator_ptr)
-{
-  bfd_boolean found = FALSE;
-
-  if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
-                                    filename_ptr, functionname_ptr,
-                                    line_ptr, discriminator_ptr,
-                                    dwarf_debug_sections, 0,
-                                    & elf_tdata (abfd)->dwarf2_find_line_info))
-    {
-      if (!*functionname_ptr)
-       arm_elf_find_function (abfd, symbols, section, offset,
-                              *filename_ptr ? NULL : filename_ptr,
-                              functionname_ptr);
-
-      return TRUE;
-    }
-
-  /* Skip _bfd_dwarf1_find_nearest_line since no known ARM toolchain
-     uses DWARF1.  */
-
-  if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
-                                            & found, filename_ptr,
-                                            functionname_ptr, line_ptr,
-                                            & elf_tdata (abfd)->line_info))
-    return FALSE;
-
-  if (found && (*functionname_ptr || *line_ptr))
-    return TRUE;
-
-  if (symbols == NULL)
-    return FALSE;
+       default:
+         return 0;
+      }
 
-  if (! arm_elf_find_function (abfd, symbols, section, offset,
-                              filename_ptr, functionname_ptr))
-    return FALSE;
+  if ((sym->flags & BSF_LOCAL)
+      && bfd_is_arm_special_symbol_name (sym->name,
+                                        BFD_ARM_SPECIAL_SYM_TYPE_ANY))
+    return 0;
 
-  *line_ptr = 0;
-  return TRUE;
+  *code_off = sym->value;
+  size = 0;
+  if (!(sym->flags & BSF_SYNTHETIC))
+    size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
+  if (size == 0)
+    size = 1;
+  return size;
 }
 
 static bfd_boolean
@@ -15853,23 +15943,6 @@ elf32_arm_find_inliner_info (bfd *         abfd,
   return found;
 }
 
-/* Find dynamic relocs for H that apply to read-only sections.  */
-
-static asection *
-readonly_dynrelocs (struct elf_link_hash_entry *h)
-{
-  struct elf_dyn_relocs *p;
-
-  for (p = elf32_arm_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
-    {
-      asection *s = p->sec->output_section;
-
-      if (s != NULL && (s->flags & SEC_READONLY) != 0)
-       return p->sec;
-    }
-  return NULL;
-}
-
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -16082,7 +16155,7 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
          /* VxWorks executables have a second set of relocations for
             each PLT entry.  They go in a separate relocation section,
             which is processed by the kernel loader.  */
-         if (htab->vxworks_p && !bfd_link_pic (info))
+         if (htab->root.target_os == is_vxworks && !bfd_link_pic (info))
            {
              /* There is a relocation for the initial PLT entry:
                 an R_ARM_32 relocation for _GLOBAL_OFFSET_TABLE_.  */
@@ -16119,112 +16192,108 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
 
       /* Make sure this symbol is output as a dynamic symbol.
         Undefined weak syms won't yet be marked as dynamic.  */
-      if (htab->root.dynamic_sections_created && h->dynindx == -1 && !h->forced_local
+      if (htab->root.dynamic_sections_created
+         && h->dynindx == -1
+         && !h->forced_local
          && h->root.type == bfd_link_hash_undefweak)
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
            return FALSE;
        }
 
-      if (!htab->symbian_p)
-       {
-         s = htab->root.sgot;
-         h->got.offset = s->size;
+      s = htab->root.sgot;
+      h->got.offset = s->size;
 
-         if (tls_type == GOT_UNKNOWN)
-           abort ();
+      if (tls_type == GOT_UNKNOWN)
+       abort ();
 
-         if (tls_type == GOT_NORMAL)
-           /* Non-TLS symbols need one GOT slot.  */
-           s->size += 4;
-         else
+      if (tls_type == GOT_NORMAL)
+       /* Non-TLS symbols need one GOT slot.  */
+       s->size += 4;
+      else
+       {
+         if (tls_type & GOT_TLS_GDESC)
            {
-             if (tls_type & GOT_TLS_GDESC)
-               {
-                 /* R_ARM_TLS_DESC needs 2 GOT slots.  */
-                 eh->tlsdesc_got
-                   = (htab->root.sgotplt->size
-                      - elf32_arm_compute_jump_table_size (htab));
-                 htab->root.sgotplt->size += 8;
-                 h->got.offset = (bfd_vma) -2;
-                 /* plt.got_offset needs to know there's a TLS_DESC
-                    reloc in the middle of .got.plt.  */
-                 htab->num_tls_desc++;
-               }
-
-             if (tls_type & GOT_TLS_GD)
-               {
-                 /* R_ARM_TLS_GD32 and R_ARM_TLS_GD32_FDPIC need two
-                    consecutive GOT slots.  If the symbol is both GD
-                    and GDESC, got.offset may have been
-                    overwritten.  */
-                 h->got.offset = s->size;
-                 s->size += 8;
-               }
+             /* R_ARM_TLS_DESC needs 2 GOT slots.  */
+             eh->tlsdesc_got
+               = (htab->root.sgotplt->size
+                  - elf32_arm_compute_jump_table_size (htab));
+             htab->root.sgotplt->size += 8;
+             h->got.offset = (bfd_vma) -2;
+             /* plt.got_offset needs to know there's a TLS_DESC
+                reloc in the middle of .got.plt.  */
+             htab->num_tls_desc++;
+           }
 
-             if (tls_type & GOT_TLS_IE)
-               /* R_ARM_TLS_IE32/R_ARM_TLS_IE32_FDPIC need one GOT
-                  slot.  */
-               s->size += 4;
+         if (tls_type & GOT_TLS_GD)
+           {
+             /* R_ARM_TLS_GD32 and R_ARM_TLS_GD32_FDPIC need two
+                consecutive GOT slots.  If the symbol is both GD
+                and GDESC, got.offset may have been
+                overwritten.  */
+             h->got.offset = s->size;
+             s->size += 8;
            }
 
-         dyn = htab->root.dynamic_sections_created;
+         if (tls_type & GOT_TLS_IE)
+           /* R_ARM_TLS_IE32/R_ARM_TLS_IE32_FDPIC need one GOT
+              slot.  */
+           s->size += 4;
+       }
 
-         indx = 0;
-         if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
-                                              bfd_link_pic (info),
-                                              h)
-             && (!bfd_link_pic (info)
-                 || !SYMBOL_REFERENCES_LOCAL (info, h)))
-           indx = h->dynindx;
+      dyn = htab->root.dynamic_sections_created;
 
-         if (tls_type != GOT_NORMAL
-             && (bfd_link_pic (info) || indx != 0)
-             && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-                 || h->root.type != bfd_link_hash_undefweak))
-           {
-             if (tls_type & GOT_TLS_IE)
-               elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
+      indx = 0;
+      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h)
+         && (!bfd_link_pic (info)
+             || !SYMBOL_REFERENCES_LOCAL (info, h)))
+       indx = h->dynindx;
 
-             if (tls_type & GOT_TLS_GD)
-               elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
+      if (tls_type != GOT_NORMAL
+         && (bfd_link_dll (info) || indx != 0)
+         && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+             || h->root.type != bfd_link_hash_undefweak))
+       {
+         if (tls_type & GOT_TLS_IE)
+           elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
 
-             if (tls_type & GOT_TLS_GDESC)
-               {
-                 elf32_arm_allocate_dynrelocs (info, htab->root.srelplt, 1);
-                 /* GDESC needs a trampoline to jump to.  */
-                 htab->tls_trampoline = -1;
-               }
+         if (tls_type & GOT_TLS_GD)
+           elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
 
-             /* Only GD needs it.  GDESC just emits one relocation per
-                2 entries.  */
-             if ((tls_type & GOT_TLS_GD) && indx != 0)
-               elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
-           }
-         else if (((indx != -1) || htab->fdpic_p)
-                  && !SYMBOL_REFERENCES_LOCAL (info, h))
+         if (tls_type & GOT_TLS_GDESC)
            {
-             if (htab->root.dynamic_sections_created)
-               /* Reserve room for the GOT entry's R_ARM_GLOB_DAT relocation.  */
-               elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
+             elf32_arm_allocate_dynrelocs (info, htab->root.srelplt, 1);
+             /* GDESC needs a trampoline to jump to.  */
+             htab->tls_trampoline = -1;
            }
-         else if (h->type == STT_GNU_IFUNC
-                  && eh->plt.noncall_refcount == 0)
-           /* No non-call references resolve the STT_GNU_IFUNC's PLT entry;
-              they all resolve dynamically instead.  Reserve room for the
-              GOT entry's R_ARM_IRELATIVE relocation.  */
-           elf32_arm_allocate_irelocs (info, htab->root.srelgot, 1);
-         else if (bfd_link_pic (info)
-                  && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-                      || h->root.type != bfd_link_hash_undefweak))
-           /* Reserve room for the GOT entry's R_ARM_RELATIVE relocation.  */
+
+         /* Only GD needs it.  GDESC just emits one relocation per
+            2 entries.  */
+         if ((tls_type & GOT_TLS_GD) && indx != 0)
            elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
-         else if (htab->fdpic_p && tls_type == GOT_NORMAL)
-           /* Reserve room for rofixup for FDPIC executable.  */
-           /* TLS relocs do not need space since they are completely
-              resolved.  */
-           htab->srofixup->size += 4;
        }
+      else if (((indx != -1) || htab->fdpic_p)
+              && !SYMBOL_REFERENCES_LOCAL (info, h))
+       {
+         if (htab->root.dynamic_sections_created)
+           /* Reserve room for the GOT entry's R_ARM_GLOB_DAT relocation.  */
+           elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
+       }
+      else if (h->type == STT_GNU_IFUNC
+              && eh->plt.noncall_refcount == 0)
+       /* No non-call references resolve the STT_GNU_IFUNC's PLT entry;
+          they all resolve dynamically instead.  Reserve room for the
+          GOT entry's R_ARM_IRELATIVE relocation.  */
+       elf32_arm_allocate_irelocs (info, htab->root.srelgot, 1);
+      else if (bfd_link_pic (info)
+              && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
+       /* Reserve room for the GOT entry's R_ARM_RELATIVE relocation.  */
+       elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
+      else if (htab->fdpic_p && tls_type == GOT_NORMAL)
+       /* Reserve room for rofixup for FDPIC executable.  */
+       /* TLS relocs do not need space since they are completely
+          resolved.  */
+       htab->srofixup->size += 4;
     }
   else
     h->got.offset = (bfd_vma) -1;
@@ -16236,7 +16305,8 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
       if (h->dynindx != -1)
        abort();
 
-      /* We only allocate one function descriptor with its associated relocation.  */
+      /* We only allocate one function descriptor with its associated
+        relocation.  */
       if (eh->fdpic_cnts.funcdesc_offset == -1)
        {
          asection *s = htab->root.sgot;
@@ -16262,13 +16332,15 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
 
       if (h->dynindx == -1)
        {
-         /* We only allocate one function descriptor with its associated relocation. q */
+         /* We only allocate one function descriptor with its
+            associated relocation.  */
          if (eh->fdpic_cnts.funcdesc_offset == -1)
            {
 
              eh->fdpic_cnts.funcdesc_offset = s->size;
              s->size += 8;
-             /* We will add an R_ARM_FUNCDESC_VALUE relocation or two rofixups.  */
+             /* We will add an R_ARM_FUNCDESC_VALUE relocation or two
+                rofixups.  */
              if (bfd_link_pic(info))
                elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
              else
@@ -16281,9 +16353,9 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
       eh->fdpic_cnts.gotfuncdesc_offset = s->size;
       s->size += 4;
       if (h->dynindx == -1 && !bfd_link_pic(info))
-        htab->srofixup->size += 4;
+       htab->srofixup->size += 4;
       else
-        elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
+       elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
     }
 
   if (eh->fdpic_cnts.funcdesc_cnt > 0)
@@ -16295,14 +16367,16 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
 
       if (h->dynindx == -1)
        {
-         /* We only allocate one function descriptor with its associated relocation.  */
+         /* We only allocate one function descriptor with its
+            associated relocation.  */
          if (eh->fdpic_cnts.funcdesc_offset == -1)
            {
              asection *s = htab->root.sgot;
 
              eh->fdpic_cnts.funcdesc_offset = s->size;
              s->size += 8;
-             /* We will add an R_ARM_FUNCDESC_VALUE relocation or two rofixups.  */
+             /* We will add an R_ARM_FUNCDESC_VALUE relocation or two
+                rofixups.  */
              if (bfd_link_pic(info))
                elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
              else
@@ -16356,7 +16430,7 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
       h->root.u.def.value = th->root.u.def.value & ~1;
     }
 
-  if (eh->dyn_relocs == NULL)
+  if (h->dyn_relocs == NULL)
     return TRUE;
 
   /* In the shared -Bsymbolic case, discard space allocated for
@@ -16365,7 +16439,9 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
      space for pc-relative relocs that have become local due to symbol
      visibility changes.  */
 
-  if (bfd_link_pic (info) || htab->root.is_relocatable_executable || htab->fdpic_p)
+  if (bfd_link_pic (info)
+      || htab->root.is_relocatable_executable
+      || htab->fdpic_p)
     {
       /* Relocs that use pc_count are PC-relative forms, which will appear
         on something like ".long foo - ." or "movw REG, foo - .".  We want
@@ -16377,7 +16453,7 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
        {
          struct elf_dyn_relocs **pp;
 
-         for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+         for (pp = &h->dyn_relocs; (p = *pp) != NULL; )
            {
              p->count -= p->pc_count;
              p->pc_count = 0;
@@ -16388,11 +16464,11 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
            }
        }
 
-      if (htab->vxworks_p)
+      if (htab->root.target_os == is_vxworks)
        {
          struct elf_dyn_relocs **pp;
 
-         for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+         for (pp = &h->dyn_relocs; (p = *pp) != NULL; )
            {
              if (strcmp (p->sec->output_section->name, ".tls_vars") == 0)
                *pp = p->next;
@@ -16403,12 +16479,12 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
 
       /* Also discard relocs on undefined weak syms with non-default
         visibility.  */
-      if (eh->dyn_relocs != NULL
+      if (h->dyn_relocs != NULL
          && h->root.type == bfd_link_hash_undefweak)
        {
          if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
              || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
-           eh->dyn_relocs = NULL;
+           h->dyn_relocs = NULL;
 
          /* Make sure undefined weak symbols are output as a dynamic
             symbol in PIEs.  */
@@ -16459,13 +16535,13 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
            goto keep;
        }
 
-      eh->dyn_relocs = NULL;
+      h->dyn_relocs = NULL;
 
     keep: ;
     }
 
   /* Finally, allocate space.  */
-  for (p = eh->dyn_relocs; p != NULL; p = p->next)
+  for (p = h->dyn_relocs; p != NULL; p = p->next)
     {
       asection *sreloc = elf_section_data (p->sec)->sreloc;
 
@@ -16473,7 +16549,8 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
          && eh->plt.noncall_refcount == 0
          && SYMBOL_REFERENCES_LOCAL (info, h))
        elf32_arm_allocate_irelocs (info, sreloc, p->count);
-      else if (h->dynindx != -1 && (!bfd_link_pic(info) || !info->symbolic || !h->def_regular))
+      else if (h->dynindx != -1
+              && (!bfd_link_pic(info) || !info->symbolic || !h->def_regular))
        elf32_arm_allocate_dynrelocs (info, sreloc, p->count);
       else if (htab->fdpic_p && !bfd_link_pic(info))
        htab->srofixup->size += 4 * p->count;
@@ -16484,34 +16561,6 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
   return TRUE;
 }
 
-/* Set DF_TEXTREL if we find any dynamic relocs that apply to
-   read-only sections.  */
-
-static bfd_boolean
-maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p)
-{
-  asection *sec;
-
-  if (h->root.type == bfd_link_hash_indirect)
-    return TRUE;
-
-  sec = readonly_dynrelocs (h);
-  if (sec != NULL)
-    {
-      struct bfd_link_info *info = (struct bfd_link_info *) info_p;
-
-      info->flags |= DF_TEXTREL;
-      info->callbacks->minfo
-       (_("%pB: dynamic relocation against `%pT' in read-only section `%pA'\n"),
-        sec->owner, h->root.root.string, sec);
-
-      /* Not an error, just cut short the traversal.  */
-      return FALSE;
-    }
-
-  return TRUE;
-}
-
 void
 bfd_elf32_arm_set_byteswap_code (struct bfd_link_info *info,
                                 int byteswap_code)
@@ -16533,7 +16582,6 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
 {
   bfd * dynobj;
   asection * s;
-  bfd_boolean plt;
   bfd_boolean relocs;
   bfd *ibfd;
   struct elf32_arm_link_hash_table *htab;
@@ -16570,7 +16618,6 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
-      bfd_boolean is_vxworks = htab->vxworks_p;
       unsigned int symndx;
       struct fdpic_local *local_fdpic_cnts;
 
@@ -16592,7 +16639,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
                     linker script /DISCARD/, so we'll be discarding
                     the relocs too.  */
                }
-             else if (is_vxworks
+             else if (htab->root.target_os == is_vxworks
                       && strcmp (p->sec->output_section->name,
                                  ".tls_vars") == 0)
                {
@@ -16733,7 +16780,8 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
                  s->size += 4;
                }
 
-             isym = bfd_sym_from_r_symndx (&htab->sym_cache, ibfd, symndx);
+             isym = bfd_sym_from_r_symndx (&htab->root.sym_cache, ibfd,
+                                           symndx);
              if (isym == NULL)
                return FALSE;
 
@@ -16822,12 +16870,14 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
 
       /* If we're not using lazy TLS relocations, don't generate the
         PLT and GOT entries they require.  */
-      if (!(info->flags & DF_BIND_NOW))
+      if ((info->flags & DF_BIND_NOW))
+       htab->root.tlsdesc_plt = 0;
+      else
        {
-         htab->dt_tlsdesc_got = htab->root.sgot->size;
+         htab->root.tlsdesc_got = htab->root.sgot->size;
          htab->root.sgot->size += 4;
 
-         htab->dt_tlsdesc_plt = htab->root.splt->size;
+         htab->root.tlsdesc_plt = htab->root.splt->size;
          htab->root.splt->size += 4 * ARRAY_SIZE (dl_tlsdesc_lazy_trampoline);
        }
     }
@@ -16835,7 +16885,6 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
   /* The check_relocs and adjust_dynamic_symbol entry points have
      determined the sizes of the various dynamic sections.  Allocate
      memory for them.  */
-  plt = FALSE;
   relocs = FALSE;
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
@@ -16846,14 +16895,14 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
 
       /* It's OK to base decisions on the section name, because none
         of the dynobj section names depend upon the input files.  */
-      name = bfd_get_section_name (dynobj, s);
+      name = bfd_section_name (s);
 
       if (s == htab->root.splt)
        {
          /* Remember whether there is a PLT.  */
-         plt = s->size != 0;
+         ;
        }
-      else if (CONST_STRNEQ (name, ".rel"))
+      else if (startswith (name, ".rel"))
        {
          if (s->size != 0)
            {
@@ -16903,72 +16952,8 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
        return FALSE;
     }
 
-  if (elf_hash_table (info)->dynamic_sections_created)
-    {
-      /* Add some entries to the .dynamic section.  We fill in the
-        values later, in elf32_arm_finish_dynamic_sections, but we
-        must add the entries now so that we get the correct size for
-        the .dynamic section.  The DT_DEBUG entry is filled in by the
-        dynamic linker and used by the debugger.  */
-#define add_dynamic_entry(TAG, VAL) \
-  _bfd_elf_add_dynamic_entry (info, TAG, VAL)
-
-     if (bfd_link_executable (info))
-       {
-         if (!add_dynamic_entry (DT_DEBUG, 0))
-           return FALSE;
-       }
-
-      if (plt)
-       {
-         if (   !add_dynamic_entry (DT_PLTGOT, 0)
-             || !add_dynamic_entry (DT_PLTRELSZ, 0)
-             || !add_dynamic_entry (DT_PLTREL,
-                                    htab->use_rel ? DT_REL : DT_RELA)
-             || !add_dynamic_entry (DT_JMPREL, 0))
-           return FALSE;
-
-         if (htab->dt_tlsdesc_plt
-             && (!add_dynamic_entry (DT_TLSDESC_PLT,0)
-                 || !add_dynamic_entry (DT_TLSDESC_GOT,0)))
-           return FALSE;
-       }
-
-      if (relocs)
-       {
-         if (htab->use_rel)
-           {
-             if (!add_dynamic_entry (DT_REL, 0)
-                 || !add_dynamic_entry (DT_RELSZ, 0)
-                 || !add_dynamic_entry (DT_RELENT, RELOC_SIZE (htab)))
-               return FALSE;
-           }
-         else
-           {
-             if (!add_dynamic_entry (DT_RELA, 0)
-                 || !add_dynamic_entry (DT_RELASZ, 0)
-                 || !add_dynamic_entry (DT_RELAENT, RELOC_SIZE (htab)))
-               return FALSE;
-           }
-       }
-
-      /* If any dynamic relocs apply to a read-only section,
-        then we need a DT_TEXTREL entry.  */
-      if ((info->flags & DF_TEXTREL) == 0)
-       elf_link_hash_traverse (&htab->root, maybe_set_textrel, info);
-
-      if ((info->flags & DF_TEXTREL) != 0)
-       {
-         if (!add_dynamic_entry (DT_TEXTREL, 0))
-           return FALSE;
-       }
-      if (htab->vxworks_p
-         && !elf_vxworks_add_dynamic_entries (output_bfd, info))
-       return FALSE;
-    }
-#undef add_dynamic_entry
-
-  return TRUE;
+  return _bfd_elf_maybe_vxworks_add_dynamic_tags (output_bfd, info,
+                                                 relocs);
 }
 
 /* Size sections even though they're not dynamic.  We use it to setup
@@ -17107,7 +17092,9 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd,
      and for FDPIC, the _GLOBAL_OFFSET_TABLE_ symbol is not absolute:
      it is relative to the ".got" section.  */
   if (h == htab->root.hdynamic
-      || (!htab->fdpic_p && !htab->vxworks_p && h == htab->root.hgot))
+      || (!htab->fdpic_p
+         && htab->root.target_os != is_vxworks
+         && h == htab->root.hgot))
     sym->st_shndx = SHN_ABS;
 
   return TRUE;
@@ -17193,7 +17180,7 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
 
       splt = htab->root.splt;
       BFD_ASSERT (splt != NULL && sdyn != NULL);
-      BFD_ASSERT (htab->symbian_p || sgot != NULL);
+      BFD_ASSERT (sgot != NULL);
 
       dyncon = (Elf32_External_Dyn *) sdyn->contents;
       dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
@@ -17208,35 +17195,22 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
 
          switch (dyn.d_tag)
            {
-             unsigned int type;
-
            default:
-             if (htab->vxworks_p
+             if (htab->root.target_os == is_vxworks
                  && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
                bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
 
            case DT_HASH:
-             name = ".hash";
-             goto get_vma_if_bpabi;
            case DT_STRTAB:
-             name = ".dynstr";
-             goto get_vma_if_bpabi;
            case DT_SYMTAB:
-             name = ".dynsym";
-             goto get_vma_if_bpabi;
            case DT_VERSYM:
-             name = ".gnu.version";
-             goto get_vma_if_bpabi;
            case DT_VERDEF:
-             name = ".gnu.version_d";
-             goto get_vma_if_bpabi;
            case DT_VERNEED:
-             name = ".gnu.version_r";
-             goto get_vma_if_bpabi;
+             break;
 
            case DT_PLTGOT:
-             name = htab->symbian_p ? ".got" : ".got.plt";
+             name = ".got.plt";
              goto get_vma;
            case DT_JMPREL:
              name = RELOC_SECTION (htab, ".plt");
@@ -17249,21 +17223,10 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
                  bfd_set_error (bfd_error_invalid_operation);
                  return FALSE;
                }
-             if (!htab->symbian_p)
-               dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
-             else
-               /* In the BPABI, tags in the PT_DYNAMIC section point
-                  at the file offset, not the memory address, for the
-                  convenience of the post linker.  */
-               dyn.d_un.d_ptr = s->output_section->filepos + s->output_offset;
+             dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
 
-           get_vma_if_bpabi:
-             if (htab->symbian_p)
-               goto get_vma;
-             break;
-
            case DT_PLTRELSZ:
              s = htab->root.srelplt;
              BFD_ASSERT (s != NULL);
@@ -17275,48 +17238,19 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
            case DT_RELASZ:
            case DT_REL:
            case DT_RELA:
-             /* In the BPABI, the DT_REL tag must point at the file
-                offset, not the VMA, of the first relocation
-                section.  So, we use code similar to that in
-                elflink.c, but do not check for SHF_ALLOC on the
-                relocation section, since relocation sections are
-                never allocated under the BPABI.  PLT relocs are also
-                included.  */
-             if (htab->symbian_p)
-               {
-                 unsigned int i;
-                 type = ((dyn.d_tag == DT_REL || dyn.d_tag == DT_RELSZ)
-                         ? SHT_REL : SHT_RELA);
-                 dyn.d_un.d_val = 0;
-                 for (i = 1; i < elf_numsections (output_bfd); i++)
-                   {
-                     Elf_Internal_Shdr *hdr
-                       = elf_elfsections (output_bfd)[i];
-                     if (hdr->sh_type == type)
-                       {
-                         if (dyn.d_tag == DT_RELSZ
-                             || dyn.d_tag == DT_RELASZ)
-                           dyn.d_un.d_val += hdr->sh_size;
-                         else if ((ufile_ptr) hdr->sh_offset
-                                  <= dyn.d_un.d_val - 1)
-                           dyn.d_un.d_val = hdr->sh_offset;
-                       }
-                   }
-                 bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
-               }
              break;
 
            case DT_TLSDESC_PLT:
              s = htab->root.splt;
              dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset
-                               + htab->dt_tlsdesc_plt);
+                               + htab->root.tlsdesc_plt);
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
 
            case DT_TLSDESC_GOT:
              s = htab->root.sgot;
              dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset
-                               + htab->dt_tlsdesc_got);
+                               + htab->root.tlsdesc_got);
              bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
 
@@ -17358,7 +17292,7 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
          got_address = sgot->output_section->vma + sgot->output_offset;
          plt_address = splt->output_section->vma + splt->output_offset;
 
-         if (htab->vxworks_p)
+         if (htab->root.target_os == is_vxworks)
            {
              /* The VxWorks GOT is relocated by the dynamic linker.
                 Therefore, we must emit relocations rather than simply
@@ -17381,7 +17315,7 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
              SWAP_RELOC_OUT (htab) (output_bfd, &rel,
                                     htab->srelplt2->contents);
            }
-         else if (htab->nacl_p)
+         else if (htab->root.target_os == is_nacl)
            arm_nacl_put_plt0 (htab, output_bfd, splt,
                               got_address + 8 - (plt_address + 16));
          else if (using_thumb_only (htab))
@@ -17427,7 +17361,7 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
       if (splt->output_section->owner == output_bfd)
        elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
 
-      if (htab->dt_tlsdesc_plt)
+      if (htab->root.tlsdesc_plt)
        {
          bfd_vma got_address
            = sgot->output_section->vma + sgot->output_offset;
@@ -17437,18 +17371,18 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
            = splt->output_section->vma + splt->output_offset;
 
          arm_put_trampoline (htab, output_bfd,
-                             splt->contents + htab->dt_tlsdesc_plt,
+                             splt->contents + htab->root.tlsdesc_plt,
                              dl_tlsdesc_lazy_trampoline, 6);
 
          bfd_put_32 (output_bfd,
-                     gotplt_address + htab->dt_tlsdesc_got
-                     - (plt_address + htab->dt_tlsdesc_plt)
+                     gotplt_address + htab->root.tlsdesc_got
+                     - (plt_address + htab->root.tlsdesc_plt)
                      - dl_tlsdesc_lazy_trampoline[6],
-                     splt->contents + htab->dt_tlsdesc_plt + 24);
+                     splt->contents + htab->root.tlsdesc_plt + 24);
          bfd_put_32 (output_bfd,
-                     got_address - (plt_address + htab->dt_tlsdesc_plt)
+                     got_address - (plt_address + htab->root.tlsdesc_plt)
                      - dl_tlsdesc_lazy_trampoline[7],
-                     splt->contents + htab->dt_tlsdesc_plt + 24 + 4);
+                     splt->contents + htab->root.tlsdesc_plt + 24 + 4);
        }
 
       if (htab->tls_trampoline)
@@ -17462,7 +17396,7 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
 #endif
        }
 
-      if (htab->vxworks_p
+      if (htab->root.target_os == is_vxworks
          && !bfd_link_pic (info)
          && htab->root.splt->size > 0)
        {
@@ -17492,7 +17426,9 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
        }
     }
 
-  if (htab->nacl_p && htab->root.iplt != NULL && htab->root.iplt->size > 0)
+  if (htab->root.target_os == is_nacl
+      && htab->root.iplt != NULL
+      && htab->root.iplt->size > 0)
     /* NaCl uses a special first entry in .iplt too.  */
     arm_nacl_put_plt0 (htab, output_bfd, htab->root.iplt, 0);
 
@@ -17532,19 +17468,20 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
   return TRUE;
 }
 
-static void
-elf32_arm_post_process_headers (bfd * abfd, struct bfd_link_info * link_info ATTRIBUTE_UNUSED)
+static bfd_boolean
+elf32_arm_init_file_header (bfd *abfd, struct bfd_link_info *link_info)
 {
   Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form.  */
   struct elf32_arm_link_hash_table *globals;
   struct elf_segment_map *m;
 
+  if (!_bfd_elf_init_file_header (abfd, link_info))
+    return FALSE;
+
   i_ehdrp = elf_elfheader (abfd);
 
   if (EF_ARM_EABI_VERSION (i_ehdrp->e_flags) == EF_ARM_EABI_UNKNOWN)
     i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_ARM;
-  else
-    _bfd_elf_post_process_headers (abfd, link_info);
   i_ehdrp->e_ident[EI_ABIVERSION] = ARM_ELF_ABI_VERSION;
 
   if (link_info)
@@ -17586,6 +17523,7 @@ elf32_arm_post_process_headers (bfd * abfd, struct bfd_link_info * link_info ATT
          m->p_flags_valid = 1;
        }
     }
+  return TRUE;
 }
 
 static enum elf_reloc_type_class
@@ -17609,18 +17547,25 @@ elf32_arm_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
 }
 
 static void
-elf32_arm_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
+arm_final_write_processing (bfd *abfd)
 {
   bfd_arm_update_notes (abfd, ARM_NOTE_SECTION);
 }
 
+static bfd_boolean
+elf32_arm_final_write_processing (bfd *abfd)
+{
+  arm_final_write_processing (abfd);
+  return _bfd_elf_final_write_processing (abfd);
+}
+
 /* Return TRUE if this is an unwinding table entry.  */
 
 static bfd_boolean
 is_arm_elf_unwind_section_name (bfd * abfd ATTRIBUTE_UNUSED, const char * name)
 {
-  return (CONST_STRNEQ (name, ELF_STRING_ARM_unwind)
-         || CONST_STRNEQ (name, ELF_STRING_ARM_unwind_once));
+  return (startswith (name, ELF_STRING_ARM_unwind)
+         || startswith (name, ELF_STRING_ARM_unwind_once));
 }
 
 
@@ -17632,7 +17577,7 @@ elf32_arm_fake_sections (bfd * abfd, Elf_Internal_Shdr * hdr, asection * sec)
 {
   const char * name;
 
-  name = bfd_get_section_name (abfd, sec);
+  name = bfd_section_name (sec);
 
   if (is_arm_elf_unwind_section_name (abfd, name))
     {
@@ -17760,14 +17705,7 @@ elf32_arm_output_plt_map_1 (output_arch_syminfo *osi,
                    (osi->info->output_bfd, osi->sec->output_section));
 
   addr = root_plt->offset & -2;
-  if (htab->symbian_p)
-    {
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr))
-       return FALSE;
-      if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 4))
-       return FALSE;
-    }
-  else if (htab->vxworks_p)
+  if (htab->root.target_os == is_vxworks)
     {
       if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr))
        return FALSE;
@@ -17778,7 +17716,7 @@ elf32_arm_output_plt_map_1 (output_arch_syminfo *osi,
       if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 20))
        return FALSE;
     }
-  else if (htab->nacl_p)
+  else if (htab->root.target_os == is_nacl)
     {
       if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr))
        return FALSE;
@@ -17790,15 +17728,15 @@ elf32_arm_output_plt_map_1 (output_arch_syminfo *osi,
        : ARM_MAP_ARM;
 
       if (elf32_arm_plt_needs_thumb_stub_p (osi->info, arm_plt))
-        if (!elf32_arm_output_map_sym (osi, ARM_MAP_THUMB, addr - 4))
-          return FALSE;
+       if (!elf32_arm_output_map_sym (osi, ARM_MAP_THUMB, addr - 4))
+         return FALSE;
       if (!elf32_arm_output_map_sym (osi, type, addr))
-        return FALSE;
+       return FALSE;
       if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 16))
-        return FALSE;
+       return FALSE;
       if (htab->plt_entry_size == 4 * ARRAY_SIZE(elf32_arm_fdpic_plt_entry))
-        if (!elf32_arm_output_map_sym (osi, type, addr + 24))
-          return FALSE;
+       if (!elf32_arm_output_map_sym (osi, type, addr + 24))
+         return FALSE;
     }
   else if (using_thumb_only (htab))
     {
@@ -18138,9 +18076,8 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
       osi.sec_shndx = (_bfd_elf_section_from_bfd_section
                       (output_bfd, osi.sec->output_section));
 
-      /* Output mapping symbols for the plt header.  SymbianOS does not have a
-        plt header.  */
-      if (htab->vxworks_p)
+      /* Output mapping symbols for the plt header.  */
+      if (htab->root.target_os == is_vxworks)
        {
          /* VxWorks shared libraries have no PLT header.  */
          if (!bfd_link_pic (info))
@@ -18151,7 +18088,7 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
                return FALSE;
            }
        }
-      else if (htab->nacl_p)
+      else if (htab->root.target_os == is_nacl)
        {
          if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, 0))
            return FALSE;
@@ -18165,7 +18102,7 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
          if (!elf32_arm_output_map_sym (&osi, ARM_MAP_THUMB, 16))
            return FALSE;
        }
-      else if (!htab->symbian_p && !htab->fdpic_p)
+      else if (!htab->fdpic_p)
        {
          if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, 0))
            return FALSE;
@@ -18175,7 +18112,9 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
 #endif
        }
     }
-  if (htab->nacl_p && htab->root.iplt && htab->root.iplt->size > 0)
+  if (htab->root.target_os == is_nacl
+      && htab->root.iplt
+      && htab->root.iplt->size > 0)
     {
       /* NaCl uses a special first entry in .iplt too.  */
       osi.sec = htab->root.iplt;
@@ -18208,14 +18147,15 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
            }
        }
     }
-  if (htab->dt_tlsdesc_plt != 0)
+  if (htab->root.tlsdesc_plt != 0)
     {
       /* Mapping symbols for the lazy tls trampoline.  */
-      if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, htab->dt_tlsdesc_plt))
+      if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM,
+                                    htab->root.tlsdesc_plt))
        return FALSE;
 
       if (!elf32_arm_output_map_sym (&osi, ARM_MAP_DATA,
-                                    htab->dt_tlsdesc_plt + 24))
+                                    htab->root.tlsdesc_plt + 24))
        return FALSE;
     }
   if (htab->tls_trampoline != 0)
@@ -18256,6 +18196,8 @@ elf32_arm_filter_cmse_symbols (bfd *abfd ATTRIBUTE_UNUSED,
 
   maxnamelen = 128;
   cmse_name = (char *) bfd_malloc (maxnamelen);
+  BFD_ASSERT (cmse_name);
+
   for (src_count = 0; src_count < symcount; src_count++)
     {
       struct elf32_arm_link_hash_entry *cmse_hash;
@@ -18290,9 +18232,6 @@ elf32_arm_filter_cmse_symbols (bfd *abfd ATTRIBUTE_UNUSED,
          || cmse_hash->root.type != STT_FUNC)
        continue;
 
-      if (!ARM_GET_SYM_CMSE_SPCL (cmse_hash->root.target_internal))
-       continue;
-
       syms[dst_count++] = sym;
     }
   free (cmse_name);
@@ -18334,7 +18273,7 @@ elf32_arm_new_section_hook (bfd *abfd, asection *sec)
   if (!sec->used_by_bfd)
     {
       _arm_elf_section_data *sdata;
-      bfd_size_type amt = sizeof (*sdata);
+      size_t amt = sizeof (*sdata);
 
       sdata = (_arm_elf_section_data *) bfd_zalloc (abfd, amt);
       if (sdata == NULL)
@@ -19110,7 +19049,7 @@ stm32l4xx_create_replacing_stub_vldm (struct elf32_arm_link_hash_table * htab,
                                      const bfd_byte *const initial_insn_addr,
                                      bfd_byte *const base_stub_contents)
 {
-  int num_words = ((unsigned int) initial_insn << 24) >> 24;
+  int num_words = initial_insn & 0xff;
   bfd_byte *current_stub_contents = base_stub_contents;
 
   BFD_ASSERT (is_thumb2_vldm (initial_insn));
@@ -19454,6 +19393,8 @@ elf32_arm_write_section (bfd *output_bfd,
       unsigned int in_index, out_index;
       bfd_vma add_to_offsets = 0;
 
+      if (edited_contents == NULL)
+       return FALSE;
       for (in_index = 0, out_index = 0; in_index * 8 < input_size || edit_node;)
        {
          if (edit_node)
@@ -19615,9 +19556,6 @@ elf32_arm_swap_symbol_in (bfd * abfd,
                          const void *pshn,
                          Elf_Internal_Sym *dst)
 {
-  Elf_Internal_Shdr *symtab_hdr;
-  const char *name = NULL;
-
   if (!bfd_elf32_swap_symbol_in (abfd, psrc, pshn, dst))
     return FALSE;
   dst->st_target_internal = 0;
@@ -19646,13 +19584,6 @@ elf32_arm_swap_symbol_in (bfd * abfd,
   else
     ARM_SET_SYM_BRANCH_TYPE (dst->st_target_internal, ST_BRANCH_UNKNOWN);
 
-  /* Mark CMSE special symbols.  */
-  symtab_hdr = & elf_symtab_hdr (abfd);
-  if (symtab_hdr->sh_size)
-    name = bfd_elf_sym_name (abfd, symtab_hdr, dst, NULL);
-  if (name && CONST_STRNEQ (name, CMSE_PREFIX))
-    ARM_SET_SYM_CMSE_SPCL (dst->st_target_internal);
-
   return TRUE;
 }
 
@@ -19756,7 +19687,7 @@ elf32_arm_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
   if (elf32_arm_hash_table (info) == NULL)
     return FALSE;
 
-  if (elf32_arm_hash_table (info)->vxworks_p
+  if (elf32_arm_hash_table (info)->root.target_os == is_vxworks
       && !elf_vxworks_add_symbol_hook (abfd, info, sym, namep,
                                       flagsp, secp, valp))
     return FALSE;
@@ -19995,10 +19926,10 @@ elf32_arm_get_synthetic_symtab (bfd *abfd,
 }
 
 static bfd_boolean
-elf32_arm_section_flags (flagword *flags, const Elf_Internal_Shdr * hdr)
+elf32_arm_section_flags (const Elf_Internal_Shdr *hdr)
 {
   if (hdr->sh_flags & SHF_ARM_PURECODE)
-    *flags |= SEC_ELF_PURECODE;
+    hdr->bfd_section->flags |= SEC_ELF_PURECODE;
   return TRUE;
 }
 
@@ -20171,7 +20102,6 @@ elf32_arm_backend_symbol_processing (bfd *abfd, asymbol *sym)
 #define bfd_elf32_bfd_link_hash_table_create   elf32_arm_link_hash_table_create
 #define bfd_elf32_bfd_reloc_type_lookup                elf32_arm_reloc_type_lookup
 #define bfd_elf32_bfd_reloc_name_lookup                elf32_arm_reloc_name_lookup
-#define bfd_elf32_find_nearest_line            elf32_arm_find_nearest_line
 #define bfd_elf32_find_inliner_info            elf32_arm_find_inliner_info
 #define bfd_elf32_new_section_hook             elf32_arm_new_section_hook
 #define bfd_elf32_bfd_is_target_special_symbol elf32_arm_is_target_special_symbol
@@ -20179,6 +20109,7 @@ elf32_arm_backend_symbol_processing (bfd *abfd, asymbol *sym)
 #define bfd_elf32_get_synthetic_symtab elf32_arm_get_synthetic_symtab
 
 #define elf_backend_get_symbol_type            elf32_arm_get_symbol_type
+#define elf_backend_maybe_function_sym         elf32_arm_maybe_function_sym
 #define elf_backend_gc_mark_hook               elf32_arm_gc_mark_hook
 #define elf_backend_gc_mark_extra_sections     elf32_arm_gc_mark_extra_sections
 #define elf_backend_check_relocs               elf32_arm_check_relocs
@@ -20192,7 +20123,7 @@ elf32_arm_backend_symbol_processing (bfd *abfd, asymbol *sym)
 #define elf_backend_size_dynamic_sections      elf32_arm_size_dynamic_sections
 #define elf_backend_always_size_sections       elf32_arm_always_size_sections
 #define elf_backend_init_index_section         _bfd_elf_init_2_index_sections
-#define elf_backend_post_process_headers       elf32_arm_post_process_headers
+#define elf_backend_init_file_header           elf32_arm_init_file_header
 #define elf_backend_reloc_type_class           elf32_arm_reloc_type_class
 #define elf_backend_object_p                   elf32_arm_object_p
 #define elf_backend_fake_sections              elf32_arm_fake_sections
@@ -20268,8 +20199,6 @@ elf32_arm_nacl_link_hash_table_create (bfd *abfd)
       struct elf32_arm_link_hash_table *htab
        = (struct elf32_arm_link_hash_table *) ret;
 
-      htab->nacl_p = 1;
-
       htab->plt_header_size = 4 * ARRAY_SIZE (elf32_arm_nacl_plt0_entry);
       htab->plt_entry_size = 4 * ARRAY_SIZE (elf32_arm_nacl_plt_entry);
     }
@@ -20287,11 +20216,11 @@ elf32_arm_nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
          && nacl_modify_segment_map (abfd, info));
 }
 
-static void
-elf32_arm_nacl_final_write_processing (bfd *abfd, bfd_boolean linker)
+static bfd_boolean
+elf32_arm_nacl_final_write_processing (bfd *abfd)
 {
-  elf32_arm_final_write_processing (abfd, linker);
-  nacl_final_write_processing (abfd, linker);
+  arm_final_write_processing (abfd);
+  return nacl_final_write_processing (abfd);
 }
 
 static bfd_vma
@@ -20312,8 +20241,8 @@ elf32_arm_nacl_plt_sym_val (bfd_vma i, const asection *plt,
 #define elf_backend_plt_alignment              4
 #undef elf_backend_modify_segment_map
 #define        elf_backend_modify_segment_map          elf32_arm_nacl_modify_segment_map
-#undef elf_backend_modify_program_headers
-#define        elf_backend_modify_program_headers      nacl_modify_program_headers
+#undef elf_backend_modify_headers
+#define        elf_backend_modify_headers              nacl_modify_headers
 #undef  elf_backend_final_write_processing
 #define elf_backend_final_write_processing     elf32_arm_nacl_final_write_processing
 #undef bfd_elf32_get_synthetic_symtab
@@ -20324,6 +20253,8 @@ elf32_arm_nacl_plt_sym_val (bfd_vma i, const asection *plt,
 #undef ELF_MINPAGESIZE
 #undef ELF_COMMONPAGESIZE
 
+#undef ELF_TARGET_OS
+#define ELF_TARGET_OS                          is_nacl
 
 #include "elf32-target.h"
 
@@ -20331,7 +20262,7 @@ elf32_arm_nacl_plt_sym_val (bfd_vma i, const asection *plt,
 #undef elf_backend_plt_alignment
 #undef elf_backend_modify_segment_map
 #define elf_backend_modify_segment_map         elf32_arm_modify_segment_map
-#undef elf_backend_modify_program_headers
+#undef elf_backend_modify_headers
 #undef  elf_backend_final_write_processing
 #define elf_backend_final_write_processing     elf32_arm_final_write_processing
 #undef ELF_MINPAGESIZE
@@ -20401,11 +20332,13 @@ elf32_arm_fdpic_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED,
 #define elf32_bed                              elf32_arm_fdpic_bed
 
 #undef  bfd_elf32_bfd_link_hash_table_create
-#define bfd_elf32_bfd_link_hash_table_create   elf32_arm_fdpic_link_hash_table_create
+#define bfd_elf32_bfd_link_hash_table_create   elf32_arm_fdpic_link_hash_table_create
 
 #undef elf_backend_omit_section_dynsym
 #define elf_backend_omit_section_dynsym                elf32_arm_fdpic_omit_section_dynsym
 
+#undef ELF_TARGET_OS
+
 #include "elf32-target.h"
 
 #undef elf_match_priority
@@ -20437,16 +20370,15 @@ elf32_arm_vxworks_link_hash_table_create (bfd *abfd)
       struct elf32_arm_link_hash_table *htab
        = (struct elf32_arm_link_hash_table *) ret;
       htab->use_rel = 0;
-      htab->vxworks_p = 1;
     }
   return ret;
 }
 
-static void
-elf32_arm_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
+static bfd_boolean
+elf32_arm_vxworks_final_write_processing (bfd *abfd)
 {
-  elf32_arm_final_write_processing (abfd, linker);
-  elf_vxworks_final_write_processing (abfd, linker);
+  arm_final_write_processing (abfd);
+  return elf_vxworks_final_write_processing (abfd);
 }
 
 #undef  elf32_bed
@@ -20469,6 +20401,8 @@ elf32_arm_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
 #define elf_backend_want_plt_sym       1
 #undef  ELF_MAXPAGESIZE
 #define ELF_MAXPAGESIZE                        0x1000
+#undef ELF_TARGET_OS
+#define ELF_TARGET_OS                  is_vxworks
 
 #include "elf32-target.h"
 
@@ -20568,7 +20502,7 @@ elf32_arm_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
          if (strcmp (sec->name, ".glue_7")
              && strcmp (sec->name, ".glue_7t"))
            {
-             if ((bfd_get_section_flags (ibfd, sec)
+             if ((bfd_section_flags (sec)
                   & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
                  == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
                only_data_sections = FALSE;
@@ -20695,166 +20629,3 @@ elf32_arm_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
 
   return flags_compatible;
 }
-
-
-/* Symbian OS Targets.  */
-
-#undef TARGET_LITTLE_SYM
-#define TARGET_LITTLE_SYM              arm_elf32_symbian_le_vec
-#undef TARGET_LITTLE_NAME
-#define TARGET_LITTLE_NAME             "elf32-littlearm-symbian"
-#undef TARGET_BIG_SYM
-#define TARGET_BIG_SYM                 arm_elf32_symbian_be_vec
-#undef TARGET_BIG_NAME
-#define TARGET_BIG_NAME                        "elf32-bigarm-symbian"
-
-/* Like elf32_arm_link_hash_table_create -- but overrides
-   appropriately for Symbian OS.  */
-
-static struct bfd_link_hash_table *
-elf32_arm_symbian_link_hash_table_create (bfd *abfd)
-{
-  struct bfd_link_hash_table *ret;
-
-  ret = elf32_arm_link_hash_table_create (abfd);
-  if (ret)
-    {
-      struct elf32_arm_link_hash_table *htab
-       = (struct elf32_arm_link_hash_table *)ret;
-      /* There is no PLT header for Symbian OS.  */
-      htab->plt_header_size = 0;
-      /* The PLT entries are each one instruction and one word.  */
-      htab->plt_entry_size = 4 * ARRAY_SIZE (elf32_arm_symbian_plt_entry);
-      htab->symbian_p = 1;
-      /* Symbian uses armv5t or above, so use_blx is always true.  */
-      htab->use_blx = 1;
-      htab->root.is_relocatable_executable = 1;
-    }
-  return ret;
-}
-
-static const struct bfd_elf_special_section
-elf32_arm_symbian_special_sections[] =
-{
-  /* In a BPABI executable, the dynamic linking sections do not go in
-     the loadable read-only segment.  The post-linker may wish to
-     refer to these sections, but they are not part of the final
-     program image.  */
-  { STRING_COMMA_LEN (".dynamic"),      0, SHT_DYNAMIC,  0 },
-  { STRING_COMMA_LEN (".dynstr"),       0, SHT_STRTAB,   0 },
-  { STRING_COMMA_LEN (".dynsym"),       0, SHT_DYNSYM,   0 },
-  { STRING_COMMA_LEN (".got"),          0, SHT_PROGBITS, 0 },
-  { STRING_COMMA_LEN (".hash"),                 0, SHT_HASH,     0 },
-  /* These sections do not need to be writable as the SymbianOS
-     postlinker will arrange things so that no dynamic relocation is
-     required.  */
-  { STRING_COMMA_LEN (".init_array"),   0, SHT_INIT_ARRAY,    SHF_ALLOC },
-  { STRING_COMMA_LEN (".fini_array"),   0, SHT_FINI_ARRAY,    SHF_ALLOC },
-  { STRING_COMMA_LEN (".preinit_array"), 0, SHT_PREINIT_ARRAY, SHF_ALLOC },
-  { NULL,                            0, 0, 0,                 0 }
-};
-
-static void
-elf32_arm_symbian_begin_write_processing (bfd *abfd,
-                                         struct bfd_link_info *link_info)
-{
-  /* BPABI objects are never loaded directly by an OS kernel; they are
-     processed by a postlinker first, into an OS-specific format.  If
-     the D_PAGED bit is set on the file, BFD will align segments on
-     page boundaries, so that an OS can directly map the file.  With
-     BPABI objects, that just results in wasted space.  In addition,
-     because we clear the D_PAGED bit, map_sections_to_segments will
-     recognize that the program headers should not be mapped into any
-     loadable segment.  */
-  abfd->flags &= ~D_PAGED;
-  elf32_arm_begin_write_processing (abfd, link_info);
-}
-
-static bfd_boolean
-elf32_arm_symbian_modify_segment_map (bfd *abfd,
-                                     struct bfd_link_info *info)
-{
-  struct elf_segment_map *m;
-  asection *dynsec;
-
-  /* BPABI shared libraries and executables should have a PT_DYNAMIC
-     segment.  However, because the .dynamic section is not marked
-     with SEC_LOAD, the generic ELF code will not create such a
-     segment.  */
-  dynsec = bfd_get_section_by_name (abfd, ".dynamic");
-  if (dynsec)
-    {
-      for (m = elf_seg_map (abfd); m != NULL; m = m->next)
-       if (m->p_type == PT_DYNAMIC)
-         break;
-
-      if (m == NULL)
-       {
-         m = _bfd_elf_make_dynamic_segment (abfd, dynsec);
-         m->next = elf_seg_map (abfd);
-         elf_seg_map (abfd) = m;
-       }
-    }
-
-  /* Also call the generic arm routine.  */
-  return elf32_arm_modify_segment_map (abfd, info);
-}
-
-/* Return address for Ith PLT stub in section PLT, for relocation REL
-   or (bfd_vma) -1 if it should not be included.  */
-
-static bfd_vma
-elf32_arm_symbian_plt_sym_val (bfd_vma i, const asection *plt,
-                              const arelent *rel ATTRIBUTE_UNUSED)
-{
-  return plt->vma + 4 * ARRAY_SIZE (elf32_arm_symbian_plt_entry) * i;
-}
-
-#undef  elf32_bed
-#define elf32_bed elf32_arm_symbian_bed
-
-/* The dynamic sections are not allocated on SymbianOS; the postlinker
-   will process them and then discard them.  */
-#undef  ELF_DYNAMIC_SEC_FLAGS
-#define ELF_DYNAMIC_SEC_FLAGS \
-  (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED)
-
-#undef elf_backend_emit_relocs
-
-#undef  bfd_elf32_bfd_link_hash_table_create
-#define bfd_elf32_bfd_link_hash_table_create   elf32_arm_symbian_link_hash_table_create
-#undef  elf_backend_special_sections
-#define elf_backend_special_sections           elf32_arm_symbian_special_sections
-#undef  elf_backend_begin_write_processing
-#define elf_backend_begin_write_processing     elf32_arm_symbian_begin_write_processing
-#undef  elf_backend_final_write_processing
-#define elf_backend_final_write_processing     elf32_arm_final_write_processing
-
-#undef  elf_backend_modify_segment_map
-#define elf_backend_modify_segment_map elf32_arm_symbian_modify_segment_map
-
-/* There is no .got section for BPABI objects, and hence no header.  */
-#undef  elf_backend_got_header_size
-#define elf_backend_got_header_size 0
-
-/* Similarly, there is no .got.plt section.  */
-#undef  elf_backend_want_got_plt
-#define elf_backend_want_got_plt 0
-
-#undef  elf_backend_plt_sym_val
-#define elf_backend_plt_sym_val                elf32_arm_symbian_plt_sym_val
-
-#undef  elf_backend_may_use_rel_p
-#define elf_backend_may_use_rel_p      1
-#undef  elf_backend_may_use_rela_p
-#define elf_backend_may_use_rela_p     0
-#undef  elf_backend_default_use_rela_p
-#define elf_backend_default_use_rela_p 0
-#undef  elf_backend_want_plt_sym
-#define elf_backend_want_plt_sym       0
-#undef  elf_backend_dtrel_excludes_plt
-#define elf_backend_dtrel_excludes_plt 0
-#undef  ELF_MAXPAGESIZE
-#define ELF_MAXPAGESIZE                        0x8000
-
-#include "elf32-target.h"
This page took 0.076739 seconds and 4 git commands to generate.