* elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Warn if
[deliverable/binutils-gdb.git] / bfd / elf32-spu.c
index 25783c0df2d75518f899a44e721ef05748b5e6f9..df0b68ae22d149c7edbfbfe6887b40c77830e4ab 100644 (file)
@@ -704,7 +704,8 @@ needs_ovl_stub (const char *sym_name,
     return FALSE;
 
   if (sym_sec == NULL
-      || sym_sec->output_section == NULL)
+      || sym_sec->output_section == NULL
+      || spu_elf_section_data (sym_sec->output_section) == NULL)
     return FALSE;
 
   /* setjmp always goes via an overlay stub, because then the return
@@ -731,10 +732,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 +844,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 +1032,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;
@@ -1535,6 +1591,47 @@ spu_elf_relocate_section (bfd *output_bfd,
   return ret;
 }
 
+/* Adjust _SPUEAR_ syms to point at their overlay stubs.  */
+
+static bfd_boolean
+spu_elf_output_symbol_hook (struct bfd_link_info *info,
+                           const char *sym_name ATTRIBUTE_UNUSED,
+                           Elf_Internal_Sym *sym,
+                           asection *sym_sec ATTRIBUTE_UNUSED,
+                           struct elf_link_hash_entry *h)
+{
+  struct spu_link_hash_table *htab = spu_hash_table (info);
+
+  if (!info->relocatable
+      && htab->num_overlays != 0
+      && h != NULL
+      && (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)
+    {
+      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)
+       return FALSE;
+      sh = (struct spu_stub_hash_entry *)
+       bfd_hash_lookup (&htab->stub_hash_table, stub_name, FALSE, FALSE);
+      free (stub_name);
+      if (sh == NULL)
+       return TRUE;
+      sym->st_shndx
+       = _bfd_elf_section_from_bfd_section (htab->stub->output_section->owner,
+                                            htab->stub->output_section);
+      sym->st_value = (htab->stub->output_section->vma
+                      + htab->stub->output_offset
+                      + sh->off);
+    }
+
+  return TRUE;
+}
+
 static int spu_plugin = 0;
 
 void
@@ -1775,6 +1872,7 @@ spu_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED,
 #define elf_backend_gc_mark_hook               spu_elf_gc_mark_hook
 #define elf_backend_relocate_section           spu_elf_relocate_section
 #define elf_backend_symbol_processing          spu_elf_backend_symbol_processing
+#define elf_backend_link_output_symbol_hook    spu_elf_output_symbol_hook
 #define bfd_elf32_new_section_hook             spu_elf_new_section_hook
 #define bfd_elf32_bfd_link_hash_table_create   spu_elf_link_hash_table_create
 #define bfd_elf32_bfd_link_hash_table_free     spu_elf_link_hash_table_free
This page took 0.024098 seconds and 4 git commands to generate.