aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-spu.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2007-03-26 12:50:09 +0000
committerAlan Modra <amodra@gmail.com>2007-03-26 12:50:09 +0000
commitf4b39977c8162c118d6f8ebfacd1fc5850ec2842 (patch)
tree5d37e436f68cee62ec4a01b704b36200cca87c26 /bfd/elf32-spu.c
parent05e9452c8210da86b07b621562f4a89bd6f637d4 (diff)
downloadgdb-f4b39977c8162c118d6f8ebfacd1fc5850ec2842.zip
gdb-f4b39977c8162c118d6f8ebfacd1fc5850ec2842.tar.gz
gdb-f4b39977c8162c118d6f8ebfacd1fc5850ec2842.tar.bz2
* 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.
Diffstat (limited to 'bfd/elf32-spu.c')
-rw-r--r--bfd/elf32-spu.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/bfd/elf32-spu.c b/bfd/elf32-spu.c
index 25783c0..d05aaef 100644
--- a/bfd/elf32-spu.c
+++ b/bfd/elf32-spu.c
@@ -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;