* elf32-spu.c (struct stubarr): Add stub_hash_table and err fields.
authorAlan Modra <amodra@gmail.com>
Mon, 26 Mar 2007 12:50:09 +0000 (12:50 +0000)
committerAlan Modra <amodra@gmail.com>
Mon, 26 Mar 2007 12:50:09 +0000 (12:50 +0000)
(allocate_spuear_stubs): New function.
(spu_elf_size_stubs): Call allocate_spuear_stubs.

bfd/ChangeLog
bfd/elf32-spu.c

index 1301c1082c32bf4587a22fba1b75f6534163801a..bc127a97e0812d1191e7f1d4c25d16e2cbb241ef 100644 (file)
@@ -1,3 +1,9 @@
+2007-03-26  Alan Modra  <amodra@bigpond.net.au>
+
+       * elf32-spu.c (struct stubarr): Add stub_hash_table and err fields.
+       (allocate_spuear_stubs): New function.
+       (spu_elf_size_stubs): Call allocate_spuear_stubs.
+
 2007-03-26  Alan Modra  <amodra@bigpond.net.au>
 
        * aout-adobe.c (aout_32_bfd_reloc_name_lookup): Define.
index 25783c0df2d75518f899a44e721ef05748b5e6f9..d05aaef54814b41f769b46c47a5fc18f5e3f7c24 100644 (file)
@@ -731,10 +731,59 @@ needs_ovl_stub (const char *sym_name,
 }
 
 struct stubarr {
+  struct bfd_hash_table *stub_hash_table;
   struct spu_stub_hash_entry **sh;
   unsigned int count;
+  int err;
 };
 
+/* Called via elf_link_hash_traverse to allocate stubs for any _SPUEAR_
+   symbols.  */
+
+static bfd_boolean
+allocate_spuear_stubs (struct elf_link_hash_entry *h, void *inf)
+{
+  /* Symbols starting with _SPUEAR_ need a stub because they may be
+     invoked by the PPU.  */
+  if ((h->root.type == bfd_link_hash_defined
+       || h->root.type == bfd_link_hash_defweak)
+      && h->def_regular
+      && strncmp (h->root.root.string, "_SPUEAR_", 8) == 0)
+    {
+      struct stubarr *stubs = inf;
+      static Elf_Internal_Rela zero_rel;
+      char *stub_name = spu_stub_name (h->root.u.def.section, h, &zero_rel);
+      struct spu_stub_hash_entry *sh;
+
+      if (stub_name == NULL)
+       {
+         stubs->err = 1;
+         return FALSE;
+       }
+
+      sh = (struct spu_stub_hash_entry *)
+       bfd_hash_lookup (stubs->stub_hash_table, stub_name, TRUE, FALSE);
+      if (sh == NULL)
+       {
+         free (stub_name);
+         return FALSE;
+       }
+
+      /* If this entry isn't new, we already have a stub.  */
+      if (sh->target_section != NULL)
+       {
+         free (stub_name);
+         return TRUE;
+       }
+
+      sh->target_section = h->root.u.def.section;
+      sh->target_off = h->root.u.def.value;
+      stubs->count += 1;
+    }
+  
+  return TRUE;
+}
+
 /* Called via bfd_hash_traverse to set up pointers to all symbols
    in the stub hash table.  */
 
@@ -794,7 +843,9 @@ spu_elf_size_stubs (bfd *output_bfd,
   flagword flags;
 
   htab->non_overlay_stubs = non_overlay_stubs;
+  stubs.stub_hash_table = &htab->stub_hash_table;
   stubs.count = 0;
+  stubs.err = 0;
   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
     {
       extern const bfd_target bfd_elf32_spu_vec;
@@ -980,6 +1031,10 @@ spu_elf_size_stubs (bfd *output_bfd,
        }
     }
 
+  elf_link_hash_traverse (&htab->elf, allocate_spuear_stubs, &stubs);
+  if (stubs.err)
+    return FALSE;
+
   *stub = NULL;
   if (stubs.count == 0)
     return TRUE;