2006-12-13 Paul Brook <paul@codesourcery.com>
[binutils-gdb.git] / bfd / elf32-arm.c
index f8eff7089fcefe96d8dea4b08de2ba717c3c4deb..881bd6013e944e2649a28b79f5830a420613e0ba 100644 (file)
@@ -2429,7 +2429,7 @@ elf32_arm_link_hash_table_create (bfd *abfd)
 static struct elf_link_hash_entry *
 find_thumb_glue (struct bfd_link_info *link_info,
                 const char *name,
-                bfd *input_bfd)
+                char **error_message)
 {
   char *tmp_name;
   struct elf_link_hash_entry *hash;
@@ -2449,9 +2449,8 @@ find_thumb_glue (struct bfd_link_info *link_info,
     (&(hash_table)->root, tmp_name, FALSE, FALSE, TRUE);
 
   if (hash == NULL)
-    /* xgettext:c-format */
-    (*_bfd_error_handler) (_("%B: unable to find THUMB glue '%s' for `%s'"),
-                          input_bfd, tmp_name, name);
+    asprintf (error_message, _("unable to find THUMB glue '%s' for '%s'"),
+             tmp_name, name);
 
   free (tmp_name);
 
@@ -2463,7 +2462,7 @@ find_thumb_glue (struct bfd_link_info *link_info,
 static struct elf_link_hash_entry *
 find_arm_glue (struct bfd_link_info *link_info,
               const char *name,
-              bfd *input_bfd)
+              char **error_message)
 {
   char *tmp_name;
   struct elf_link_hash_entry *myh;
@@ -2483,9 +2482,8 @@ find_arm_glue (struct bfd_link_info *link_info,
     (&(hash_table)->root, tmp_name, FALSE, FALSE, TRUE);
 
   if (myh == NULL)
-    /* xgettext:c-format */
-    (*_bfd_error_handler) (_("%B: unable to find ARM glue '%s' for `%s'"),
-                          input_bfd, tmp_name, name);
+    asprintf (error_message, _("unable to find ARM glue '%s' for '%s'"),
+             tmp_name, name);
 
   free (tmp_name);
 
@@ -2828,8 +2826,7 @@ static void check_use_blx(struct elf32_arm_link_hash_table *globals)
 
 bfd_boolean
 bfd_elf32_arm_process_before_allocation (bfd *abfd,
-                                        struct bfd_link_info *link_info,
-                                        int byteswap_code)
+                                        struct bfd_link_info *link_info)
 {
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Rela *internal_relocs = NULL;
@@ -2852,13 +2849,12 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd,
   BFD_ASSERT (globals != NULL);
   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
 
-  if (byteswap_code && !bfd_big_endian (abfd))
+  if (globals->byteswap_code && !bfd_big_endian (abfd))
     {
       _bfd_error_handler (_("%B: BE8 images only valid in big-endian mode."),
                          abfd);
       return FALSE;
     }
-  globals->byteswap_code = byteswap_code;
 
   /* Rummage around all the relocs and map the glue vectors.  */
   sec = abfd->sections;
@@ -2934,19 +2930,9 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd,
          if (h == NULL)
            continue;
 
-         /* If the call will go through a PLT entry then we do not
-            need glue.  We have to do a fairly complicated check
-            here, since we don't determine this finally (by setting
-            plt.offset) until later; this test should be kept in sync
-            with elf32_arm_adjust_dynamic_symbol.  */
-         if (globals->splt != NULL
-             && h->plt.refcount > 0
-             && (h->type == STT_FUNC
-                 || h->type == STT_ARM_TFUNC
-                 || h->needs_plt)
-             && !SYMBOL_CALLS_LOCAL (link_info, h)
-             && !(ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
-                  && h->root.type == bfd_link_hash_undefweak))
+         /* If the call will go through a PLT entry then we do not need
+            glue.  */
+         if (globals->splt != NULL && h->plt.offset != (bfd_vma) -1)
            continue;
 
          switch (r_type)
@@ -3126,7 +3112,8 @@ elf32_thumb_to_arm_stub (struct bfd_link_info * info,
                         asection *             sym_sec,
                         bfd_vma                offset,
                         bfd_signed_vma         addend,
-                        bfd_vma                val)
+                        bfd_vma                val,
+                        char **error_message)
 {
   asection * s = 0;
   bfd_vma my_offset;
@@ -3135,7 +3122,7 @@ elf32_thumb_to_arm_stub (struct bfd_link_info * info,
   struct elf_link_hash_entry * myh;
   struct elf32_arm_link_hash_table * globals;
 
-  myh = find_thumb_glue (info, name, input_bfd);
+  myh = find_thumb_glue (info, name, error_message);
   if (myh == NULL)
     return FALSE;
 
@@ -3230,14 +3217,15 @@ elf32_arm_create_thumb_stub (struct bfd_link_info * info,
                             bfd *                  output_bfd,
                             asection *             sym_sec,
                             bfd_vma                val,
-                            asection               *s)
+                            asection               *s,
+                            char **error_message)
 {
   bfd_vma my_offset;
   long int ret_offset;
   struct elf_link_hash_entry * myh;
   struct elf32_arm_link_hash_table * globals;
 
-  myh = find_arm_glue (info, name, input_bfd);
+  myh = find_arm_glue (info, name, error_message);
   if (myh == NULL)
     return NULL;
 
@@ -3315,7 +3303,8 @@ elf32_arm_to_thumb_stub (struct bfd_link_info * info,
                         asection *             sym_sec,
                         bfd_vma                offset,
                         bfd_signed_vma         addend,
-                        bfd_vma                val)
+                        bfd_vma                val,
+                        char **error_message)
 {
   unsigned long int tmp;
   bfd_vma my_offset;
@@ -3336,7 +3325,7 @@ elf32_arm_to_thumb_stub (struct bfd_link_info * info,
   BFD_ASSERT (s->output_section != NULL);
 
   myh = elf32_arm_create_thumb_stub (info, name, input_bfd, output_bfd,
-                                    sym_sec, val, s);
+                                    sym_sec, val, s, error_message);
   if (!myh)
     return FALSE;
 
@@ -3372,6 +3361,7 @@ elf32_arm_to_thumb_export_stub (struct elf_link_hash_entry *h, void * inf)
   struct elf32_arm_link_hash_table * globals;
   asection *sec;
   bfd_vma val;
+  char *error_message;
 
   eh = elf32_arm_hash_entry(h);
   /* Allocate stubs for exported Thumb functions on v4t.  */
@@ -3390,11 +3380,15 @@ elf32_arm_to_thumb_export_stub (struct elf_link_hash_entry *h, void * inf)
   BFD_ASSERT (s->output_section != NULL);
 
   sec = eh->export_glue->root.u.def.section;
+
+  BFD_ASSERT (sec->output_section != NULL);
+
   val = eh->export_glue->root.u.def.value + sec->output_offset
        + sec->output_section->vma;
   myh = elf32_arm_create_thumb_stub (info, h->root.root.string,
                                     h->root.u.def.section->owner,
-                                    globals->obfd, sec, val, s);
+                                    globals->obfd, sec, val, s,
+                                    &error_message);
   BFD_ASSERT (myh);
   return TRUE;
 }
@@ -3575,7 +3569,8 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                               const char *                 sym_name,
                               int                          sym_flags,
                               struct elf_link_hash_entry * h,
-                              bfd_boolean *                unresolved_reloc_p)
+                              bfd_boolean *                unresolved_reloc_p,
+                              char **error_message)
 {
   unsigned long                 r_type = howto->type;
   unsigned long                 r_symndx;
@@ -3847,11 +3842,14 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
              /* Check for Arm calling Thumb function.  */
              if (sym_flags == STT_ARM_TFUNC)
                {
-                 elf32_arm_to_thumb_stub (info, sym_name, input_bfd,
-                                          output_bfd, input_section,
-                                          hit_data, sym_sec, rel->r_offset,
-                                          signed_addend, value);
-                 return bfd_reloc_ok;
+                 if (elf32_arm_to_thumb_stub (info, sym_name, input_bfd,
+                                              output_bfd, input_section,
+                                              hit_data, sym_sec, rel->r_offset,
+                                              signed_addend, value,
+                                              error_message))
+                   return bfd_reloc_ok;
+                 else
+                   return bfd_reloc_dangerous;
                }
            }
 
@@ -4143,7 +4141,8 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                  }
                else if (elf32_thumb_to_arm_stub
                    (info, sym_name, input_bfd, output_bfd, input_section,
-                    hit_data, sym_sec, rel->r_offset, signed_addend, value))
+                    hit_data, sym_sec, rel->r_offset, signed_addend, value,
+                    error_message))
                  return bfd_reloc_ok;
                else
                  return bfd_reloc_dangerous;
@@ -5654,6 +5653,7 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
       arelent                      bfd_reloc;
       char                         sym_type;
       bfd_boolean                  unresolved_reloc = FALSE;
+      char *error_message = NULL;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
       r_type   = ELF32_R_TYPE (rel->r_info);
@@ -5787,7 +5787,7 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
                                         relocation, info, sec, name,
                                         (h ? ELF_ST_TYPE (h->type) :
                                          ELF_ST_TYPE (sym->st_info)), h,
-                                        &unresolved_reloc);
+                                        &unresolved_reloc, &error_message);
 
       /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
         because such sections are not SEC_ALLOC and thus ld.so will
@@ -5808,8 +5808,6 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
 
       if (r != bfd_reloc_ok)
        {
-         const char * msg = (const char *) 0;
-
          switch (r)
            {
            case bfd_reloc_overflow:
@@ -5833,24 +5831,25 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
              break;
 
            case bfd_reloc_outofrange:
-             msg = _("internal error: out of range error");
+             error_message = _("out of range");
              goto common_error;
 
            case bfd_reloc_notsupported:
-             msg = _("internal error: unsupported relocation error");
+             error_message = _("unsupported relocation");
              goto common_error;
 
            case bfd_reloc_dangerous:
-             msg = _("internal error: dangerous error");
+             /* error_message should already be set.  */
              goto common_error;
 
            default:
-             msg = _("internal error: unknown error");
+             error_message = _("unknown error");
              /* fall through */
 
            common_error:
-             if (!((*info->callbacks->warning)
-                   (info, msg, name, input_bfd, input_section,
+             BFD_ASSERT (error_message != NULL);
+             if (!((*info->callbacks->reloc_dangerous)
+                   (info, error_message, input_bfd, input_section,
                     rel->r_offset)))
                return FALSE;
              break;
@@ -6044,8 +6043,8 @@ copy_eabi_attributes (bfd *ibfd, bfd *obfd)
   aeabi_attribute_list *list;
   int i;
 
-  in_attr = elf32_arm_tdata (ibfd)->known_eabi_attributes;
-  out_attr = elf32_arm_tdata (obfd)->known_eabi_attributes;
+  in_attr = &elf32_arm_tdata (ibfd)->known_eabi_attributes[4];
+  out_attr = &elf32_arm_tdata (obfd)->known_eabi_attributes[4];
   for (i = 4; i < NUM_KNOWN_ATTRIBUTES; i++)
     {
       out_attr->i = in_attr->i;
@@ -6176,17 +6175,18 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
   static const int order_312[3] = {3, 1, 2};
   int i;
 
-  if (!elf32_arm_tdata (ibfd)->known_eabi_attributes[0].i)
+  if (!elf32_arm_tdata (obfd)->known_eabi_attributes[0].i)
     {
       /* This is the first object.  Copy the attributes.  */
       copy_eabi_attributes (ibfd, obfd);
+
+      /* Use the Tag_null value to indicate the attributes have been
+        initialized.  */
+      elf32_arm_tdata (obfd)->known_eabi_attributes[0].i = 1;
+
       return TRUE;
     }
 
-  /* Use the Tag_null value to indicate the attributes have been
-     initialized.  */
-  elf32_arm_tdata (ibfd)->known_eabi_attributes[0].i = 1;
-
   in_attr = elf32_arm_tdata (ibfd)->known_eabi_attributes;
   out_attr = elf32_arm_tdata (obfd)->known_eabi_attributes;
   /* This needs to happen before Tag_ABI_FP_number_model is merged.  */
@@ -6211,8 +6211,11 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
        {
        case Tag_CPU_raw_name:
        case Tag_CPU_name:
-         /* Use whichever has the greatest architecture requirements.  */
-         if (in_attr[Tag_CPU_arch].i > out_attr[Tag_CPU_arch].i)
+         /* Use whichever has the greatest architecture requirements.  We
+            won't necessarily have both the above tags, so make sure input
+            name is non-NULL.  */
+         if (in_attr[Tag_CPU_arch].i > out_attr[Tag_CPU_arch].i
+             && in_attr[i].s)
            out_attr[i].s = attr_strdup(obfd, in_attr[i].s);
          break;
 
@@ -6264,7 +6267,8 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
            }
          break;
        case Tag_ABI_PCS_R9_use:
-         if (out_attr[i].i != AEABI_R9_unused
+         if (in_attr[i].i != out_attr[i].i
+             && out_attr[i].i != AEABI_R9_unused
              && in_attr[i].i != AEABI_R9_unused)
            {
              _bfd_error_handler
@@ -7748,6 +7752,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 
   /* Allocate stubs for exported Thumb functions on v4t.  */
   if (!htab->use_blx && h->dynindx != -1
+      && h->def_regular
       && ELF_ST_TYPE (h->type) == STT_ARM_TFUNC
       && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
     {
@@ -7909,6 +7914,16 @@ elf32_arm_readonly_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
   return TRUE;
 }
 
+void
+bfd_elf32_arm_set_byteswap_code (struct bfd_link_info *info,
+                                int byteswap_code)
+{
+  struct elf32_arm_link_hash_table *globals;
+
+  globals = elf32_arm_hash_table (info);
+  globals->byteswap_code = byteswap_code;
+}
+
 /* Set the sizes of the dynamic sections.  */
 
 static bfd_boolean
@@ -8024,6 +8039,13 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
      sym dynamic relocs.  */
   elf_link_hash_traverse (& htab->root, allocate_dynrelocs, info);
 
+  /* Here we rummage through the found bfds to collect glue information.  */
+  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+    if (!bfd_elf32_arm_process_before_allocation (ibfd, info))
+      /* xgettext:c-format */
+      _bfd_error_handler (_("Errors encountered processing file %s"),
+                         ibfd->filename);
+
   /* The check_relocs and adjust_dynamic_symbol entry points have
      determined the sizes of the various dynamic sections.  Allocate
      memory for them.  */