Add -Wshadow to the gcc command line options used when compiling the binutils.
[deliverable/binutils-gdb.git] / bfd / elf32-arm.c
index cd40eefbf5c52e3d108ca01b5e0666fab066fb65..1921780edb2ffdd7afe53791a73c5ed4a0e8dc1f 100644 (file)
@@ -61,8 +61,6 @@
 #define ARM_ELF_ABI_VERSION            0
 #define ARM_ELF_OS_ABI_VERSION         ELFOSABI_ARM
 
-static struct elf_backend_data elf32_arm_vxworks_bed;
-
 static bfd_boolean elf32_arm_write_section (bfd *output_bfd,
                                            struct bfd_link_info *link_info,
                                            asection *sec,
@@ -2228,12 +2226,14 @@ static const insn_sequence elf32_arm_stub_a8_veneer_blx[] =
 enum elf32_arm_stub_type {
   arm_stub_none,
   DEF_STUBS
+  /* Note the first a8_veneer type */
+  arm_stub_a8_veneer_lwm = arm_stub_a8_veneer_b_cond
 };
 #undef DEF_STUB
 
 typedef struct
 {
-  const insn_sequence* template;
+  const insn_sequence* template_sequence;
   int template_size;
 } stub_def;
 
@@ -2521,6 +2521,17 @@ struct elf32_arm_link_hash_entry
   ((struct elf32_arm_stub_hash_entry *) \
    bfd_hash_lookup ((table), (string), (create), (copy)))
 
+/* Array to keep track of which stub sections have been created, and
+   information on stub grouping.  */
+struct map_stub
+{
+  /* This is the section to which stubs in the group will be
+     attached.  */
+  asection *link_sec;
+  /* The stub section.  */
+  asection *stub_sec;
+};
+
 /* ARM ELF linker hash table.  */
 struct elf32_arm_link_hash_table
 {
@@ -2636,14 +2647,7 @@ struct elf32_arm_link_hash_table
 
   /* Array to keep track of which stub sections have been created, and
      information on stub grouping.  */
-  struct map_stub
-  {
-    /* This is the section to which stubs in the group will be
-       attached.  */
-    asection *link_sec;
-    /* The stub section.  */
-    asection *stub_sec;
-  } *stub_group;
+  struct map_stub *stub_group;
 
   /* Assorted information used by elf32_arm_size_stubs.  */
   unsigned int bfd_count;
@@ -2664,7 +2668,8 @@ elf32_arm_link_hash_newfunc (struct bfd_hash_entry * entry,
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
   if (ret == NULL)
-    ret = bfd_hash_allocate (table, sizeof (struct elf32_arm_link_hash_entry));
+    ret = (struct elf32_arm_link_hash_entry *)
+        bfd_hash_allocate (table, sizeof (struct elf32_arm_link_hash_entry));
   if (ret == NULL)
     return (struct bfd_hash_entry *) ret;
 
@@ -2698,8 +2703,8 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
      subclass.  */
   if (entry == NULL)
     {
-      entry = bfd_hash_allocate (table,
-                                sizeof (struct elf32_arm_stub_hash_entry));
+      entry = (struct bfd_hash_entry *)
+          bfd_hash_allocate (table, sizeof (struct elf32_arm_stub_hash_entry));
       if (entry == NULL)
        return entry;
     }
@@ -2716,12 +2721,15 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
       eh->stub_offset = 0;
       eh->target_value = 0;
       eh->target_section = NULL;
+      eh->target_addend = 0;
+      eh->orig_insn = 0;
       eh->stub_type = arm_stub_none;
       eh->stub_size = 0;
       eh->stub_template = NULL;
       eh->stub_template_size = 0;
       eh->h = NULL;
       eh->id_sec = NULL;
+      eh->output_name = NULL;
     }
 
   return entry;
@@ -2877,7 +2885,7 @@ 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);
 
-  ret = bfd_malloc (amt);
+  ret = (struct elf32_arm_link_hash_table *) bfd_malloc (amt);
   if (ret == NULL)
     return NULL;
 
@@ -2963,7 +2971,7 @@ using_thumb_only (struct elf32_arm_link_hash_table *globals)
                                       Tag_CPU_arch);
   int profile;
 
-  if (arch != TAG_CPU_ARCH_V7)
+  if (arch != TAG_CPU_ARCH_V7 && arch != TAG_CPU_ARCH_V7E_M)
     return FALSE;
 
   profile = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
@@ -2982,6 +2990,28 @@ using_thumb2 (struct elf32_arm_link_hash_table *globals)
   return arch == TAG_CPU_ARCH_V6T2 || arch >= TAG_CPU_ARCH_V7;
 }
 
+/* Determine what kind of NOPs are available.  */
+
+static bfd_boolean
+arch_has_arm_nop (struct elf32_arm_link_hash_table *globals)
+{
+  const int arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
+                                            Tag_CPU_arch);
+  return arch == TAG_CPU_ARCH_V6T2
+        || arch == TAG_CPU_ARCH_V6K
+        || arch == TAG_CPU_ARCH_V7
+        || arch == TAG_CPU_ARCH_V7E_M;
+}
+
+static bfd_boolean
+arch_has_thumb2_nop (struct elf32_arm_link_hash_table *globals)
+{
+  const int arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
+                                            Tag_CPU_arch);
+  return (arch == TAG_CPU_ARCH_V6T2 || arch == TAG_CPU_ARCH_V7
+         || arch == TAG_CPU_ARCH_V7E_M);
+}
+
 static bfd_boolean
 arm_stub_is_thumb (enum elf32_arm_stub_type stub_type)
 {
@@ -3223,7 +3253,7 @@ elf32_arm_stub_name (const asection *input_section,
   if (hash)
     {
       len = 8 + 1 + strlen (hash->root.root.root.string) + 1 + 8 + 1;
-      stub_name = bfd_malloc (len);
+      stub_name = (char *) bfd_malloc (len);
       if (stub_name != NULL)
        sprintf (stub_name, "%08x_%s+%x",
                 input_section->id & 0xffffffff,
@@ -3233,7 +3263,7 @@ elf32_arm_stub_name (const asection *input_section,
   else
     {
       len = 8 + 1 + 8 + 1 + 8 + 1 + 8 + 1;
-      stub_name = bfd_malloc (len);
+      stub_name = (char *) bfd_malloc (len);
       if (stub_name != NULL)
        sprintf (stub_name, "%08x_%x:%x+%x",
                 input_section->id & 0xffffffff,
@@ -3318,7 +3348,7 @@ elf32_arm_create_or_find_stub_sec (asection **link_sec_p, asection *section,
 
          namelen = strlen (link_sec->name);
          len = namelen + sizeof (STUB_SUFFIX);
-         s_name = bfd_alloc (htab->stub_bfd, len);
+         s_name = (char *) bfd_alloc (htab->stub_bfd, len);
          if (s_name == NULL)
            return NULL;
 
@@ -3418,7 +3448,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
   bfd_vma sym_value;
   int template_size;
   int size;
-  const insn_sequence *template;
+  const insn_sequence *template_sequence;
   int i;
   struct elf32_arm_link_hash_table * globals;
   int stub_reloc_idx[MAXRELOCS] = {-1, -1};
@@ -3434,6 +3464,12 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
   htab = elf32_arm_hash_table (info);
   stub_sec = stub_entry->stub_sec;
 
+  if ((htab->fix_cortex_a8 < 0)
+      != (stub_entry->stub_type >= arm_stub_a8_veneer_lwm))
+    /* We have to do the a8 fixes last, as they are less aligned than
+       the other veneers.  */
+    return TRUE;
+  
   /* Make a note of the offset within the stubs for this entry.  */
   stub_entry->stub_offset = stub_sec->size;
   loc = stub_sec->contents + stub_entry->stub_offset;
@@ -3449,18 +3485,18 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
               + stub_entry->target_section->output_offset
               + stub_entry->target_section->output_section->vma);
 
-  template = stub_entry->stub_template;
+  template_sequence = stub_entry->stub_template;
   template_size = stub_entry->stub_template_size;
 
   size = 0;
   for (i = 0; i < template_size; i++)
     {
-      switch (template[i].type)
+      switch (template_sequence[i].type)
        {
        case THUMB16_TYPE:
          {
-           bfd_vma data = template[i].data;
-           if (template[i].reloc_addend != 0)
+           bfd_vma data = (bfd_vma) template_sequence[i].data;
+           if (template_sequence[i].reloc_addend != 0)
              {
                 /* We've borrowed the reloc_addend field to mean we should
                    insert a condition code into this (Thumb-1 branch)
@@ -3474,11 +3510,12 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
          break;
 
        case THUMB32_TYPE:
-          put_thumb_insn (globals, stub_bfd, (template[i].data >> 16) & 0xffff,
+          put_thumb_insn (globals, stub_bfd,
+                          (template_sequence[i].data >> 16) & 0xffff,
                           loc + size);
-          put_thumb_insn (globals, stub_bfd, template[i].data & 0xffff,
+          put_thumb_insn (globals, stub_bfd, template_sequence[i].data & 0xffff,
                           loc + size + 2);
-          if (template[i].r_type != R_ARM_NONE)
+          if (template_sequence[i].r_type != R_ARM_NONE)
             {
               stub_reloc_idx[nrelocs] = i;
               stub_reloc_offset[nrelocs++] = size;
@@ -3487,10 +3524,11 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
           break;
 
        case ARM_TYPE:
-         put_arm_insn (globals, stub_bfd, template[i].data, loc + size);
+         put_arm_insn (globals, stub_bfd, template_sequence[i].data,
+                        loc + size);
          /* Handle cases where the target is encoded within the
             instruction.  */
-         if (template[i].r_type == R_ARM_JUMP24)
+         if (template_sequence[i].r_type == R_ARM_JUMP24)
            {
              stub_reloc_idx[nrelocs] = i;
              stub_reloc_offset[nrelocs++] = size;
@@ -3499,7 +3537,7 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
          break;
 
        case DATA_TYPE:
-         bfd_put_32 (stub_bfd, template[i].data, loc + size);
+         bfd_put_32 (stub_bfd, template_sequence[i].data, loc + size);
          stub_reloc_idx[nrelocs] = i;
          stub_reloc_offset[nrelocs++] = size;
          size += 4;
@@ -3526,22 +3564,23 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
   BFD_ASSERT (nrelocs != 0 && nrelocs <= MAXRELOCS);
 
   for (i = 0; i < nrelocs; i++)
-    if (template[stub_reloc_idx[i]].r_type == R_ARM_THM_JUMP24
-       || template[stub_reloc_idx[i]].r_type == R_ARM_THM_JUMP19
-       || template[stub_reloc_idx[i]].r_type == R_ARM_THM_CALL
-       || template[stub_reloc_idx[i]].r_type == R_ARM_THM_XPC22)
+    if (template_sequence[stub_reloc_idx[i]].r_type == R_ARM_THM_JUMP24
+       || template_sequence[stub_reloc_idx[i]].r_type == R_ARM_THM_JUMP19
+       || template_sequence[stub_reloc_idx[i]].r_type == R_ARM_THM_CALL
+       || template_sequence[stub_reloc_idx[i]].r_type == R_ARM_THM_XPC22)
       {
        Elf_Internal_Rela rel;
        bfd_boolean unresolved_reloc;
        char *error_message;
        int sym_flags
-         = (template[stub_reloc_idx[i]].r_type != R_ARM_THM_XPC22)
+         = (template_sequence[stub_reloc_idx[i]].r_type != R_ARM_THM_XPC22)
            ? STT_ARM_TFUNC : 0;
        bfd_vma points_to = sym_value + stub_entry->target_addend;
 
        rel.r_offset = stub_entry->stub_offset + stub_reloc_offset[i];
-       rel.r_info = ELF32_R_INFO (0, template[stub_reloc_idx[i]].r_type);
-       rel.r_addend = template[stub_reloc_idx[i]].reloc_addend;
+       rel.r_info = ELF32_R_INFO (0,
+                                   template_sequence[stub_reloc_idx[i]].r_type);
+       rel.r_addend = template_sequence[stub_reloc_idx[i]].reloc_addend;
 
        if (stub_entry->stub_type == arm_stub_a8_veneer_b_cond && i == 0)
          /* The first relocation in the elf32_arm_stub_a8_veneer_b_cond[]
@@ -3549,24 +3588,27 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
             branch.  */
          points_to = sym_value;
 
+       /* There may be unintended consequences if this is not true.  */
+       BFD_ASSERT (stub_entry->h == NULL);
+
        /* Note: _bfd_final_link_relocate doesn't handle these relocations
           properly.  We should probably use this function unconditionally,
           rather than only for certain relocations listed in the enclosing
           conditional, for the sake of consistency.  */
        elf32_arm_final_link_relocate (elf32_arm_howto_from_type
-           (template[stub_reloc_idx[i]].r_type),
+           (template_sequence[stub_reloc_idx[i]].r_type),
          stub_bfd, info->output_bfd, stub_sec, stub_sec->contents, &rel,
          points_to, info, stub_entry->target_section, "", sym_flags,
-         (struct elf_link_hash_entry *) stub_entry, &unresolved_reloc,
+         (struct elf_link_hash_entry *) stub_entry->h, &unresolved_reloc,
          &error_message);
       }
     else
       {
        _bfd_final_link_relocate (elf32_arm_howto_from_type
-           (template[stub_reloc_idx[i]].r_type), stub_bfd, stub_sec,
+           (template_sequence[stub_reloc_idx[i]].r_type), stub_bfd, stub_sec,
          stub_sec->contents, stub_entry->stub_offset + stub_reloc_offset[i],
          sym_value + stub_entry->target_addend,
-         template[stub_reloc_idx[i]].reloc_addend);
+         template_sequence[stub_reloc_idx[i]].reloc_addend);
       }
 
   return TRUE;
@@ -3581,17 +3623,17 @@ find_stub_size_and_template (enum elf32_arm_stub_type stub_type,
                             const insn_sequence **stub_template,
                             int *stub_template_size)
 {
-  const insn_sequence *template = NULL;
+  const insn_sequence *template_sequence = NULL;
   int template_size = 0, i;
   unsigned int size;
 
-  template = stub_definitions[stub_type].template;
+  template_sequence = stub_definitions[stub_type].template_sequence;
   template_size = stub_definitions[stub_type].template_size;
 
   size = 0;
   for (i = 0; i < template_size; i++)
     {
-      switch (template[i].type)
+      switch (template_sequence[i].type)
        {
        case THUMB16_TYPE:
          size += 2;
@@ -3610,7 +3652,7 @@ find_stub_size_and_template (enum elf32_arm_stub_type stub_type,
     }
 
   if (stub_template)
-    *stub_template = template;
+    *stub_template = template_sequence;
 
   if (stub_template_size)
     *stub_template_size = template_size;
@@ -3627,7 +3669,7 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
 {
   struct elf32_arm_stub_hash_entry *stub_entry;
   struct elf32_arm_link_hash_table *htab;
-  const insn_sequence *template;
+  const insn_sequence *template_sequence;
   int template_size, size;
 
   /* Massage our args to the form they really have.  */
@@ -3637,11 +3679,11 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
   BFD_ASSERT((stub_entry->stub_type > arm_stub_none)
             && stub_entry->stub_type < ARRAY_SIZE(stub_definitions));
 
-  size = find_stub_size_and_template (stub_entry->stub_type, &template,
+  size = find_stub_size_and_template (stub_entry->stub_type, &template_sequence,
                                      &template_size);
 
   stub_entry->stub_size = size;
-  stub_entry->stub_template = template;
+  stub_entry->stub_template = template_sequence;
   stub_entry->stub_template_size = template_size;
 
   size = (size + 7) & ~7;
@@ -3688,7 +3730,7 @@ elf32_arm_setup_section_lists (bfd *output_bfd,
   htab->bfd_count = bfd_count;
 
   amt = sizeof (struct map_stub) * (top_id + 1);
-  htab->stub_group = bfd_zmalloc (amt);
+  htab->stub_group = (struct map_stub *) bfd_zmalloc (amt);
   if (htab->stub_group == NULL)
     return -1;
 
@@ -3705,7 +3747,7 @@ elf32_arm_setup_section_lists (bfd *output_bfd,
 
   htab->top_index = top_index;
   amt = sizeof (asection *) * (top_index + 1);
-  input_list = bfd_malloc (amt);
+  input_list = (asection **) bfd_malloc (amt);
   htab->input_list = input_list;
   if (input_list == NULL)
     return -1;
@@ -3743,7 +3785,7 @@ elf32_arm_next_input_section (struct bfd_link_info *info,
     {
       asection **list = htab->input_list + isec->output_section->index;
 
-      if (*list != bfd_abs_section_ptr)
+      if (*list != bfd_abs_section_ptr && (isec->flags & SEC_CODE) != 0)
        {
          /* Steal the link_sec pointer for our list.  */
 #define PREV_SEC(sec) (htab->stub_group[(sec)->id].link_sec)
@@ -3862,7 +3904,8 @@ group_sections (struct elf32_arm_link_hash_table *htab,
 static int
 a8_reloc_compare (const void *a, const void *b)
 {
-  const struct a8_erratum_reloc *ra = a, *rb = b;
+  const struct a8_erratum_reloc *ra = (const struct a8_erratum_reloc *) a;
+  const struct a8_erratum_reloc *rb = (const struct a8_erratum_reloc *) b;
 
   if (ra->from < rb->from)
     return -1;
@@ -3887,7 +3930,9 @@ cortex_a8_erratum_scan (bfd *input_bfd,
                        unsigned int *num_a8_fixes_p,
                        unsigned int *a8_fix_table_size_p,
                        struct a8_erratum_reloc *a8_relocs,
-                       unsigned int num_a8_relocs)
+                       unsigned int num_a8_relocs,
+                       unsigned prev_num_a8_fixes,
+                       bfd_boolean *stub_changed_p)
 {
   asection *section;
   struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
@@ -3985,9 +4030,10 @@ cortex_a8_erratum_scan (bfd *input_bfd,
                   struct a8_erratum_reloc key, *found;
 
                   key.from = base_vma + i;
-                  found = bsearch (&key, a8_relocs, num_a8_relocs,
-                                   sizeof (struct a8_erratum_reloc),
-                                   &a8_reloc_compare);
+                  found = (struct a8_erratum_reloc *)
+                      bsearch (&key, a8_relocs, num_a8_relocs,
+                               sizeof (struct a8_erratum_reloc),
+                               &a8_reloc_compare);
 
                  if (found)
                    {
@@ -4099,19 +4145,39 @@ cortex_a8_erratum_scan (bfd *input_bfd,
 
                       if (((base_vma + i) & ~0xfff) == (target & ~0xfff))
                         {
-                          char *stub_name;
+                          char *stub_name = NULL;
 
                           if (num_a8_fixes == a8_fix_table_size)
                             {
                               a8_fix_table_size *= 2;
-                              a8_fixes = bfd_realloc (a8_fixes,
-                                sizeof (struct a8_erratum_fix)
-                                * a8_fix_table_size);
+                              a8_fixes = (struct a8_erratum_fix *)
+                                  bfd_realloc (a8_fixes,
+                                               sizeof (struct a8_erratum_fix)
+                                               * a8_fix_table_size);
                             }
 
-                          stub_name = bfd_malloc (8 + 1 + 8 + 1);
-                          if (stub_name != NULL)
-                            sprintf (stub_name, "%x:%x", section->id, i);
+                         if (num_a8_fixes < prev_num_a8_fixes)
+                           {
+                             /* If we're doing a subsequent scan,
+                                check if we've found the same fix as
+                                before, and try and reuse the stub
+                                name.  */
+                             stub_name = a8_fixes[num_a8_fixes].stub_name;
+                             if ((a8_fixes[num_a8_fixes].section != section)
+                                 || (a8_fixes[num_a8_fixes].offset != i))
+                               {
+                                 free (stub_name);
+                                 stub_name = NULL;
+                                 *stub_changed_p = TRUE;
+                               }
+                           }
+
+                         if (!stub_name)
+                           {
+                             stub_name = (char *) bfd_malloc (8 + 1 + 8 + 1);
+                             if (stub_name != NULL)
+                               sprintf (stub_name, "%x:%x", section->id, i);
+                           }
 
                           a8_fixes[num_a8_fixes].input_bfd = input_bfd;
                           a8_fixes[num_a8_fixes].section = section;
@@ -4159,19 +4225,18 @@ elf32_arm_size_stubs (bfd *output_bfd,
 {
   bfd_size_type stub_group_size;
   bfd_boolean stubs_always_after_branch;
-  bfd_boolean stub_changed = 0;
   struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
   struct a8_erratum_fix *a8_fixes = NULL;
-  unsigned int num_a8_fixes = 0, prev_num_a8_fixes = 0, a8_fix_table_size = 10;
+  unsigned int num_a8_fixes = 0, a8_fix_table_size = 10;
   struct a8_erratum_reloc *a8_relocs = NULL;
   unsigned int num_a8_relocs = 0, a8_reloc_table_size = 10, i;
 
   if (htab->fix_cortex_a8)
     {
-      a8_fixes = bfd_zmalloc (sizeof (struct a8_erratum_fix)
-                              * a8_fix_table_size);
-      a8_relocs = bfd_zmalloc (sizeof (struct a8_erratum_reloc)
-                               * a8_reloc_table_size);
+      a8_fixes = (struct a8_erratum_fix *)
+          bfd_zmalloc (sizeof (struct a8_erratum_fix) * a8_fix_table_size);
+      a8_relocs = (struct a8_erratum_reloc *)
+          bfd_zmalloc (sizeof (struct a8_erratum_reloc) * a8_reloc_table_size);
     }
 
   /* Propagate mach to stub bfd, because it may not have been
@@ -4212,14 +4277,25 @@ elf32_arm_size_stubs (bfd *output_bfd,
 
   group_sections (htab, stub_group_size, stubs_always_after_branch);
 
+  /* If we're applying the cortex A8 fix, we need to determine the
+     program header size now, because we cannot change it later --
+     that could alter section placements.  Notice the A8 erratum fix
+     ends up requiring the section addresses to remain unchanged
+     modulo the page size.  That's something we cannot represent
+     inside BFD, and we don't want to force the section alignment to
+     be the page size.  */
+  if (htab->fix_cortex_a8)
+    (*htab->layout_sections_again) ();
+
   while (1)
     {
       bfd *input_bfd;
       unsigned int bfd_indx;
       asection *stub_sec;
+      bfd_boolean stub_changed = FALSE;
+      unsigned prev_num_a8_fixes = num_a8_fixes;
 
       num_a8_fixes = 0;
-
       for (input_bfd = info->input_bfds, bfd_indx = 0;
           input_bfd != NULL;
           input_bfd = input_bfd->link_next, bfd_indx++)
@@ -4331,6 +4407,11 @@ elf32_arm_size_stubs (bfd *output_bfd,
                      sym = local_syms + r_indx;
                      hdr = elf_elfsections (input_bfd)[sym->st_shndx];
                      sym_sec = hdr->bfd_section;
+                     if (!sym_sec)
+                       /* This is an undefined symbol.  It can never
+                          be resolved. */
+                       continue;
+                 
                      if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
                        sym_value = sym->st_value;
                      destination = (sym_value + irela->r_addend
@@ -4446,6 +4527,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
                        {
                          /* The proper stub has already been created.  */
                          free (stub_name);
+                         stub_entry->target_value = sym_value;
                          break;
                        }
 
@@ -4465,8 +4547,8 @@ elf32_arm_size_stubs (bfd *output_bfd,
 
                       if (sym_name == NULL)
                        sym_name = "unnamed";
-                      stub_entry->output_name
-                       = bfd_alloc (htab->stub_bfd,
+                      stub_entry->output_name = (char *)
+                          bfd_alloc (htab->stub_bfd,
                                      sizeof (THUMB2ARM_GLUE_ENTRY_NAME)
                                      + strlen (sym_name));
                       if (stub_entry->output_name == NULL)
@@ -4517,9 +4599,10 @@ elf32_arm_size_stubs (bfd *output_bfd,
                           if (num_a8_relocs == a8_reloc_table_size)
                             {
                               a8_reloc_table_size *= 2;
-                              a8_relocs = bfd_realloc (a8_relocs,
-                                sizeof (struct a8_erratum_reloc)
-                                * a8_reloc_table_size);
+                              a8_relocs = (struct a8_erratum_reloc *)
+                                  bfd_realloc (a8_relocs,
+                                               sizeof (struct a8_erratum_reloc)
+                                               * a8_reloc_table_size);
                             }
 
                           a8_relocs[num_a8_relocs].from = from;
@@ -4542,18 +4625,21 @@ elf32_arm_size_stubs (bfd *output_bfd,
           if (htab->fix_cortex_a8)
            {
               /* Sort relocs which might apply to Cortex-A8 erratum.  */
-              qsort (a8_relocs, num_a8_relocs, sizeof (struct a8_erratum_reloc),
+              qsort (a8_relocs, num_a8_relocs,
+                    sizeof (struct a8_erratum_reloc),
                      &a8_reloc_compare);
 
               /* Scan for branches which might trigger Cortex-A8 erratum.  */
               if (cortex_a8_erratum_scan (input_bfd, info, &a8_fixes,
                                          &num_a8_fixes, &a8_fix_table_size,
-                                         a8_relocs, num_a8_relocs) != 0)
+                                         a8_relocs, num_a8_relocs,
+                                         prev_num_a8_fixes, &stub_changed)
+                 != 0)
                goto error_ret_free_local;
            }
        }
 
-      if (htab->fix_cortex_a8 && num_a8_fixes != prev_num_a8_fixes)
+      if (prev_num_a8_fixes != num_a8_fixes)
         stub_changed = TRUE;
 
       if (!stub_changed)
@@ -4592,8 +4678,6 @@ elf32_arm_size_stubs (bfd *output_bfd,
 
       /* Ask the linker to do its stuff.  */
       (*htab->layout_sections_again) ();
-      stub_changed = FALSE;
-      prev_num_a8_fixes = num_a8_fixes;
     }
 
   /* Add stubs for Cortex-A8 erratum fixes now.  */
@@ -4607,7 +4691,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
           unsigned int section_id = a8_fixes[i].section->id;
           asection *link_sec = htab->stub_group[section_id].link_sec;
           asection *stub_sec = htab->stub_group[section_id].stub_sec;
-          const insn_sequence *template;
+          const insn_sequence *template_sequence;
           int template_size, size = 0;
 
           stub_entry = arm_stub_hash_lookup (&htab->stub_hash_table, stub_name,
@@ -4630,11 +4714,12 @@ elf32_arm_size_stubs (bfd *output_bfd,
           stub_entry->orig_insn = a8_fixes[i].orig_insn;
           stub_entry->st_type = STT_ARM_TFUNC;
 
-          size = find_stub_size_and_template (a8_fixes[i].stub_type, &template,
+          size = find_stub_size_and_template (a8_fixes[i].stub_type,
+                                              &template_sequence,
                                               &template_size);
 
           stub_entry->stub_size = size;
-          stub_entry->stub_template = template;
+          stub_entry->stub_template = template_sequence;
           stub_entry->stub_template_size = template_size;
         }
 
@@ -4681,7 +4766,7 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
 
       /* Allocate memory to hold the linker stubs.  */
       size = stub_sec->size;
-      stub_sec->contents = bfd_zalloc (htab->stub_bfd, size);
+      stub_sec->contents = (unsigned char *) bfd_zalloc (htab->stub_bfd, size);
       if (stub_sec->contents == NULL && size != 0)
        return FALSE;
       stub_sec->size = 0;
@@ -4690,6 +4775,12 @@ elf32_arm_build_stubs (struct bfd_link_info *info)
   /* Build the stubs as directed by the stub hash table.  */
   table = &htab->stub_hash_table;
   bfd_hash_traverse (table, arm_build_one_stub, info);
+  if (htab->fix_cortex_a8)
+    {
+      /* Place the cortex a8 stubs last.  */
+      htab->fix_cortex_a8 = -1;
+      bfd_hash_traverse (table, arm_build_one_stub, info);
+    }
 
   return TRUE;
 }
@@ -4708,8 +4799,8 @@ find_thumb_glue (struct bfd_link_info *link_info,
   /* We need a pointer to the armelf specific hash table.  */
   hash_table = elf32_arm_hash_table (link_info);
 
-  tmp_name = bfd_malloc ((bfd_size_type) strlen (name)
-                        + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1);
+  tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen (name)
+                                  + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1);
 
   BFD_ASSERT (tmp_name);
 
@@ -4742,8 +4833,8 @@ find_arm_glue (struct bfd_link_info *link_info,
   /* We need a pointer to the elfarm specific hash table.  */
   hash_table = elf32_arm_hash_table (link_info);
 
-  tmp_name = bfd_malloc ((bfd_size_type) strlen (name)
-                        + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1);
+  tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen (name)
+                                  + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1);
 
   BFD_ASSERT (tmp_name);
 
@@ -4853,7 +4944,7 @@ arm_allocate_glue_section_space (bfd * abfd, bfd_size_type size, const char * na
   s = bfd_get_section_by_name (abfd, name);
   BFD_ASSERT (s != NULL);
 
-  contents = bfd_alloc (abfd, size);
+  contents = (bfd_byte *) bfd_alloc (abfd, size);
 
   BFD_ASSERT (s->size == size);
   s->contents = contents;
@@ -4912,7 +5003,8 @@ record_arm_to_thumb_glue (struct bfd_link_info * link_info,
 
   BFD_ASSERT (s != NULL);
 
-  tmp_name = bfd_malloc ((bfd_size_type) strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1);
+  tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen (name)
+                                  + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1);
 
   BFD_ASSERT (tmp_name);
 
@@ -4989,7 +5081,8 @@ record_arm_bx_glue (struct bfd_link_info * link_info, int reg)
   BFD_ASSERT (s != NULL);
 
   /* Add symbol for veneer.  */
-  tmp_name = bfd_malloc ((bfd_size_type) strlen (ARM_BX_GLUE_ENTRY_NAME) + 1);
+  tmp_name = (char *)
+      bfd_malloc ((bfd_size_type) strlen (ARM_BX_GLUE_ENTRY_NAME) + 1);
 
   BFD_ASSERT (tmp_name);
 
@@ -5026,7 +5119,8 @@ elf32_arm_section_map_add (asection *sec, char type, bfd_vma vma)
 
   if (sec_data->map == NULL)
     {
-      sec_data->map = bfd_malloc (sizeof (elf32_arm_section_map));
+      sec_data->map = (elf32_arm_section_map *)
+          bfd_malloc (sizeof (elf32_arm_section_map));
       sec_data->mapcount = 0;
       sec_data->mapsize = 1;
     }
@@ -5036,8 +5130,9 @@ elf32_arm_section_map_add (asection *sec, char type, bfd_vma vma)
   if (sec_data->mapcount > sec_data->mapsize)
     {
       sec_data->mapsize *= 2;
-      sec_data->map = bfd_realloc_or_free (sec_data->map, sec_data->mapsize
-                                          * sizeof (elf32_arm_section_map));
+      sec_data->map = (elf32_arm_section_map *)
+          bfd_realloc_or_free (sec_data->map, sec_data->mapsize
+                               * sizeof (elf32_arm_section_map));
     }
 
   if (sec_data->map)
@@ -5080,8 +5175,8 @@ record_vfp11_erratum_veneer (struct bfd_link_info *link_info,
 
   BFD_ASSERT (s != NULL);
 
-  tmp_name = bfd_malloc ((bfd_size_type) strlen
-                        (VFP11_ERRATUM_VENEER_ENTRY_NAME) + 10);
+  tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen
+                                  (VFP11_ERRATUM_VENEER_ENTRY_NAME) + 10);
 
   BFD_ASSERT (tmp_name);
 
@@ -5105,7 +5200,8 @@ record_vfp11_erratum_veneer (struct bfd_link_info *link_info,
 
   /* Link veneer back to calling location.  */
   errcount = ++(sec_data->erratumcount);
-  newerr = bfd_zmalloc (sizeof (elf32_vfp11_erratum_list));
+  newerr = (elf32_vfp11_erratum_list *)
+      bfd_zmalloc (sizeof (elf32_vfp11_erratum_list));
 
   newerr->type = VFP11_ERRATUM_ARM_VENEER;
   newerr->vma = -1;
@@ -5597,7 +5693,7 @@ static enum bfd_arm_vfp11_pipe
 bfd_arm_vfp11_insn_decode (unsigned int insn, unsigned int *destmask, int *regs,
                            int *numregs)
 {
-  enum bfd_arm_vfp11_pipe pipe = VFP11_BAD;
+  enum bfd_arm_vfp11_pipe vpipe = VFP11_BAD;
   bfd_boolean is_double = ((insn & 0xf00) == 0xb00) ? 1 : 0;
 
   if ((insn & 0x0f000e10) == 0x0e000a00)  /* A data-processing insn.  */
@@ -5616,7 +5712,7 @@ bfd_arm_vfp11_insn_decode (unsigned int insn, unsigned int *destmask, int *regs,
         case 1: /* fnmac[sd].  */
         case 2: /* fmsc[sd].  */
         case 3: /* fnmsc[sd].  */
-          pipe = VFP11_FMAC;
+          vpipe = VFP11_FMAC;
           bfd_arm_vfp11_write_mask (destmask, fd);
           regs[0] = fd;
           regs[1] = bfd_arm_vfp11_regno (insn, is_double, 16, 7);  /* Fn.  */
@@ -5628,11 +5724,11 @@ bfd_arm_vfp11_insn_decode (unsigned int insn, unsigned int *destmask, int *regs,
         case 5: /* fnmul[sd].  */
         case 6: /* fadd[sd].  */
         case 7: /* fsub[sd].  */
-          pipe = VFP11_FMAC;
+          vpipe = VFP11_FMAC;
           goto vfp_binop;
 
         case 8: /* fdiv[sd].  */
-          pipe = VFP11_DS;
+          vpipe = VFP11_DS;
           vfp_binop:
           bfd_arm_vfp11_write_mask (destmask, fd);
           regs[0] = bfd_arm_vfp11_regno (insn, is_double, 16, 7);   /* Fn.  */
@@ -5662,14 +5758,14 @@ bfd_arm_vfp11_insn_decode (unsigned int insn, unsigned int *destmask, int *regs,
               case 27: /* ftosiz[sd].  */
                 /* These instructions will not bounce due to underflow.  */
                 *numregs = 0;
-                pipe = VFP11_FMAC;
+                vpipe = VFP11_FMAC;
                 break;
 
               case 3: /* fsqrt[sd].  */
                 /* fsqrt cannot underflow, but it can (perhaps) overwrite
                    registers to cause the erratum in previous instructions.  */
                 bfd_arm_vfp11_write_mask (destmask, fd);
-                pipe = VFP11_DS;
+                vpipe = VFP11_DS;
                 break;
 
               case 15: /* fcvt{ds,sd}.  */
@@ -5684,7 +5780,7 @@ bfd_arm_vfp11_insn_decode (unsigned int insn, unsigned int *destmask, int *regs,
 
                   *numregs = rnum;
 
-                  pipe = VFP11_FMAC;
+                  vpipe = VFP11_FMAC;
                 }
                 break;
 
@@ -5714,7 +5810,7 @@ bfd_arm_vfp11_insn_decode (unsigned int insn, unsigned int *destmask, int *regs,
             }
        }
 
-      pipe = VFP11_LS;
+      vpipe = VFP11_LS;
     }
   else if ((insn & 0x0e100e00) == 0x0c100a00)  /* A load insn.  */
     {
@@ -5749,7 +5845,7 @@ bfd_arm_vfp11_insn_decode (unsigned int insn, unsigned int *destmask, int *regs,
           return VFP11_BAD;
         }
 
-      pipe = VFP11_LS;
+      vpipe = VFP11_LS;
     }
   /* Single-register transfer. Note L==0.  */
   else if ((insn & 0x0f100e10) == 0x0e000a10)
@@ -5771,10 +5867,10 @@ bfd_arm_vfp11_insn_decode (unsigned int insn, unsigned int *destmask, int *regs,
           break;
         }
 
-      pipe = VFP11_LS;
+      vpipe = VFP11_LS;
     }
 
-  return pipe;
+  return vpipe;
 }
 
 
@@ -5894,17 +5990,17 @@ bfd_elf32_arm_vfp11_erratum_scan (bfd *abfd, struct bfd_link_info *link_info)
                   | (contents[i + 1] << 8)
                   | contents[i];
               unsigned int writemask = 0;
-              enum bfd_arm_vfp11_pipe pipe;
+              enum bfd_arm_vfp11_pipe vpipe;
 
               switch (state)
                 {
                 case 0:
-                  pipe = bfd_arm_vfp11_insn_decode (insn, &writemask, regs,
+                  vpipe = bfd_arm_vfp11_insn_decode (insn, &writemask, regs,
                                                     &numregs);
                   /* I'm assuming the VFP11 erratum can trigger with denorm
                      operands on either the FMAC or the DS pipeline. This might
                      lead to slightly overenthusiastic veneer insertion.  */
-                  if (pipe == VFP11_FMAC || pipe == VFP11_DS)
+                  if (vpipe == VFP11_FMAC || vpipe == VFP11_DS)
                     {
                       state = use_vector ? 1 : 2;
                       first_fmac = i;
@@ -5915,10 +6011,10 @@ bfd_elf32_arm_vfp11_erratum_scan (bfd *abfd, struct bfd_link_info *link_info)
                 case 1:
                   {
                     int other_regs[3], other_numregs;
-                    pipe = bfd_arm_vfp11_insn_decode (insn, &writemask,
+                    vpipe = bfd_arm_vfp11_insn_decode (insn, &writemask,
                                                      other_regs,
                                                       &other_numregs);
-                    if (pipe != VFP11_BAD
+                    if (vpipe != VFP11_BAD
                         && bfd_arm_vfp11_antidependency (writemask, regs,
                                                         numregs))
                       state = 3;
@@ -5930,10 +6026,10 @@ bfd_elf32_arm_vfp11_erratum_scan (bfd *abfd, struct bfd_link_info *link_info)
                 case 2:
                   {
                     int other_regs[3], other_numregs;
-                    pipe = bfd_arm_vfp11_insn_decode (insn, &writemask,
+                    vpipe = bfd_arm_vfp11_insn_decode (insn, &writemask,
                                                      other_regs,
                                                       &other_numregs);
-                    if (pipe != VFP11_BAD
+                    if (vpipe != VFP11_BAD
                         && bfd_arm_vfp11_antidependency (writemask, regs,
                                                         numregs))
                       state = 3;
@@ -5951,8 +6047,8 @@ bfd_elf32_arm_vfp11_erratum_scan (bfd *abfd, struct bfd_link_info *link_info)
 
               if (state == 3)
                 {
-                  elf32_vfp11_erratum_list *newerr
-                    = bfd_zmalloc (sizeof (elf32_vfp11_erratum_list));
+                  elf32_vfp11_erratum_list *newerr =(elf32_vfp11_erratum_list *)
+                      bfd_zmalloc (sizeof (elf32_vfp11_erratum_list));
                   int errcount;
 
                   errcount = ++(elf32_arm_section_data (sec)->erratumcount);
@@ -6020,8 +6116,8 @@ bfd_elf32_arm_vfp11_fix_veneer_locations (bfd *abfd,
 
   globals = elf32_arm_hash_table (link_info);
 
-  tmp_name = bfd_malloc ((bfd_size_type) strlen
-                          (VFP11_ERRATUM_VENEER_ENTRY_NAME) + 10);
+  tmp_name = (char *) bfd_malloc ((bfd_size_type) strlen
+                                  (VFP11_ERRATUM_VENEER_ENTRY_NAME) + 10);
 
   for (sec = abfd->sections; sec != NULL; sec = sec->next)
     {
@@ -6908,7 +7004,6 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
        case R_ARM_PC24:          /* Arm B/BL instruction.  */
        case R_ARM_PLT32:
          {
-         bfd_vma from;
          bfd_signed_vma branch_offset;
          struct elf32_arm_stub_hash_entry *stub_entry = NULL;
 
@@ -6945,6 +7040,8 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
              || r_type == R_ARM_JUMP24
              || r_type == R_ARM_PLT32)
            {
+             bfd_vma from;
+             
              /* If the call goes through a PLT entry, make sure to
                 check distance to the right destination address.  */
              if (h != NULL && splt != NULL && h->plt.offset != (bfd_vma) -1)
@@ -6953,6 +7050,9 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                           + splt->output_offset
                           + h->plt.offset);
                  *unresolved_reloc_p = FALSE;
+                 /* The PLT entry is in ARM mode, regardless of the
+                    target function.  */
+                 sym_flags = STT_FUNC;
                }
 
              from = (input_section->output_section->vma
@@ -7013,12 +7113,20 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
          signed_addend >>= howto->rightshift;
 
          /* A branch to an undefined weak symbol is turned into a jump to
-            the next instruction unless a PLT entry will be created.  */
-         if (h && h->root.type == bfd_link_hash_undefweak
-             && !(splt != NULL && h->plt.offset != (bfd_vma) -1))
+            the next instruction unless a PLT entry will be created.
+            Do the same for local undefined symbols.
+            The jump to the next instruction is optimized as a NOP depending
+            on the architecture.  */
+         if (h ? (h->root.type == bfd_link_hash_undefweak
+                  && !(splt != NULL && h->plt.offset != (bfd_vma) -1))
+             : bfd_is_und_section (sym_sec))
            {
-             value = (bfd_get_32 (input_bfd, hit_data) & 0xf0000000)
-                     | 0x0affffff;
+             value = (bfd_get_32 (input_bfd, hit_data) & 0xf0000000);
+
+             if (arch_has_arm_nop (globals))
+               value |= 0x0320f000;
+             else
+               value |= 0x01a00000; /* Using pre-UAL nop: mov r0, r0.  */
            }
          else
            {
@@ -7178,6 +7286,40 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
         return bfd_reloc_ok;
       }
 
+    case R_ARM_THM_PC8:
+      /* PR 10073:  This reloc is not generated by the GNU toolchain,
+        but it is supported for compatibility with third party libraries
+        generated by other compilers, specifically the ARM/IAR.  */
+      {
+       bfd_vma insn;
+       bfd_signed_vma relocation;
+
+       insn = bfd_get_16 (input_bfd, hit_data);
+
+        if (globals->use_rel)
+         addend = (insn & 0x00ff) << 2;
+
+       relocation = value + addend;
+       relocation -= (input_section->output_section->vma
+                      + input_section->output_offset
+                      + rel->r_offset);
+
+        value = abs (relocation);
+
+       /* We do not check for overflow of this reloc.  Although strictly
+          speaking this is incorrect, it appears to be necessary in order
+          to work with IAR generated relocs.  Since GCC and GAS do not
+          generate R_ARM_THM_PC8 relocs, the lack of a check should not be
+          a problem for them.  */
+       value &= 0x3fc;
+
+       insn = (insn & 0xff00) | (value >> 2);
+
+       bfd_put_16 (input_bfd, insn, hit_data);
+
+        return bfd_reloc_ok;
+      }
+
     case R_ARM_THM_PC12:
       /* Corresponds to: ldr.w reg, [pc, #offset].  */
       {
@@ -7229,15 +7371,25 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
        bfd_vma check;
        bfd_signed_vma signed_check;
        int bitsize;
-       int thumb2 = using_thumb2 (globals);
+       const int thumb2 = using_thumb2 (globals);
 
        /* A branch to an undefined weak symbol is turned into a jump to
-          the next instruction unless a PLT entry will be created.  */
+          the next instruction unless a PLT entry will be created.
+          The jump to the next instruction is optimized as a NOP.W for
+          Thumb-2 enabled architectures.  */
        if (h && h->root.type == bfd_link_hash_undefweak
            && !(splt != NULL && h->plt.offset != (bfd_vma) -1))
          {
-           bfd_put_16 (input_bfd, 0xe000, hit_data);
-           bfd_put_16 (input_bfd, 0xbf00, hit_data + 2);
+           if (arch_has_thumb2_nop (globals))
+             {
+               bfd_put_16 (input_bfd, 0xf3af, hit_data);
+               bfd_put_16 (input_bfd, 0x8000, hit_data + 2);
+             }
+           else
+             {
+               bfd_put_16 (input_bfd, 0xe000, hit_data);
+               bfd_put_16 (input_bfd, 0xbf00, hit_data + 2);
+             }
            return bfd_reloc_ok;
          }
 
@@ -7317,10 +7469,14 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                /* If the Thumb BLX instruction is available, convert the
                   BL to a BLX instruction to call the ARM-mode PLT entry.  */
                lower_insn = (lower_insn & ~0x1000) | 0x0800;
+               sym_flags = STT_FUNC;
              }
            else
-             /* Target the Thumb stub before the ARM PLT entry.  */
-             value -= PLT_THUMB_STUB_SIZE;
+             {
+               /* Target the Thumb stub before the ARM PLT entry.  */
+               value -= PLT_THUMB_STUB_SIZE;
+               sym_flags = STT_ARM_TFUNC;
+             }
            *unresolved_reloc_p = FALSE;
          }
 
@@ -7950,7 +8106,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
            (_("%B(%A+0x%lx): R_ARM_TLS_LE32 relocation not permitted in shared object"),
             input_bfd, input_section,
             (long) rel->r_offset, howto->name);
-         return FALSE;
+         return (bfd_reloc_status_type) FALSE;
        }
       else
        value = tpoff (info, value);
@@ -8627,6 +8783,25 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
          sym = local_syms + r_symndx;
          sym_type = ELF32_ST_TYPE (sym->st_info);
          sec = local_sections[r_symndx];
+
+         /* An object file might have a reference to a local
+            undefined symbol.  This is a daft object file, but we
+            should at least do something about it.  V4BX & NONE
+            relocations do not use the symbol and are explicitly
+            allowed to use the undefined symbol, so allow those.  */
+         if (r_type != R_ARM_V4BX
+             && r_type != R_ARM_NONE
+             && bfd_is_und_section (sec)
+             && ELF_ST_BIND (sym->st_info) != STB_WEAK)
+           {
+             if (!info->callbacks->undefined_symbol
+                 (info, bfd_elf_string_from_elf_section
+                  (input_bfd, symtab_hdr->sh_link, sym->st_name),
+                  input_bfd, input_section,
+                  rel->r_offset, TRUE))
+               return FALSE;
+           }
+         
          if (globals->use_rel)
            {
              relocation = (sec->output_section->vma
@@ -8869,9 +9044,9 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
   return TRUE;
 }
 
-/* Add a new unwind edit to the list described by HEAD, TAIL.  If INDEX is zero,
+/* Add a new unwind edit to the list described by HEAD, TAIL.  If TINDEX is zero,
    adds the edit to the start of the list.  (The list must be built in order of
-   ascending INDEX: the function's callers are primarily responsible for
+   ascending TINDEX: the function's callers are primarily responsible for
    maintaining that condition).  */
 
 static void
@@ -8879,15 +9054,16 @@ add_unwind_table_edit (arm_unwind_table_edit **head,
                       arm_unwind_table_edit **tail,
                       arm_unwind_edit_type type,
                       asection *linked_section,
-                      unsigned int index)
+                      unsigned int tindex)
 {
-  arm_unwind_table_edit *new_edit = xmalloc (sizeof (arm_unwind_table_edit));
+  arm_unwind_table_edit *new_edit = (arm_unwind_table_edit *)
+      xmalloc (sizeof (arm_unwind_table_edit));
   
   new_edit->type = type;
   new_edit->linked_section = linked_section;
-  new_edit->index = index;
+  new_edit->index = tindex;
   
-  if (index > 0)
+  if (tindex > 0)
     {
       new_edit->next = NULL;
 
@@ -8997,8 +9173,7 @@ elf32_arm_fix_exidx_coverage (asection **text_section_order,
 
   /* Walk all text sections in order of increasing VMA.  Eilminate duplicate
      index table entries (EXIDX_CANTUNWIND and inlined unwind opcodes),
-     and add EXIDX_CANTUNWIND entries for sections with no unwind table data.
-   */
+     and add EXIDX_CANTUNWIND entries for sections with no unwind table data.  */
 
   for (i = 0; i < num_text_sections; i++)
     {
@@ -9378,7 +9553,7 @@ set_secondary_compatible_arch (bfd *abfd, int arch)
   /* Note: the tag and its argument below are uleb128 values, though
      currently-defined values fit in one byte for each.  */
   if (!attr->s)
-    attr->s = bfd_alloc (abfd, 3);
+    attr->s = (char *) bfd_alloc (abfd, 3);
   attr->s[0] = Tag_CPU_arch;
   attr->s[1] = arch;
   attr->s[2] = '\0';
@@ -9463,6 +9638,23 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out,
       T(V6S_M),  /* V6_M.  */
       T(V6S_M)   /* V6S_M.  */
     };
+  const int v7e_m[] =
+    {
+      -1,        /* PRE_V4.  */
+      -1,        /* V4.  */
+      T(V7E_M),  /* V4T.  */
+      T(V7E_M),  /* V5T.  */
+      T(V7E_M),  /* V5TE.  */
+      T(V7E_M),  /* V5TEJ.  */
+      T(V7E_M),  /* V6.  */
+      T(V7E_M),  /* V6KZ.  */
+      T(V7E_M),  /* V6T2.  */
+      T(V7E_M),  /* V6K.  */
+      T(V7E_M),  /* V7.  */
+      T(V7E_M),  /* V6_M.  */
+      T(V7E_M),  /* V6S_M.  */
+      T(V7E_M)   /* V7E_M.  */
+    };
   const int v4t_plus_v6_m[] =
     {
       -1,              /* PRE_V4.  */
@@ -9478,6 +9670,7 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out,
       T(V7),           /* V7.  */
       T(V6_M),         /* V6_M.  */
       T(V6S_M),                /* V6S_M.  */
+      T(V7E_M),                /* V7E_M.  */
       T(V4T_PLUS_V6_M) /* V4T plus V6_M.  */
     };
   const int *comb[] =
@@ -9487,13 +9680,14 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out,
       v7,
       v6_m,
       v6s_m,
+      v7e_m,
       /* Pseudo-architecture.  */
       v4t_plus_v6_m
     };
 
   /* Check we've not got a higher architecture than we know about.  */
 
-  if (oldtag >= MAX_TAG_CPU_ARCH || newtag >= MAX_TAG_CPU_ARCH)
+  if (oldtag > MAX_TAG_CPU_ARCH || newtag > MAX_TAG_CPU_ARCH)
     {
       _bfd_error_handler (_("error: %B: Unknown CPU architecture"), ibfd);
       return -1;
@@ -9556,8 +9750,6 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
   /* Some tags have 0 = don't care, 1 = strong requirement,
      2 = weak requirement.  */
   static const int order_021[3] = {0, 2, 1};
-  /* For use with Tag_VFP_arch.  */
-  static const int order_01243[5] = {0, 1, 2, 4, 3};
   int i;
   bfd_boolean result = TRUE;
 
@@ -9749,12 +9941,50 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
            }
          break;
        case Tag_VFP_arch:
-         /* Use the "greatest" from the sequence 0, 1, 2, 4, 3, or the
-            largest value if greater than 4 (for future-proofing).  */
-         if ((in_attr[i].i > 4 && in_attr[i].i > out_attr[i].i)
-             || (in_attr[i].i <= 4 && out_attr[i].i <= 4
-                 && order_01243[in_attr[i].i] > order_01243[out_attr[i].i]))
-           out_attr[i].i = in_attr[i].i;
+           {
+             static const struct
+             {
+                 int ver;
+                 int regs;
+             } vfp_versions[7] =
+               {
+                 {0, 0},
+                 {1, 16},
+                 {2, 16},
+                 {3, 32},
+                 {3, 16},
+                 {4, 32},
+                 {4, 16}
+               };
+             int ver;
+             int regs;
+             int newval;
+
+             /* Values greater than 6 aren't defined, so just pick the
+                biggest */
+             if (in_attr[i].i > 6 && in_attr[i].i > out_attr[i].i)
+               {
+                 out_attr[i] = in_attr[i];
+                 break;
+               }
+             /* The output uses the superset of input features
+                (ISA version) and registers.  */
+             ver = vfp_versions[in_attr[i].i].ver;
+             if (ver < vfp_versions[out_attr[i].i].ver)
+               ver = vfp_versions[out_attr[i].i].ver;
+             regs = vfp_versions[in_attr[i].i].regs;
+             if (regs < vfp_versions[out_attr[i].i].regs)
+               regs = vfp_versions[out_attr[i].i].regs;
+             /* This assumes all possible supersets are also a valid
+                options.  */
+             for (newval = 6; newval > 0; newval--)
+               {
+                 if (regs == vfp_versions[newval].regs
+                     && ver == vfp_versions[newval].ver)
+                   break;
+               }
+             out_attr[i].i = newval;
+           }
          break;
        case Tag_PCS_config:
          if (out_attr[i].i == 0)
@@ -10034,301 +10264,83 @@ elf32_arm_versions_compatible (unsigned iver, unsigned over)
    object file when linking.  */
 
 static bfd_boolean
-elf32_arm_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
-{
-  flagword out_flags;
-  flagword in_flags;
-  bfd_boolean flags_compatible = TRUE;
-  asection *sec;
+elf32_arm_merge_private_bfd_data (bfd * ibfd, bfd * obfd);
 
-  /* Check if we have the same endianess.  */
-  if (! _bfd_generic_verify_endian_match (ibfd, obfd))
-    return FALSE;
+/* Display the flags field.  */
 
-  if (! is_arm_elf (ibfd) || ! is_arm_elf (obfd))
-    return TRUE;
+static bfd_boolean
+elf32_arm_print_private_bfd_data (bfd *abfd, void * ptr)
+{
+  FILE * file = (FILE *) ptr;
+  unsigned long flags;
 
-  if (!elf32_arm_merge_eabi_attributes (ibfd, obfd))
-    return FALSE;
+  BFD_ASSERT (abfd != NULL && ptr != NULL);
 
-  /* The input BFD must have had its flags initialised.  */
-  /* The following seems bogus to me -- The flags are initialized in
-     the assembler but I don't think an elf_flags_init field is
-     written into the object.  */
-  /* BFD_ASSERT (elf_flags_init (ibfd)); */
+  /* Print normal ELF private data.  */
+  _bfd_elf_print_private_bfd_data (abfd, ptr);
 
-  in_flags  = elf_elfheader (ibfd)->e_flags;
-  out_flags = elf_elfheader (obfd)->e_flags;
+  flags = elf_elfheader (abfd)->e_flags;
+  /* Ignore init flag - it may not be set, despite the flags field
+     containing valid data.  */
 
-  /* In theory there is no reason why we couldn't handle this.  However
-     in practice it isn't even close to working and there is no real
-     reason to want it.  */
-  if (EF_ARM_EABI_VERSION (in_flags) >= EF_ARM_EABI_VER4
-      && !(ibfd->flags & DYNAMIC)
-      && (in_flags & EF_ARM_BE8))
-    {
-      _bfd_error_handler (_("error: %B is already in final BE8 format"),
-                         ibfd);
-      return FALSE;
-    }
+  /* xgettext:c-format */
+  fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
 
-  if (!elf_flags_init (obfd))
+  switch (EF_ARM_EABI_VERSION (flags))
     {
-      /* If the input is the default architecture and had the default
-        flags then do not bother setting the flags for the output
-        architecture, instead allow future merges to do this.  If no
-        future merges ever set these flags then they will retain their
-         uninitialised values, which surprise surprise, correspond
-         to the default values.  */
-      if (bfd_get_arch_info (ibfd)->the_default
-         && elf_elfheader (ibfd)->e_flags == 0)
-       return TRUE;
+    case EF_ARM_EABI_UNKNOWN:
+      /* The following flag bits are GNU extensions and not part of the
+        official ARM ELF extended ABI.  Hence they are only decoded if
+        the EABI version is not set.  */
+      if (flags & EF_ARM_INTERWORK)
+       fprintf (file, _(" [interworking enabled]"));
 
-      elf_flags_init (obfd) = TRUE;
-      elf_elfheader (obfd)->e_flags = in_flags;
+      if (flags & EF_ARM_APCS_26)
+       fprintf (file, " [APCS-26]");
+      else
+       fprintf (file, " [APCS-32]");
 
-      if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
-         && bfd_get_arch_info (obfd)->the_default)
-       return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
+      if (flags & EF_ARM_VFP_FLOAT)
+       fprintf (file, _(" [VFP float format]"));
+      else if (flags & EF_ARM_MAVERICK_FLOAT)
+       fprintf (file, _(" [Maverick float format]"));
+      else
+       fprintf (file, _(" [FPA float format]"));
 
-      return TRUE;
-    }
+      if (flags & EF_ARM_APCS_FLOAT)
+       fprintf (file, _(" [floats passed in float registers]"));
 
-  /* Determine what should happen if the input ARM architecture
-     does not match the output ARM architecture.  */
-  if (! bfd_arm_merge_machines (ibfd, obfd))
-    return FALSE;
+      if (flags & EF_ARM_PIC)
+       fprintf (file, _(" [position independent]"));
 
-  /* Identical flags must be compatible.  */
-  if (in_flags == out_flags)
-    return TRUE;
+      if (flags & EF_ARM_NEW_ABI)
+       fprintf (file, _(" [new ABI]"));
 
-  /* Check to see if the input BFD actually contains any sections.  If
-     not, its flags may not have been initialised either, but it
-     cannot actually cause any incompatiblity.  Do not short-circuit
-     dynamic objects; their section list may be emptied by
-    elf_link_add_object_symbols.
+      if (flags & EF_ARM_OLD_ABI)
+       fprintf (file, _(" [old ABI]"));
 
-    Also check to see if there are no code sections in the input.
-    In this case there is no need to check for code specific flags.
-    XXX - do we need to worry about floating-point format compatability
-    in data sections ?  */
-  if (!(ibfd->flags & DYNAMIC))
-    {
-      bfd_boolean null_input_bfd = TRUE;
-      bfd_boolean only_data_sections = TRUE;
+      if (flags & EF_ARM_SOFT_FLOAT)
+       fprintf (file, _(" [software FP]"));
 
-      for (sec = ibfd->sections; sec != NULL; sec = sec->next)
-       {
-         /* Ignore synthetic glue sections.  */
-         if (strcmp (sec->name, ".glue_7")
-             && strcmp (sec->name, ".glue_7t"))
-           {
-             if ((bfd_get_section_flags (ibfd, sec)
-                  & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
-                 == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
-               only_data_sections = FALSE;
+      flags &= ~(EF_ARM_INTERWORK | EF_ARM_APCS_26 | EF_ARM_APCS_FLOAT
+                | EF_ARM_PIC | EF_ARM_NEW_ABI | EF_ARM_OLD_ABI
+                | EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT
+                | EF_ARM_MAVERICK_FLOAT);
+      break;
 
-             null_input_bfd = FALSE;
-             break;
-           }
-       }
+    case EF_ARM_EABI_VER1:
+      fprintf (file, _(" [Version1 EABI]"));
 
-      if (null_input_bfd || only_data_sections)
-       return TRUE;
-    }
+      if (flags & EF_ARM_SYMSARESORTED)
+       fprintf (file, _(" [sorted symbol table]"));
+      else
+       fprintf (file, _(" [unsorted symbol table]"));
 
-  /* Complain about various flag mismatches.  */
-  if (!elf32_arm_versions_compatible (EF_ARM_EABI_VERSION (in_flags),
-                                     EF_ARM_EABI_VERSION (out_flags)))
-    {
-      _bfd_error_handler
-       (_("error: Source object %B has EABI version %d, but target %B has EABI version %d"),
-        ibfd, obfd,
-        (in_flags & EF_ARM_EABIMASK) >> 24,
-        (out_flags & EF_ARM_EABIMASK) >> 24);
-      return FALSE;
-    }
+      flags &= ~ EF_ARM_SYMSARESORTED;
+      break;
 
-  /* Not sure what needs to be checked for EABI versions >= 1.  */
-  /* VxWorks libraries do not use these flags.  */
-  if (get_elf_backend_data (obfd) != &elf32_arm_vxworks_bed
-      && get_elf_backend_data (ibfd) != &elf32_arm_vxworks_bed
-      && EF_ARM_EABI_VERSION (in_flags) == EF_ARM_EABI_UNKNOWN)
-    {
-      if ((in_flags & EF_ARM_APCS_26) != (out_flags & EF_ARM_APCS_26))
-       {
-         _bfd_error_handler
-           (_("error: %B is compiled for APCS-%d, whereas target %B uses APCS-%d"),
-            ibfd, obfd,
-            in_flags & EF_ARM_APCS_26 ? 26 : 32,
-            out_flags & EF_ARM_APCS_26 ? 26 : 32);
-         flags_compatible = FALSE;
-       }
-
-      if ((in_flags & EF_ARM_APCS_FLOAT) != (out_flags & EF_ARM_APCS_FLOAT))
-       {
-         if (in_flags & EF_ARM_APCS_FLOAT)
-           _bfd_error_handler
-             (_("error: %B passes floats in float registers, whereas %B passes them in integer registers"),
-              ibfd, obfd);
-         else
-           _bfd_error_handler
-             (_("error: %B passes floats in integer registers, whereas %B passes them in float registers"),
-              ibfd, obfd);
-
-         flags_compatible = FALSE;
-       }
-
-      if ((in_flags & EF_ARM_VFP_FLOAT) != (out_flags & EF_ARM_VFP_FLOAT))
-       {
-         if (in_flags & EF_ARM_VFP_FLOAT)
-           _bfd_error_handler
-             (_("error: %B uses VFP instructions, whereas %B does not"),
-              ibfd, obfd);
-         else
-           _bfd_error_handler
-             (_("error: %B uses FPA instructions, whereas %B does not"),
-              ibfd, obfd);
-
-         flags_compatible = FALSE;
-       }
-
-      if ((in_flags & EF_ARM_MAVERICK_FLOAT) != (out_flags & EF_ARM_MAVERICK_FLOAT))
-       {
-         if (in_flags & EF_ARM_MAVERICK_FLOAT)
-           _bfd_error_handler
-             (_("error: %B uses Maverick instructions, whereas %B does not"),
-              ibfd, obfd);
-         else
-           _bfd_error_handler
-             (_("error: %B does not use Maverick instructions, whereas %B does"),
-              ibfd, obfd);
-
-         flags_compatible = FALSE;
-       }
-
-#ifdef EF_ARM_SOFT_FLOAT
-      if ((in_flags & EF_ARM_SOFT_FLOAT) != (out_flags & EF_ARM_SOFT_FLOAT))
-       {
-         /* We can allow interworking between code that is VFP format
-            layout, and uses either soft float or integer regs for
-            passing floating point arguments and results.  We already
-            know that the APCS_FLOAT flags match; similarly for VFP
-            flags.  */
-         if ((in_flags & EF_ARM_APCS_FLOAT) != 0
-             || (in_flags & EF_ARM_VFP_FLOAT) == 0)
-           {
-             if (in_flags & EF_ARM_SOFT_FLOAT)
-               _bfd_error_handler
-                 (_("error: %B uses software FP, whereas %B uses hardware FP"),
-                  ibfd, obfd);
-             else
-               _bfd_error_handler
-                 (_("error: %B uses hardware FP, whereas %B uses software FP"),
-                  ibfd, obfd);
-
-             flags_compatible = FALSE;
-           }
-       }
-#endif
-
-      /* Interworking mismatch is only a warning.  */
-      if ((in_flags & EF_ARM_INTERWORK) != (out_flags & EF_ARM_INTERWORK))
-       {
-         if (in_flags & EF_ARM_INTERWORK)
-           {
-             _bfd_error_handler
-               (_("Warning: %B supports interworking, whereas %B does not"),
-                ibfd, obfd);
-           }
-         else
-           {
-             _bfd_error_handler
-               (_("Warning: %B does not support interworking, whereas %B does"),
-                ibfd, obfd);
-           }
-       }
-    }
-
-  return flags_compatible;
-}
-
-/* Display the flags field.  */
-
-static bfd_boolean
-elf32_arm_print_private_bfd_data (bfd *abfd, void * ptr)
-{
-  FILE * file = (FILE *) ptr;
-  unsigned long flags;
-
-  BFD_ASSERT (abfd != NULL && ptr != NULL);
-
-  /* Print normal ELF private data.  */
-  _bfd_elf_print_private_bfd_data (abfd, ptr);
-
-  flags = elf_elfheader (abfd)->e_flags;
-  /* Ignore init flag - it may not be set, despite the flags field
-     containing valid data.  */
-
-  /* xgettext:c-format */
-  fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
-
-  switch (EF_ARM_EABI_VERSION (flags))
-    {
-    case EF_ARM_EABI_UNKNOWN:
-      /* The following flag bits are GNU extensions and not part of the
-        official ARM ELF extended ABI.  Hence they are only decoded if
-        the EABI version is not set.  */
-      if (flags & EF_ARM_INTERWORK)
-       fprintf (file, _(" [interworking enabled]"));
-
-      if (flags & EF_ARM_APCS_26)
-       fprintf (file, " [APCS-26]");
-      else
-       fprintf (file, " [APCS-32]");
-
-      if (flags & EF_ARM_VFP_FLOAT)
-       fprintf (file, _(" [VFP float format]"));
-      else if (flags & EF_ARM_MAVERICK_FLOAT)
-       fprintf (file, _(" [Maverick float format]"));
-      else
-       fprintf (file, _(" [FPA float format]"));
-
-      if (flags & EF_ARM_APCS_FLOAT)
-       fprintf (file, _(" [floats passed in float registers]"));
-
-      if (flags & EF_ARM_PIC)
-       fprintf (file, _(" [position independent]"));
-
-      if (flags & EF_ARM_NEW_ABI)
-       fprintf (file, _(" [new ABI]"));
-
-      if (flags & EF_ARM_OLD_ABI)
-       fprintf (file, _(" [old ABI]"));
-
-      if (flags & EF_ARM_SOFT_FLOAT)
-       fprintf (file, _(" [software FP]"));
-
-      flags &= ~(EF_ARM_INTERWORK | EF_ARM_APCS_26 | EF_ARM_APCS_FLOAT
-                | EF_ARM_PIC | EF_ARM_NEW_ABI | EF_ARM_OLD_ABI
-                | EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT
-                | EF_ARM_MAVERICK_FLOAT);
-      break;
-
-    case EF_ARM_EABI_VER1:
-      fprintf (file, _(" [Version1 EABI]"));
-
-      if (flags & EF_ARM_SYMSARESORTED)
-       fprintf (file, _(" [sorted symbol table]"));
-      else
-       fprintf (file, _(" [unsorted symbol table]"));
-
-      flags &= ~ EF_ARM_SYMSARESORTED;
-      break;
-
-    case EF_ARM_EABI_VER2:
-      fprintf (file, _(" [Version2 EABI]"));
+    case EF_ARM_EABI_VER2:
+      fprintf (file, _(" [Version2 EABI]"));
 
       if (flags & EF_ARM_SYMSARESORTED)
        fprintf (file, _(" [sorted symbol table]"));
@@ -10677,7 +10689,8 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
                      size = symtab_hdr->sh_info;
                      size *= (sizeof (bfd_signed_vma) + sizeof (char));
-                     local_got_refcounts = bfd_zalloc (abfd, size);
+                     local_got_refcounts = (bfd_signed_vma *)
+                          bfd_zalloc (abfd, size);
                      if (local_got_refcounts == NULL)
                        return FALSE;
                      elf_local_got_refcounts (abfd) = local_got_refcounts;
@@ -10876,7 +10889,8 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
                  {
                    bfd_size_type amt = sizeof *p;
 
-                   p = bfd_alloc (htab->root.dynobj, amt);
+                   p = (struct elf32_arm_relocs_copied *)
+                        bfd_alloc (htab->root.dynobj, amt);
                    if (p == NULL)
                      return FALSE;
                    p->next = *head;
@@ -11295,13 +11309,13 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
            {
              h->root.u.def.section = s;
              h->root.u.def.value = h->plt.offset;
-           }
 
-         /* Make sure the function is not marked as Thumb, in case
-            it is the target of an ABS32 relocation, which will
-            point to the PLT entry.  */
-         if (ELF_ST_TYPE (h->type) == STT_ARM_TFUNC)
-           h->type = ELF_ST_INFO (ELF_ST_BIND (h->type), STT_FUNC);
+             /* Make sure the function is not marked as Thumb, in case
+                it is the target of an ABS32 relocation, which will
+                point to the PLT entry.  */
+             if (ELF_ST_TYPE (h->type) == STT_ARM_TFUNC)
+               h->type = ELF_ST_INFO (ELF_ST_BIND (h->type), STT_FUNC);
+           }
 
          /* Make room for this entry.  */
          s->size += htab->plt_entry_size;
@@ -11650,7 +11664,8 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
        {
          struct elf32_arm_relocs_copied *p;
 
-         for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
+         for (p = (struct elf32_arm_relocs_copied *)
+                   elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
            {
              if (!bfd_is_abs_section (p->section)
                  && bfd_is_abs_section (p->section->output_section))
@@ -11804,7 +11819,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
        continue;
 
       /* Allocate memory for the section contents.  */
-      s->contents = bfd_zalloc (dynobj, s->size);
+      s->contents = (unsigned char *) bfd_zalloc (dynobj, s->size);
       if (s->contents == NULL)
        return FALSE;
     }
@@ -12599,7 +12614,7 @@ record_section_with_arm_elf_section_data (asection * sec)
 {
   struct section_list * entry;
 
-  entry = bfd_malloc (sizeof (* entry));
+  entry = (struct section_list *) bfd_malloc (sizeof (* entry));
   if (entry == NULL)
     return;
   entry->sec = sec;
@@ -12826,7 +12841,7 @@ arm_map_one_stub (struct bfd_hash_entry * gen_entry,
   bfd_vma addr;
   char *stub_name;
   output_arch_syminfo *osi;
-  const insn_sequence *template;
+  const insn_sequence *template_sequence;
   enum stub_insn_type prev_type;
   int size;
   int i;
@@ -12849,8 +12864,8 @@ arm_map_one_stub (struct bfd_hash_entry * gen_entry,
   addr = (bfd_vma) stub_entry->stub_offset;
   stub_name = stub_entry->output_name;
 
-  template = stub_entry->stub_template;
-  switch (template[0].type)
+  template_sequence = stub_entry->stub_template;
+  switch (template_sequence[0].type)
     {
     case ARM_TYPE:
       if (!elf32_arm_output_stub_sym (osi, stub_name, addr, stub_entry->stub_size))
@@ -12871,7 +12886,7 @@ arm_map_one_stub (struct bfd_hash_entry * gen_entry,
   size = 0;
   for (i = 0; i < stub_entry->stub_template_size; i++)
     {
-      switch (template[i].type)
+      switch (template_sequence[i].type)
        {
        case ARM_TYPE:
          sym_type = ARM_MAP_ARM;
@@ -12891,14 +12906,14 @@ arm_map_one_stub (struct bfd_hash_entry * gen_entry,
          return FALSE;
        }
 
-      if (template[i].type != prev_type)
+      if (template_sequence[i].type != prev_type)
        {
-         prev_type = template[i].type;
+         prev_type = template_sequence[i].type;
          if (!elf32_arm_output_map_sym (osi, sym_type, addr + size))
            return FALSE;
        }
 
-      switch (template[i].type)
+      switch (template_sequence[i].type)
        {
        case ARM_TYPE:
        case THUMB32_TYPE:
@@ -13063,7 +13078,7 @@ elf32_arm_new_section_hook (bfd *abfd, asection *sec)
       _arm_elf_section_data *sdata;
       bfd_size_type amt = sizeof (*sdata);
 
-      sdata = bfd_zalloc (abfd, amt);
+      sdata = (_arm_elf_section_data *) bfd_zalloc (abfd, amt);
       if (sdata == NULL)
        return FALSE;
       sec->used_by_bfd = sdata;
@@ -13150,7 +13165,7 @@ make_branch_to_a8_stub (struct bfd_hash_entry *gen_entry,
   bfd_vma veneered_insn_loc, veneer_entry_loc;
   bfd_signed_vma branch_offset;
   bfd *abfd;
-  unsigned int index;
+  unsigned int target;
 
   stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
   data = (struct a8_branch_to_stub_data *) in_arg;
@@ -13175,7 +13190,7 @@ make_branch_to_a8_stub (struct bfd_hash_entry *gen_entry,
   branch_offset = veneer_entry_loc - veneered_insn_loc - 4;
 
   abfd = stub_entry->target_section->owner;
-  index = stub_entry->target_value;
+  target = stub_entry->target_value;
 
   /* We attempt to avoid this condition by setting stubs_always_after_branch
      in elf32_arm_size_stubs if we've enabled the Cortex-A8 erratum workaround.
@@ -13236,8 +13251,8 @@ make_branch_to_a8_stub (struct bfd_hash_entry *gen_entry,
       return FALSE;
     }
 
-  bfd_put_16 (abfd, (branch_insn >> 16) & 0xffff, &contents[index]);
-  bfd_put_16 (abfd, branch_insn & 0xffff, &contents[index + 2]);
+  bfd_put_16 (abfd, (branch_insn >> 16) & 0xffff, &contents[target]);
+  bfd_put_16 (abfd, branch_insn & 0xffff, &contents[target + 2]);
 
   return TRUE;
 }
@@ -13279,7 +13294,7 @@ elf32_arm_write_section (bfd *output_bfd,
       for (errnode = arm_data->erratumlist; errnode != 0;
            errnode = errnode->next)
         {
-          bfd_vma index = errnode->vma - offset;
+          bfd_vma target = errnode->vma - offset;
 
           switch (errnode->type)
             {
@@ -13292,7 +13307,7 @@ elf32_arm_write_section (bfd *output_bfd,
                                   | 0x0a000000;
 
                /* The instruction is before the label.  */
-               index -= 4;
+               target -= 4;
 
                /* Above offset included in -4 below.  */
                branch_to_veneer = errnode->u.b.veneer->vma
@@ -13304,10 +13319,10 @@ elf32_arm_write_section (bfd *output_bfd,
                                           "range"), output_bfd);
 
                 insn |= (branch_to_veneer >> 2) & 0xffffff;
-                contents[endianflip ^ index] = insn & 0xff;
-                contents[endianflip ^ (index + 1)] = (insn >> 8) & 0xff;
-                contents[endianflip ^ (index + 2)] = (insn >> 16) & 0xff;
-                contents[endianflip ^ (index + 3)] = (insn >> 24) & 0xff;
+                contents[endianflip ^ target] = insn & 0xff;
+                contents[endianflip ^ (target + 1)] = (insn >> 8) & 0xff;
+                contents[endianflip ^ (target + 2)] = (insn >> 16) & 0xff;
+                contents[endianflip ^ (target + 3)] = (insn >> 24) & 0xff;
               }
               break;
 
@@ -13327,17 +13342,17 @@ elf32_arm_write_section (bfd *output_bfd,
 
                 /* Original instruction.  */
                 insn = errnode->u.v.branch->u.b.vfp_insn;
-                contents[endianflip ^ index] = insn & 0xff;
-                contents[endianflip ^ (index + 1)] = (insn >> 8) & 0xff;
-                contents[endianflip ^ (index + 2)] = (insn >> 16) & 0xff;
-                contents[endianflip ^ (index + 3)] = (insn >> 24) & 0xff;
+                contents[endianflip ^ target] = insn & 0xff;
+                contents[endianflip ^ (target + 1)] = (insn >> 8) & 0xff;
+                contents[endianflip ^ (target + 2)] = (insn >> 16) & 0xff;
+                contents[endianflip ^ (target + 3)] = (insn >> 24) & 0xff;
 
                 /* Branch back to insn after original insn.  */
                 insn = 0xea000000 | ((branch_from_veneer >> 2) & 0xffffff);
-                contents[endianflip ^ (index + 4)] = insn & 0xff;
-                contents[endianflip ^ (index + 5)] = (insn >> 8) & 0xff;
-                contents[endianflip ^ (index + 6)] = (insn >> 16) & 0xff;
-                contents[endianflip ^ (index + 7)] = (insn >> 24) & 0xff;
+                contents[endianflip ^ (target + 4)] = insn & 0xff;
+                contents[endianflip ^ (target + 5)] = (insn >> 8) & 0xff;
+                contents[endianflip ^ (target + 6)] = (insn >> 16) & 0xff;
+                contents[endianflip ^ (target + 7)] = (insn >> 24) & 0xff;
               }
               break;
 
@@ -13355,7 +13370,7 @@ elf32_arm_write_section (bfd *output_bfd,
          size (before we merged duplicate entries and inserted EXIDX_CANTUNWIND
         markers) was sec->rawsize.  (This isn't the case if we perform no
         edits, then rawsize will be zero and we should use size).  */
-      bfd_byte *edited_contents = bfd_malloc (sec->size);
+      bfd_byte *edited_contents = (bfd_byte *) bfd_malloc (sec->size);
       unsigned int input_size = sec->rawsize ? sec->rawsize : sec->size;
       unsigned int in_index, out_index;
       bfd_vma add_to_offsets = 0;
@@ -13628,7 +13643,8 @@ elf32_arm_modify_segment_map (bfd *abfd,
        m = m->next;
       if (!m)
        {
-         m = bfd_zalloc (abfd, sizeof (struct elf_segment_map));
+         m = (struct elf_segment_map *)
+              bfd_zalloc (abfd, sizeof (struct elf_segment_map));
          if (m == NULL)
            return FALSE;
          m->p_type = PT_ARM_EXIDX;
@@ -13840,6 +13856,231 @@ elf32_arm_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
 #include "elf32-target.h"
 
 
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
+static bfd_boolean
+elf32_arm_merge_private_bfd_data (bfd * ibfd, bfd * obfd)
+{
+  flagword out_flags;
+  flagword in_flags;
+  bfd_boolean flags_compatible = TRUE;
+  asection *sec;
+
+  /* Check if we have the same endianess.  */
+  if (! _bfd_generic_verify_endian_match (ibfd, obfd))
+    return FALSE;
+
+  if (! is_arm_elf (ibfd) || ! is_arm_elf (obfd))
+    return TRUE;
+
+  if (!elf32_arm_merge_eabi_attributes (ibfd, obfd))
+    return FALSE;
+
+  /* The input BFD must have had its flags initialised.  */
+  /* The following seems bogus to me -- The flags are initialized in
+     the assembler but I don't think an elf_flags_init field is
+     written into the object.  */
+  /* BFD_ASSERT (elf_flags_init (ibfd)); */
+
+  in_flags  = elf_elfheader (ibfd)->e_flags;
+  out_flags = elf_elfheader (obfd)->e_flags;
+
+  /* In theory there is no reason why we couldn't handle this.  However
+     in practice it isn't even close to working and there is no real
+     reason to want it.  */
+  if (EF_ARM_EABI_VERSION (in_flags) >= EF_ARM_EABI_VER4
+      && !(ibfd->flags & DYNAMIC)
+      && (in_flags & EF_ARM_BE8))
+    {
+      _bfd_error_handler (_("error: %B is already in final BE8 format"),
+                         ibfd);
+      return FALSE;
+    }
+
+  if (!elf_flags_init (obfd))
+    {
+      /* If the input is the default architecture and had the default
+        flags then do not bother setting the flags for the output
+        architecture, instead allow future merges to do this.  If no
+        future merges ever set these flags then they will retain their
+         uninitialised values, which surprise surprise, correspond
+         to the default values.  */
+      if (bfd_get_arch_info (ibfd)->the_default
+         && elf_elfheader (ibfd)->e_flags == 0)
+       return TRUE;
+
+      elf_flags_init (obfd) = TRUE;
+      elf_elfheader (obfd)->e_flags = in_flags;
+
+      if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
+         && bfd_get_arch_info (obfd)->the_default)
+       return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
+
+      return TRUE;
+    }
+
+  /* Determine what should happen if the input ARM architecture
+     does not match the output ARM architecture.  */
+  if (! bfd_arm_merge_machines (ibfd, obfd))
+    return FALSE;
+
+  /* Identical flags must be compatible.  */
+  if (in_flags == out_flags)
+    return TRUE;
+
+  /* Check to see if the input BFD actually contains any sections.  If
+     not, its flags may not have been initialised either, but it
+     cannot actually cause any incompatiblity.  Do not short-circuit
+     dynamic objects; their section list may be emptied by
+    elf_link_add_object_symbols.
+
+    Also check to see if there are no code sections in the input.
+    In this case there is no need to check for code specific flags.
+    XXX - do we need to worry about floating-point format compatability
+    in data sections ?  */
+  if (!(ibfd->flags & DYNAMIC))
+    {
+      bfd_boolean null_input_bfd = TRUE;
+      bfd_boolean only_data_sections = TRUE;
+
+      for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+       {
+         /* Ignore synthetic glue sections.  */
+         if (strcmp (sec->name, ".glue_7")
+             && strcmp (sec->name, ".glue_7t"))
+           {
+             if ((bfd_get_section_flags (ibfd, sec)
+                  & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
+                 == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
+               only_data_sections = FALSE;
+
+             null_input_bfd = FALSE;
+             break;
+           }
+       }
+
+      if (null_input_bfd || only_data_sections)
+       return TRUE;
+    }
+
+  /* Complain about various flag mismatches.  */
+  if (!elf32_arm_versions_compatible (EF_ARM_EABI_VERSION (in_flags),
+                                     EF_ARM_EABI_VERSION (out_flags)))
+    {
+      _bfd_error_handler
+       (_("error: Source object %B has EABI version %d, but target %B has EABI version %d"),
+        ibfd, obfd,
+        (in_flags & EF_ARM_EABIMASK) >> 24,
+        (out_flags & EF_ARM_EABIMASK) >> 24);
+      return FALSE;
+    }
+
+  /* Not sure what needs to be checked for EABI versions >= 1.  */
+  /* VxWorks libraries do not use these flags.  */
+  if (get_elf_backend_data (obfd) != &elf32_arm_vxworks_bed
+      && get_elf_backend_data (ibfd) != &elf32_arm_vxworks_bed
+      && EF_ARM_EABI_VERSION (in_flags) == EF_ARM_EABI_UNKNOWN)
+    {
+      if ((in_flags & EF_ARM_APCS_26) != (out_flags & EF_ARM_APCS_26))
+       {
+         _bfd_error_handler
+           (_("error: %B is compiled for APCS-%d, whereas target %B uses APCS-%d"),
+            ibfd, obfd,
+            in_flags & EF_ARM_APCS_26 ? 26 : 32,
+            out_flags & EF_ARM_APCS_26 ? 26 : 32);
+         flags_compatible = FALSE;
+       }
+
+      if ((in_flags & EF_ARM_APCS_FLOAT) != (out_flags & EF_ARM_APCS_FLOAT))
+       {
+         if (in_flags & EF_ARM_APCS_FLOAT)
+           _bfd_error_handler
+             (_("error: %B passes floats in float registers, whereas %B passes them in integer registers"),
+              ibfd, obfd);
+         else
+           _bfd_error_handler
+             (_("error: %B passes floats in integer registers, whereas %B passes them in float registers"),
+              ibfd, obfd);
+
+         flags_compatible = FALSE;
+       }
+
+      if ((in_flags & EF_ARM_VFP_FLOAT) != (out_flags & EF_ARM_VFP_FLOAT))
+       {
+         if (in_flags & EF_ARM_VFP_FLOAT)
+           _bfd_error_handler
+             (_("error: %B uses VFP instructions, whereas %B does not"),
+              ibfd, obfd);
+         else
+           _bfd_error_handler
+             (_("error: %B uses FPA instructions, whereas %B does not"),
+              ibfd, obfd);
+
+         flags_compatible = FALSE;
+       }
+
+      if ((in_flags & EF_ARM_MAVERICK_FLOAT) != (out_flags & EF_ARM_MAVERICK_FLOAT))
+       {
+         if (in_flags & EF_ARM_MAVERICK_FLOAT)
+           _bfd_error_handler
+             (_("error: %B uses Maverick instructions, whereas %B does not"),
+              ibfd, obfd);
+         else
+           _bfd_error_handler
+             (_("error: %B does not use Maverick instructions, whereas %B does"),
+              ibfd, obfd);
+
+         flags_compatible = FALSE;
+       }
+
+#ifdef EF_ARM_SOFT_FLOAT
+      if ((in_flags & EF_ARM_SOFT_FLOAT) != (out_flags & EF_ARM_SOFT_FLOAT))
+       {
+         /* We can allow interworking between code that is VFP format
+            layout, and uses either soft float or integer regs for
+            passing floating point arguments and results.  We already
+            know that the APCS_FLOAT flags match; similarly for VFP
+            flags.  */
+         if ((in_flags & EF_ARM_APCS_FLOAT) != 0
+             || (in_flags & EF_ARM_VFP_FLOAT) == 0)
+           {
+             if (in_flags & EF_ARM_SOFT_FLOAT)
+               _bfd_error_handler
+                 (_("error: %B uses software FP, whereas %B uses hardware FP"),
+                  ibfd, obfd);
+             else
+               _bfd_error_handler
+                 (_("error: %B uses hardware FP, whereas %B uses software FP"),
+                  ibfd, obfd);
+
+             flags_compatible = FALSE;
+           }
+       }
+#endif
+
+      /* Interworking mismatch is only a warning.  */
+      if ((in_flags & EF_ARM_INTERWORK) != (out_flags & EF_ARM_INTERWORK))
+       {
+         if (in_flags & EF_ARM_INTERWORK)
+           {
+             _bfd_error_handler
+               (_("Warning: %B supports interworking, whereas %B does not"),
+                ibfd, obfd);
+           }
+         else
+           {
+             _bfd_error_handler
+               (_("Warning: %B does not support interworking, whereas %B does"),
+                ibfd, obfd);
+           }
+       }
+    }
+
+  return flags_compatible;
+}
+
+
 /* Symbian OS Targets.  */
 
 #undef  TARGET_LITTLE_SYM
This page took 0.054192 seconds and 4 git commands to generate.