diff options
author | Alan Modra <amodra@gmail.com> | 2007-03-26 12:50:09 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2007-03-26 12:50:09 +0000 |
commit | f4b39977c8162c118d6f8ebfacd1fc5850ec2842 (patch) | |
tree | 5d37e436f68cee62ec4a01b704b36200cca87c26 /bfd/elf32-spu.c | |
parent | 05e9452c8210da86b07b621562f4a89bd6f637d4 (diff) | |
download | gdb-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.c | 55 |
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; |