* elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Warn if
[deliverable/binutils-gdb.git] / bfd / elf32-spu.c
index a48a0bcaa92ff7af5fde219f944c63f175828e56..df0b68ae22d149c7edbfbfe6887b40c77830e4ab 100644 (file)
@@ -142,6 +142,20 @@ spu_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   return elf_howto_table + spu_elf_bfd_to_reloc_type (code);
 }
 
+static reloc_howto_type *
+spu_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                          const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++)
+    if (elf_howto_table[i].name != NULL
+       && strcasecmp (elf_howto_table[i].name, r_name) == 0)
+      return &elf_howto_table[i];
+
+  return NULL;
+}
+
 /* Apply R_SPU_REL9 and R_SPU_REL9I relocs.  */
 
 static bfd_reloc_status_type
@@ -690,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
@@ -717,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.  */
 
@@ -780,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;
@@ -966,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;
@@ -1521,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
@@ -1756,10 +1867,12 @@ spu_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED,
 #define elf_backend_can_gc_sections    1
 
 #define bfd_elf32_bfd_reloc_type_lookup                spu_elf_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup        spu_elf_reloc_name_lookup
 #define elf_info_to_howto                      spu_elf_info_to_howto
 #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.025454 seconds and 4 git commands to generate.