-/* Fill in the ila and br for a stub. On the last stub for a group,
- write the stub that sets the overlay number too. */
-
-static bfd_boolean
-write_one_stub (struct spu_stub_hash_entry *ent, struct bfd_link_info *info)
-{
- struct spu_link_hash_table *htab = spu_hash_table (info);
- asection *sec = htab->stub;
- asection *s = ent->target_section;
- unsigned int ovl;
- bfd_vma val;
-
- val = ent->target_off + s->output_offset + s->output_section->vma;
- bfd_put_32 (sec->owner, ILA_79 + ((val << 7) & 0x01ffff80),
- sec->contents + ent->off);
- val = ent->delta + 4;
- bfd_put_32 (sec->owner, BR + ((val << 5) & 0x007fff80),
- sec->contents + ent->off + 4);
-
- if (info->emitrelocations)
- {
- Elf_Internal_Rela *relocs, *r;
- struct bfd_elf_section_data *elfsec_data;
-
- elfsec_data = elf_section_data (sec);
- relocs = elfsec_data->relocs;
- if (relocs == NULL)
- {
- bfd_size_type relsize;
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hash;
- unsigned long symcount;
- bfd_vma amt;
-
- relsize = sec->reloc_count * sizeof (*relocs);
- relocs = bfd_alloc (sec->owner, relsize);
- if (relocs == NULL)
- return FALSE;
- elfsec_data->relocs = relocs;
- elfsec_data->rel_hdr.sh_size
- = sec->reloc_count * sizeof (Elf32_External_Rela);
- elfsec_data->rel_hdr.sh_entsize = sizeof (Elf32_External_Rela);
- sec->reloc_count = 0;
-
- /* Increase the size of symbol hash array on the bfd to
- which we attached our .stub section. This hack allows
- us to create relocs against global symbols. */
- symtab_hdr = &elf_tdata (sec->owner)->symtab_hdr;
- symcount = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
- symcount -= symtab_hdr->sh_info;
- amt = symcount * sizeof (*sym_hash);
- sym_hash = bfd_alloc (sec->owner, amt + sizeof (*sym_hash));
- if (sym_hash == NULL)
- return FALSE;
- memcpy (sym_hash, elf_sym_hashes (sec->owner), amt);
- sym_hash[symcount] = htab->ovly_load;
- htab->ovly_load_r_symndx = symcount + symtab_hdr->sh_info;
- elf_sym_hashes (sec->owner) = sym_hash;
- }
- r = relocs + sec->reloc_count;
- sec->reloc_count += 1;
- r->r_offset = ent->off + 4;
- r->r_info = ELF32_R_INFO (0, R_SPU_REL16);
- r->r_addend = (sec->output_section->vma
- + sec->output_offset
- + ent->off + 4
- + val);
- }
-
- /* If this is the last stub of this group, write stub2. */
- if (ent->delta == 0)
- {
- bfd_put_32 (sec->owner, NOP,
- sec->contents + ent->off + 4);
-
- ovl = spu_elf_section_data (s->output_section)->ovl_index;
- bfd_put_32 (sec->owner, ILA_78 + ((ovl << 7) & 0x01ffff80),
- sec->contents + ent->off + 8);
-
- val = (htab->ovly_load->root.u.def.section->output_section->vma
- + htab->ovly_load->root.u.def.section->output_offset
- + htab->ovly_load->root.u.def.value
- - (sec->output_section->vma
- + sec->output_offset
- + ent->off + 12));
-
- if (val + 0x20000 >= 0x40000)
- htab->stub_overflow = TRUE;
-
- bfd_put_32 (sec->owner, BR + ((val << 5) & 0x007fff80),
- sec->contents + ent->off + 12);
-
- if (info->emitrelocations)
- {
- Elf_Internal_Rela *relocs, *r;
- struct bfd_elf_section_data *elfsec_data;
-
- elfsec_data = elf_section_data (sec);
- relocs = elfsec_data->relocs;
- /* The last branch is overwritten, so overwrite its reloc too. */
- r = relocs + sec->reloc_count - 1;
- r->r_offset = ent->off + 12;
- r->r_info = ELF32_R_INFO (htab->ovly_load_r_symndx, R_SPU_REL16);
- r->r_addend = 0;
- }
- }
-
- if (htab->emit_stub_syms)
- {
- struct elf_link_hash_entry *h;
- size_t len1, len2;
- char *name;
-
- len1 = sizeof ("00000000.ovl_call.") - 1;
- len2 = strlen (ent->root.string);
- name = bfd_malloc (len1 + len2 + 1);
- if (name == NULL)
- return FALSE;
- memcpy (name, "00000000.ovl_call.", len1);
- memcpy (name + len1, ent->root.string, len2 + 1);
- h = elf_link_hash_lookup (&htab->elf, name, TRUE, TRUE, FALSE);
- free (name);
- if (h == NULL)
- return FALSE;
- if (h->root.type == bfd_link_hash_new)
- {
- h->root.type = bfd_link_hash_defined;
- h->root.u.def.section = sec;
- h->root.u.def.value = ent->off;
- h->size = (ent->delta == 0
- ? SIZEOF_STUB1 + SIZEOF_STUB2 : SIZEOF_STUB1);
- h->type = STT_FUNC;
- h->ref_regular = 1;
- h->def_regular = 1;
- h->ref_regular_nonweak = 1;
- h->forced_local = 1;
- h->non_elf = 0;
- }
- }
-
- return TRUE;
-}
-