Back to index

cell-binutils  2.17cvs20070401
elf32-spu.c
Go to the documentation of this file.
00001 /* SPU specific support for 32-bit ELF
00002 
00003    Copyright 2006, 2007 Free Software Foundation, Inc.
00004 
00005    This file is part of BFD, the Binary File Descriptor library.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License along
00018    with this program; if not, write to the Free Software Foundation, Inc.,
00019    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00020 
00021 #include "bfd.h"
00022 #include "sysdep.h"
00023 #include "bfdlink.h"
00024 #include "libbfd.h"
00025 #include "elf-bfd.h"
00026 #include "elf/spu.h"
00027 #include "elf32-spu.h"
00028 
00029 /* We use RELA style relocs.  Don't define USE_REL.  */
00030 
00031 static bfd_reloc_status_type spu_elf_rel9 (bfd *, arelent *, asymbol *,
00032                                       void *, asection *,
00033                                       bfd *, char **);
00034 
00035 /* Values of type 'enum elf_spu_reloc_type' are used to index this
00036    array, so it must be declared in the order of that type.  */
00037 
00038 static reloc_howto_type elf_howto_table[] = {
00039   HOWTO (R_SPU_NONE,       0, 0,  0, FALSE,  0, complain_overflow_dont,
00040         bfd_elf_generic_reloc, "SPU_NONE",
00041         FALSE, 0, 0x00000000, FALSE),
00042   HOWTO (R_SPU_ADDR10,     4, 2, 10, FALSE, 14, complain_overflow_bitfield,
00043         bfd_elf_generic_reloc, "SPU_ADDR10",
00044         FALSE, 0, 0x00ffc000, FALSE),
00045   HOWTO (R_SPU_ADDR16,     2, 2, 16, FALSE,  7, complain_overflow_bitfield,
00046         bfd_elf_generic_reloc, "SPU_ADDR16",
00047         FALSE, 0, 0x007fff80, FALSE),
00048   HOWTO (R_SPU_ADDR16_HI, 16, 2, 16, FALSE,  7, complain_overflow_bitfield,
00049         bfd_elf_generic_reloc, "SPU_ADDR16_HI",
00050         FALSE, 0, 0x007fff80, FALSE),
00051   HOWTO (R_SPU_ADDR16_LO,  0, 2, 16, FALSE,  7, complain_overflow_dont,
00052         bfd_elf_generic_reloc, "SPU_ADDR16_LO",
00053         FALSE, 0, 0x007fff80, FALSE),
00054   HOWTO (R_SPU_ADDR18,     0, 2, 18, FALSE,  7, complain_overflow_bitfield,
00055         bfd_elf_generic_reloc, "SPU_ADDR18",
00056         FALSE, 0, 0x01ffff80, FALSE),
00057   HOWTO (R_SPU_ADDR32,   0, 2, 32, FALSE,  0, complain_overflow_dont,
00058         bfd_elf_generic_reloc, "SPU_ADDR32",
00059         FALSE, 0, 0xffffffff, FALSE),
00060   HOWTO (R_SPU_REL16,      2, 2, 16,  TRUE,  7, complain_overflow_bitfield,
00061         bfd_elf_generic_reloc, "SPU_REL16",
00062         FALSE, 0, 0x007fff80, TRUE),
00063   HOWTO (R_SPU_ADDR7,      0, 2,  7, FALSE, 14, complain_overflow_dont,
00064         bfd_elf_generic_reloc, "SPU_ADDR7",
00065         FALSE, 0, 0x001fc000, FALSE),
00066   HOWTO (R_SPU_REL9,       2, 2,  9,  TRUE,  0, complain_overflow_signed,
00067         spu_elf_rel9,          "SPU_REL9",
00068         FALSE, 0, 0x0180007f, TRUE),
00069   HOWTO (R_SPU_REL9I,      2, 2,  9,  TRUE,  0, complain_overflow_signed,
00070         spu_elf_rel9,          "SPU_REL9I",
00071         FALSE, 0, 0x0000c07f, TRUE),
00072   HOWTO (R_SPU_ADDR10I,    0, 2, 10, FALSE, 14, complain_overflow_signed,
00073         bfd_elf_generic_reloc, "SPU_ADDR10I",
00074         FALSE, 0, 0x00ffc000, FALSE),
00075   HOWTO (R_SPU_ADDR16I,    0, 2, 16, FALSE,  7, complain_overflow_signed,
00076         bfd_elf_generic_reloc, "SPU_ADDR16I",
00077         FALSE, 0, 0x007fff80, FALSE),
00078   HOWTO (R_SPU_REL32,   0, 2, 32, TRUE,  0, complain_overflow_dont,
00079         bfd_elf_generic_reloc, "SPU_REL32",
00080         FALSE, 0, 0xffffffff, TRUE),
00081 };
00082 
00083 static struct bfd_elf_special_section const spu_elf_special_sections[] = {
00084   { ".toe", 4, 0, SHT_NOBITS, SHF_ALLOC },
00085   { NULL, 0, 0, 0, 0 }
00086 };
00087 
00088 static enum elf_spu_reloc_type
00089 spu_elf_bfd_to_reloc_type (bfd_reloc_code_real_type code)
00090 {
00091   switch (code)
00092     {
00093     default:
00094       return R_SPU_NONE;
00095     case BFD_RELOC_SPU_IMM10W:
00096       return R_SPU_ADDR10;
00097     case BFD_RELOC_SPU_IMM16W:
00098       return R_SPU_ADDR16;
00099     case BFD_RELOC_SPU_LO16:
00100       return R_SPU_ADDR16_LO;
00101     case BFD_RELOC_SPU_HI16:
00102       return R_SPU_ADDR16_HI;
00103     case BFD_RELOC_SPU_IMM18:
00104       return R_SPU_ADDR18;
00105     case BFD_RELOC_SPU_PCREL16:
00106       return R_SPU_REL16;
00107     case BFD_RELOC_SPU_IMM7:
00108       return R_SPU_ADDR7;
00109     case BFD_RELOC_SPU_IMM8:
00110       return R_SPU_NONE;
00111     case BFD_RELOC_SPU_PCREL9a:
00112       return R_SPU_REL9;
00113     case BFD_RELOC_SPU_PCREL9b:
00114       return R_SPU_REL9I;
00115     case BFD_RELOC_SPU_IMM10:
00116       return R_SPU_ADDR10I;
00117     case BFD_RELOC_SPU_IMM16:
00118       return R_SPU_ADDR16I;
00119     case BFD_RELOC_32:
00120       return R_SPU_ADDR32;
00121     case BFD_RELOC_32_PCREL:
00122       return R_SPU_REL32;
00123     }
00124 }
00125 
00126 static void
00127 spu_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
00128                      arelent *cache_ptr,
00129                      Elf_Internal_Rela *dst)
00130 {
00131   enum elf_spu_reloc_type r_type;
00132 
00133   r_type = (enum elf_spu_reloc_type) ELF32_R_TYPE (dst->r_info);
00134   BFD_ASSERT (r_type < R_SPU_max);
00135   cache_ptr->howto = &elf_howto_table[(int) r_type];
00136 }
00137 
00138 static reloc_howto_type *
00139 spu_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00140                         bfd_reloc_code_real_type code)
00141 {
00142   return elf_howto_table + spu_elf_bfd_to_reloc_type (code);
00143 }
00144 
00145 static reloc_howto_type *
00146 spu_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00147                         const char *r_name)
00148 {
00149   unsigned int i;
00150 
00151   for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++)
00152     if (elf_howto_table[i].name != NULL
00153        && strcasecmp (elf_howto_table[i].name, r_name) == 0)
00154       return &elf_howto_table[i];
00155 
00156   return NULL;
00157 }
00158 
00159 /* Apply R_SPU_REL9 and R_SPU_REL9I relocs.  */
00160 
00161 static bfd_reloc_status_type
00162 spu_elf_rel9 (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
00163              void *data, asection *input_section,
00164              bfd *output_bfd, char **error_message)
00165 {
00166   bfd_size_type octets;
00167   bfd_vma val;
00168   long insn;
00169 
00170   /* If this is a relocatable link (output_bfd test tells us), just
00171      call the generic function.  Any adjustment will be done at final
00172      link time.  */
00173   if (output_bfd != NULL)
00174     return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
00175                               input_section, output_bfd, error_message);
00176 
00177   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
00178     return bfd_reloc_outofrange;
00179   octets = reloc_entry->address * bfd_octets_per_byte (abfd);
00180 
00181   /* Get symbol value.  */
00182   val = 0;
00183   if (!bfd_is_com_section (symbol->section))
00184     val = symbol->value;
00185   if (symbol->section->output_section)
00186     val += symbol->section->output_section->vma;
00187 
00188   val += reloc_entry->addend;
00189 
00190   /* Make it pc-relative.  */
00191   val -= input_section->output_section->vma + input_section->output_offset;
00192 
00193   val >>= 2;
00194   if (val + 256 >= 512)
00195     return bfd_reloc_overflow;
00196 
00197   insn = bfd_get_32 (abfd, (bfd_byte *) data + octets);
00198 
00199   /* Move two high bits of value to REL9I and REL9 position.
00200      The mask will take care of selecting the right field.  */
00201   val = (val & 0x7f) | ((val & 0x180) << 7) | ((val & 0x180) << 16);
00202   insn &= ~reloc_entry->howto->dst_mask;
00203   insn |= val & reloc_entry->howto->dst_mask;
00204   bfd_put_32 (abfd, insn, (bfd_byte *) data + octets);
00205   return bfd_reloc_ok;
00206 }
00207 
00208 static bfd_boolean
00209 spu_elf_new_section_hook (bfd *abfd, asection *sec)
00210 {
00211   if (!sec->used_by_bfd)
00212     {
00213       struct _spu_elf_section_data *sdata;
00214 
00215       sdata = bfd_zalloc (abfd, sizeof (*sdata));
00216       if (sdata == NULL)
00217        return FALSE;
00218       sec->used_by_bfd = sdata;
00219     }
00220 
00221   return _bfd_elf_new_section_hook (abfd, sec);
00222 }
00223 
00224 /* Specially mark defined symbols named _EAR_* with BSF_KEEP so that
00225    strip --strip-unneeded will not remove them.  */
00226 
00227 static void
00228 spu_elf_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, asymbol *sym)
00229 {
00230   if (sym->name != NULL
00231       && sym->section != bfd_abs_section_ptr
00232       && strncmp (sym->name, "_EAR_", 5) == 0)
00233     sym->flags |= BSF_KEEP;
00234 }
00235 
00236 /* SPU ELF linker hash table.  */
00237 
00238 struct spu_link_hash_table
00239 {
00240   struct elf_link_hash_table elf;
00241 
00242   /* The stub hash table.  */
00243   struct bfd_hash_table stub_hash_table;
00244 
00245   /* Shortcuts to overlay sections.  */
00246   asection *stub;
00247   asection *ovtab;
00248 
00249   struct elf_link_hash_entry *ovly_load;
00250 
00251   /* An array of two output sections per overlay region, chosen such that
00252      the first section vma is the overlay buffer vma (ie. the section has
00253      the lowest vma in the group that occupy the region), and the second
00254      section vma+size specifies the end of the region.  We keep pointers
00255      to sections like this because section vmas may change when laying
00256      them out.  */
00257   asection **ovl_region;
00258 
00259   /* Number of overlay buffers.  */
00260   unsigned int num_buf;
00261 
00262   /* Total number of overlays.  */
00263   unsigned int num_overlays;
00264 
00265   /* Set if we should emit symbols for stubs.  */
00266   unsigned int emit_stub_syms:1;
00267 
00268   /* Set if we want stubs on calls out of overlay regions to
00269      non-overlay regions.  */
00270   unsigned int non_overlay_stubs : 1;
00271 
00272   /* Set on error.  */
00273   unsigned int stub_overflow : 1;
00274 };
00275 
00276 #define spu_hash_table(p) \
00277   ((struct spu_link_hash_table *) ((p)->hash))
00278 
00279 struct spu_stub_hash_entry
00280 {
00281   struct bfd_hash_entry root;
00282 
00283   /* Destination of this stub.  */
00284   asection *target_section;
00285   bfd_vma target_off;
00286 
00287   /* Offset of entry in stub section.  */
00288   bfd_vma off;
00289 
00290   /* Offset from this stub to stub that loads the overlay index.  */
00291   bfd_vma delta;
00292 };
00293 
00294 /* Create an entry in a spu stub hash table.  */
00295 
00296 static struct bfd_hash_entry *
00297 stub_hash_newfunc (struct bfd_hash_entry *entry,
00298                  struct bfd_hash_table *table,
00299                  const char *string)
00300 {
00301   /* Allocate the structure if it has not already been allocated by a
00302      subclass.  */
00303   if (entry == NULL)
00304     {
00305       entry = bfd_hash_allocate (table, sizeof (struct spu_stub_hash_entry));
00306       if (entry == NULL)
00307        return entry;
00308     }
00309 
00310   /* Call the allocation method of the superclass.  */
00311   entry = bfd_hash_newfunc (entry, table, string);
00312   if (entry != NULL)
00313     {
00314       struct spu_stub_hash_entry *sh = (struct spu_stub_hash_entry *) entry;
00315 
00316       sh->target_section = NULL;
00317       sh->target_off = 0;
00318       sh->off = 0;
00319       sh->delta = 0;
00320     }
00321 
00322   return entry;
00323 }
00324 
00325 /* Create a spu ELF linker hash table.  */
00326 
00327 static struct bfd_link_hash_table *
00328 spu_elf_link_hash_table_create (bfd *abfd)
00329 {
00330   struct spu_link_hash_table *htab;
00331 
00332   htab = bfd_malloc (sizeof (*htab));
00333   if (htab == NULL)
00334     return NULL;
00335 
00336   if (!_bfd_elf_link_hash_table_init (&htab->elf, abfd,
00337                                   _bfd_elf_link_hash_newfunc,
00338                                   sizeof (struct elf_link_hash_entry)))
00339     {
00340       free (htab);
00341       return NULL;
00342     }
00343 
00344   /* Init the stub hash table too.  */
00345   if (!bfd_hash_table_init (&htab->stub_hash_table, stub_hash_newfunc,
00346                          sizeof (struct spu_stub_hash_entry)))
00347     return NULL;
00348 
00349   memset (&htab->stub, 0,
00350          sizeof (*htab) - offsetof (struct spu_link_hash_table, stub));
00351 
00352   return &htab->elf.root;
00353 }
00354 
00355 /* Free the derived linker hash table.  */
00356 
00357 static void
00358 spu_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
00359 {
00360   struct spu_link_hash_table *ret = (struct spu_link_hash_table *) hash;
00361 
00362   bfd_hash_table_free (&ret->stub_hash_table);
00363   _bfd_generic_link_hash_table_free (hash);
00364 }
00365 
00366 /* Find the symbol for the given R_SYMNDX in IBFD and set *HP and *SYMP
00367    to (hash, NULL) for global symbols, and (NULL, sym) for locals.  Set
00368    *SYMSECP to the symbol's section.  *LOCSYMSP caches local syms.  */
00369 
00370 static bfd_boolean
00371 get_sym_h (struct elf_link_hash_entry **hp,
00372           Elf_Internal_Sym **symp,
00373           asection **symsecp,
00374           Elf_Internal_Sym **locsymsp,
00375           unsigned long r_symndx,
00376           bfd *ibfd)
00377 {
00378   Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
00379 
00380   if (r_symndx >= symtab_hdr->sh_info)
00381     {
00382       struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (ibfd);
00383       struct elf_link_hash_entry *h;
00384 
00385       h = sym_hashes[r_symndx - symtab_hdr->sh_info];
00386       while (h->root.type == bfd_link_hash_indirect
00387             || h->root.type == bfd_link_hash_warning)
00388        h = (struct elf_link_hash_entry *) h->root.u.i.link;
00389 
00390       if (hp != NULL)
00391        *hp = h;
00392 
00393       if (symp != NULL)
00394        *symp = NULL;
00395 
00396       if (symsecp != NULL)
00397        {
00398          asection *symsec = NULL;
00399          if (h->root.type == bfd_link_hash_defined
00400              || h->root.type == bfd_link_hash_defweak)
00401            symsec = h->root.u.def.section;
00402          *symsecp = symsec;
00403        }
00404     }
00405   else
00406     {
00407       Elf_Internal_Sym *sym;
00408       Elf_Internal_Sym *locsyms = *locsymsp;
00409 
00410       if (locsyms == NULL)
00411        {
00412          locsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
00413          if (locsyms == NULL)
00414            locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
00415                                        symtab_hdr->sh_info,
00416                                        0, NULL, NULL, NULL);
00417          if (locsyms == NULL)
00418            return FALSE;
00419          *locsymsp = locsyms;
00420        }
00421       sym = locsyms + r_symndx;
00422 
00423       if (hp != NULL)
00424        *hp = NULL;
00425 
00426       if (symp != NULL)
00427        *symp = sym;
00428 
00429       if (symsecp != NULL)
00430        {
00431          asection *symsec = NULL;
00432          if ((sym->st_shndx != SHN_UNDEF
00433               && sym->st_shndx < SHN_LORESERVE)
00434              || sym->st_shndx > SHN_HIRESERVE)
00435            symsec = bfd_section_from_elf_index (ibfd, sym->st_shndx);
00436          *symsecp = symsec;
00437        }
00438     }
00439   return TRUE;
00440 }
00441 
00442 /* Build a name for an entry in the stub hash table.  We can't use a
00443    local symbol name because ld -r might generate duplicate local symbols.  */
00444 
00445 static char *
00446 spu_stub_name (const asection *sym_sec,
00447               const struct elf_link_hash_entry *h,
00448               const Elf_Internal_Rela *rel)
00449 {
00450   char *stub_name;
00451   bfd_size_type len;
00452 
00453   if (h)
00454     {
00455       len = strlen (h->root.root.string) + 1 + 8 + 1;
00456       stub_name = bfd_malloc (len);
00457       if (stub_name == NULL)
00458        return stub_name;
00459 
00460       sprintf (stub_name, "%s+%x",
00461               h->root.root.string,
00462               (int) rel->r_addend & 0xffffffff);
00463       len -= 8;
00464     }
00465   else
00466     {
00467       len = 8 + 1 + 8 + 1 + 8 + 1;
00468       stub_name = bfd_malloc (len);
00469       if (stub_name == NULL)
00470        return stub_name;
00471 
00472       sprintf (stub_name, "%x:%x+%x",
00473               sym_sec->id & 0xffffffff,
00474               (int) ELF32_R_SYM (rel->r_info) & 0xffffffff,
00475               (int) rel->r_addend & 0xffffffff);
00476       len = strlen (stub_name);
00477     }
00478 
00479   if (stub_name[len - 2] == '+'
00480       && stub_name[len - 1] == '0'
00481       && stub_name[len] == 0)
00482     stub_name[len - 2] = 0;
00483 
00484   return stub_name;
00485 }
00486 
00487 /* Create the note section if not already present.  This is done early so
00488    that the linker maps the sections to the right place in the output.  */
00489 
00490 bfd_boolean
00491 spu_elf_create_sections (bfd *output_bfd, struct bfd_link_info *info)
00492 {
00493   bfd *ibfd;
00494 
00495   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->next)
00496     if (bfd_get_section_by_name (ibfd, SPU_PTNOTE_SPUNAME) != NULL)
00497       break;
00498 
00499   if (ibfd == NULL)
00500     {
00501       /* Make SPU_PTNOTE_SPUNAME section.  */
00502       asection *s;
00503       size_t name_len;
00504       size_t size;
00505       bfd_byte *data;
00506       flagword flags;
00507 
00508       ibfd = info->input_bfds;
00509       flags = SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
00510       s = bfd_make_section_anyway_with_flags (ibfd, SPU_PTNOTE_SPUNAME, flags);
00511       if (s == NULL
00512          || !bfd_set_section_alignment (ibfd, s, 4))
00513        return FALSE;
00514 
00515       name_len = strlen (bfd_get_filename (output_bfd)) + 1;
00516       size = 12 + ((sizeof (SPU_PLUGIN_NAME) + 3) & -4);
00517       size += (name_len + 3) & -4;
00518 
00519       if (!bfd_set_section_size (ibfd, s, size))
00520        return FALSE;
00521 
00522       data = bfd_zalloc (ibfd, size);
00523       if (data == NULL)
00524        return FALSE;
00525 
00526       bfd_put_32 (ibfd, sizeof (SPU_PLUGIN_NAME), data + 0);
00527       bfd_put_32 (ibfd, name_len, data + 4);
00528       bfd_put_32 (ibfd, 1, data + 8);
00529       memcpy (data + 12, SPU_PLUGIN_NAME, sizeof (SPU_PLUGIN_NAME));
00530       memcpy (data + 12 + ((sizeof (SPU_PLUGIN_NAME) + 3) & -4),
00531              bfd_get_filename (output_bfd), name_len);
00532       s->contents = data;
00533     }
00534 
00535   return TRUE;
00536 }
00537 
00538 /* Return the section that should be marked against GC for a given
00539    relocation.  */
00540 
00541 static asection *
00542 spu_elf_gc_mark_hook (asection *sec,
00543                     struct bfd_link_info *info ATTRIBUTE_UNUSED,
00544                     Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
00545                     struct elf_link_hash_entry *h,
00546                     Elf_Internal_Sym *sym)
00547 {
00548   if (h != NULL)
00549     {
00550       switch (h->root.type)
00551        {
00552        case bfd_link_hash_defined:
00553        case bfd_link_hash_defweak:
00554          return h->root.u.def.section;
00555 
00556        case bfd_link_hash_common:
00557          return h->root.u.c.p->section;
00558 
00559        default:
00560          break;
00561        }
00562     }
00563   else
00564     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
00565 
00566   return NULL;
00567 }
00568 
00569 /* qsort predicate to sort sections by vma.  */
00570 
00571 static int
00572 sort_sections (const void *a, const void *b)
00573 {
00574   const asection *const *s1 = a;
00575   const asection *const *s2 = b;
00576   bfd_signed_vma delta = (*s1)->vma - (*s2)->vma;
00577 
00578   if (delta != 0)
00579     return delta < 0 ? -1 : 1;
00580 
00581   return (*s1)->index - (*s2)->index;
00582 }
00583 
00584 /* Identify overlays in the output bfd, and number them.  */
00585 
00586 bfd_boolean
00587 spu_elf_find_overlays (bfd *output_bfd, struct bfd_link_info *info)
00588 {
00589   struct spu_link_hash_table *htab = spu_hash_table (info);
00590   asection **alloc_sec;
00591   unsigned int i, n, ovl_index, num_buf;
00592   asection *s;
00593   bfd_vma ovl_end;
00594 
00595   if (output_bfd->section_count < 2)
00596     return FALSE;
00597 
00598   alloc_sec = bfd_malloc (output_bfd->section_count * sizeof (*alloc_sec));
00599   if (alloc_sec == NULL)
00600     return FALSE;
00601 
00602   /* Pick out all the alloced sections.  */
00603   for (n = 0, s = output_bfd->sections; s != NULL; s = s->next)
00604     if ((s->flags & SEC_ALLOC) != 0
00605        && (s->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != SEC_THREAD_LOCAL
00606        && s->size != 0)
00607       alloc_sec[n++] = s;
00608 
00609   if (n == 0)
00610     {
00611       free (alloc_sec);
00612       return FALSE;
00613     }
00614 
00615   /* Sort them by vma.  */
00616   qsort (alloc_sec, n, sizeof (*alloc_sec), sort_sections);
00617 
00618   /* Look for overlapping vmas.  Any with overlap must be overlays.
00619      Count them.  Also count the number of overlay regions and for
00620      each region save a section from that region with the lowest vma
00621      and another section with the highest end vma.  */
00622   ovl_end = alloc_sec[0]->vma + alloc_sec[0]->size;
00623   for (ovl_index = 0, num_buf = 0, i = 1; i < n; i++)
00624     {
00625       s = alloc_sec[i];
00626       if (s->vma < ovl_end)
00627        {
00628          asection *s0 = alloc_sec[i - 1];
00629 
00630          if (spu_elf_section_data (s0)->ovl_index == 0)
00631            {
00632              spu_elf_section_data (s0)->ovl_index = ++ovl_index;
00633              alloc_sec[num_buf * 2] = s0;
00634              alloc_sec[num_buf * 2 + 1] = s0;
00635              num_buf++;
00636            }
00637          spu_elf_section_data (s)->ovl_index = ++ovl_index;
00638          if (ovl_end < s->vma + s->size)
00639            {
00640              ovl_end = s->vma + s->size;
00641              alloc_sec[num_buf * 2 - 1] = s;
00642            }
00643        }
00644       else
00645        ovl_end = s->vma + s->size;
00646     }
00647 
00648   htab->num_overlays = ovl_index;
00649   htab->num_buf = num_buf;
00650   if (ovl_index == 0)
00651     {
00652       free (alloc_sec);
00653       return FALSE;
00654     }
00655 
00656   alloc_sec = bfd_realloc (alloc_sec, num_buf * 2 * sizeof (*alloc_sec));
00657   if (alloc_sec == NULL)
00658     return FALSE;
00659 
00660   htab->ovl_region = alloc_sec;
00661   return TRUE;
00662 }
00663 
00664 /* One of these per stub.  */
00665 #define SIZEOF_STUB1 8
00666 #define ILA_79       0x4200004f           /* ila $79,function_address */
00667 #define BR    0x32000000           /* br stub2 */
00668 
00669 /* One of these per overlay.  */
00670 #define SIZEOF_STUB2 8
00671 #define ILA_78       0x4200004e           /* ila $78,overlay_number */
00672                                    /* br __ovly_load */
00673 #define NOP   0x40200000
00674 
00675 /* Return true for all relative and absolute branch and hint instructions.
00676    bra   00110000 0..
00677    brasl 00110001 0..
00678    br    00110010 0..
00679    brsl  00110011 0..
00680    brz   00100000 0..
00681    brnz  00100001 0..
00682    brhz  00100010 0..
00683    brhnz 00100011 0..
00684    hbra  0001000..
00685    hbrr  0001001..  */
00686 
00687 static bfd_boolean
00688 is_branch (const unsigned char *insn)
00689 {
00690   return (((insn[0] & 0xec) == 0x20 && (insn[1] & 0x80) == 0)
00691          || (insn[0] & 0xfc) == 0x10);
00692 }
00693 
00694 /* Return TRUE if this reloc symbol should possibly go via an overlay stub.  */
00695 
00696 static bfd_boolean
00697 needs_ovl_stub (const char *sym_name,
00698               asection *sym_sec,
00699               asection *input_section,
00700               struct spu_link_hash_table *htab,
00701               bfd_boolean is_branch)
00702 {
00703   if (htab->num_overlays == 0)
00704     return FALSE;
00705 
00706   if (sym_sec == NULL
00707       || sym_sec->output_section == NULL)
00708     return FALSE;
00709 
00710   /* setjmp always goes via an overlay stub, because then the return
00711      and hence the longjmp goes via __ovly_return.  That magically
00712      makes setjmp/longjmp between overlays work.  */
00713   if (strncmp (sym_name, "setjmp", 6) == 0
00714       && (sym_name[6] == '\0' || sym_name[6] == '@'))
00715     return TRUE;
00716 
00717   /* Usually, symbols in non-overlay sections don't need stubs.  */
00718   if (spu_elf_section_data (sym_sec->output_section)->ovl_index == 0
00719       && !htab->non_overlay_stubs)
00720     return FALSE;
00721 
00722   /* A reference from some other section to a symbol in an overlay
00723      section needs a stub.  */
00724   if (spu_elf_section_data (sym_sec->output_section)->ovl_index
00725        != spu_elf_section_data (input_section->output_section)->ovl_index)
00726     return TRUE;
00727 
00728   /* If this insn isn't a branch then we are possibly taking the
00729      address of a function and passing it out somehow.  */
00730   return !is_branch;
00731 }
00732 
00733 struct stubarr {
00734   struct bfd_hash_table *stub_hash_table;
00735   struct spu_stub_hash_entry **sh;
00736   unsigned int count;
00737   int err;
00738 };
00739 
00740 /* Called via elf_link_hash_traverse to allocate stubs for any _SPUEAR_
00741    symbols.  */
00742 
00743 static bfd_boolean
00744 allocate_spuear_stubs (struct elf_link_hash_entry *h, void *inf)
00745 {
00746   /* Symbols starting with _SPUEAR_ need a stub because they may be
00747      invoked by the PPU.  */
00748   if ((h->root.type == bfd_link_hash_defined
00749        || h->root.type == bfd_link_hash_defweak)
00750       && h->def_regular
00751       && strncmp (h->root.root.string, "_SPUEAR_", 8) == 0)
00752     {
00753       struct stubarr *stubs = inf;
00754       static Elf_Internal_Rela zero_rel;
00755       char *stub_name = spu_stub_name (h->root.u.def.section, h, &zero_rel);
00756       struct spu_stub_hash_entry *sh;
00757 
00758       if (stub_name == NULL)
00759        {
00760          stubs->err = 1;
00761          return FALSE;
00762        }
00763 
00764       sh = (struct spu_stub_hash_entry *)
00765        bfd_hash_lookup (stubs->stub_hash_table, stub_name, TRUE, FALSE);
00766       if (sh == NULL)
00767        {
00768          free (stub_name);
00769          return FALSE;
00770        }
00771 
00772       /* If this entry isn't new, we already have a stub.  */
00773       if (sh->target_section != NULL)
00774        {
00775          free (stub_name);
00776          return TRUE;
00777        }
00778 
00779       sh->target_section = h->root.u.def.section;
00780       sh->target_off = h->root.u.def.value;
00781       stubs->count += 1;
00782     }
00783   
00784   return TRUE;
00785 }
00786 
00787 /* Called via bfd_hash_traverse to set up pointers to all symbols
00788    in the stub hash table.  */
00789 
00790 static bfd_boolean
00791 populate_stubs (struct bfd_hash_entry *bh, void *inf)
00792 {
00793   struct stubarr *stubs = inf;
00794 
00795   stubs->sh[--stubs->count] = (struct spu_stub_hash_entry *) bh;
00796   return TRUE;
00797 }
00798 
00799 /* qsort predicate to sort stubs by overlay number.  */
00800 
00801 static int
00802 sort_stubs (const void *a, const void *b)
00803 {
00804   const struct spu_stub_hash_entry *const *sa = a;
00805   const struct spu_stub_hash_entry *const *sb = b;
00806   int i;
00807   bfd_signed_vma d;
00808 
00809   i = spu_elf_section_data ((*sa)->target_section->output_section)->ovl_index;
00810   i -= spu_elf_section_data ((*sb)->target_section->output_section)->ovl_index;
00811   if (i != 0)
00812     return i;
00813 
00814   d = ((*sa)->target_section->output_section->vma
00815        + (*sa)->target_section->output_offset
00816        + (*sa)->target_off
00817        - (*sb)->target_section->output_section->vma
00818        - (*sb)->target_section->output_offset
00819        - (*sb)->target_off);
00820   if (d != 0)
00821     return d < 0 ? -1 : 1;
00822 
00823   /* Two functions at the same address.  Aliases perhaps.  */
00824   i = strcmp ((*sb)->root.string, (*sa)->root.string);
00825   BFD_ASSERT (i != 0);
00826   return i;
00827 }
00828 
00829 /* Allocate space for overlay call and return stubs.  */
00830 
00831 bfd_boolean
00832 spu_elf_size_stubs (bfd *output_bfd,
00833                   struct bfd_link_info *info,
00834                   int non_overlay_stubs,
00835                   asection **stub,
00836                   asection **ovtab,
00837                   asection **toe)
00838 {
00839   struct spu_link_hash_table *htab = spu_hash_table (info);
00840   bfd *ibfd;
00841   struct stubarr stubs;
00842   unsigned i, group;
00843   flagword flags;
00844 
00845   htab->non_overlay_stubs = non_overlay_stubs;
00846   stubs.stub_hash_table = &htab->stub_hash_table;
00847   stubs.count = 0;
00848   stubs.err = 0;
00849   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
00850     {
00851       extern const bfd_target bfd_elf32_spu_vec;
00852       Elf_Internal_Shdr *symtab_hdr;
00853       asection *section;
00854       Elf_Internal_Sym *local_syms = NULL;
00855 
00856       if (ibfd->xvec != &bfd_elf32_spu_vec)
00857        continue;
00858 
00859       /* We'll need the symbol table in a second.  */
00860       symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
00861       if (symtab_hdr->sh_info == 0)
00862        continue;
00863 
00864       /* Walk over each section attached to the input bfd.  */
00865       for (section = ibfd->sections; section != NULL; section = section->next)
00866        {
00867          Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
00868 
00869          /* If there aren't any relocs, then there's nothing more to do.  */
00870          if ((section->flags & SEC_RELOC) == 0
00871              || (section->flags & SEC_ALLOC) == 0
00872              || (section->flags & SEC_LOAD) == 0
00873              || section->reloc_count == 0)
00874            continue;
00875 
00876          /* If this section is a link-once section that will be
00877             discarded, then don't create any stubs.  */
00878          if (section->output_section == NULL
00879              || section->output_section->owner != output_bfd)
00880            continue;
00881 
00882          /* Get the relocs.  */
00883          internal_relocs
00884            = _bfd_elf_link_read_relocs (ibfd, section, NULL, NULL,
00885                                     info->keep_memory);
00886          if (internal_relocs == NULL)
00887            goto error_ret_free_local;
00888 
00889          /* Now examine each relocation.  */
00890          irela = internal_relocs;
00891          irelaend = irela + section->reloc_count;
00892          for (; irela < irelaend; irela++)
00893            {
00894              enum elf_spu_reloc_type r_type;
00895              unsigned int r_indx;
00896              asection *sym_sec;
00897              Elf_Internal_Sym *sym;
00898              struct elf_link_hash_entry *h;
00899              const char *sym_name;
00900              char *stub_name;
00901              struct spu_stub_hash_entry *sh;
00902              unsigned int sym_type;
00903              enum _insn_type { non_branch, branch, call } insn_type;
00904 
00905              r_type = ELF32_R_TYPE (irela->r_info);
00906              r_indx = ELF32_R_SYM (irela->r_info);
00907 
00908              if (r_type >= R_SPU_max)
00909               {
00910                 bfd_set_error (bfd_error_bad_value);
00911                 goto error_ret_free_internal;
00912               }
00913 
00914              /* Determine the reloc target section.  */
00915              if (!get_sym_h (&h, &sym, &sym_sec, &local_syms, r_indx, ibfd))
00916               goto error_ret_free_internal;
00917 
00918              if (sym_sec == NULL
00919                 || sym_sec->output_section == NULL
00920                 || sym_sec->output_section->owner != output_bfd)
00921               continue;
00922 
00923              /* Ensure no stubs for user supplied overlay manager syms.  */
00924              if (h != NULL
00925                 && (strcmp (h->root.root.string, "__ovly_load") == 0
00926                     || strcmp (h->root.root.string, "__ovly_return") == 0))
00927               continue;
00928 
00929              insn_type = non_branch;
00930              if (r_type == R_SPU_REL16
00931                 || r_type == R_SPU_ADDR16)
00932               {
00933                 unsigned char insn[4];
00934 
00935                 if (!bfd_get_section_contents (ibfd, section, insn,
00936                                            irela->r_offset, 4))
00937                   goto error_ret_free_internal;
00938 
00939                 if (is_branch (insn))
00940                   {
00941                     insn_type = branch;
00942                     if ((insn[0] & 0xfd) == 0x31)
00943                      insn_type = call;
00944                   }
00945               }
00946 
00947              /* We are only interested in function symbols.  */
00948              if (h != NULL)
00949               {
00950                 sym_type = h->type;
00951                 sym_name = h->root.root.string;
00952               }
00953              else
00954               {
00955                 sym_type = ELF_ST_TYPE (sym->st_info);
00956                 sym_name = bfd_elf_sym_name (sym_sec->owner,
00957                                           symtab_hdr,
00958                                           sym,
00959                                           sym_sec);
00960               }
00961              if (sym_type != STT_FUNC)
00962               {
00963                 /* It's common for people to write assembly and forget
00964                    to give function symbols the right type.  Handle
00965                    calls to such symbols, but warn so that (hopefully)
00966                    people will fix their code.  We need the symbol
00967                    type to be correct to distinguish function pointer
00968                    initialisation from other pointer initialisation.  */
00969                 if (insn_type == call)
00970                   (*_bfd_error_handler) (_("warning: call to non-function"
00971                                         " symbol %s defined in %B"),
00972                                       sym_sec->owner, sym_name);
00973                 else
00974                   continue;
00975               }
00976 
00977              if (!needs_ovl_stub (sym_name, sym_sec, section, htab,
00978                                insn_type != non_branch))
00979               continue;
00980 
00981              stub_name = spu_stub_name (sym_sec, h, irela);
00982              if (stub_name == NULL)
00983               goto error_ret_free_internal;
00984 
00985              sh = (struct spu_stub_hash_entry *)
00986               bfd_hash_lookup (&htab->stub_hash_table, stub_name,
00987                              TRUE, FALSE);
00988              if (sh == NULL)
00989               {
00990                 free (stub_name);
00991               error_ret_free_internal:
00992                 if (elf_section_data (section)->relocs != internal_relocs)
00993                   free (internal_relocs);
00994               error_ret_free_local:
00995                 if (local_syms != NULL
00996                     && (symtab_hdr->contents
00997                        != (unsigned char *) local_syms))
00998                   free (local_syms);
00999                 return FALSE;
01000               }
01001 
01002              /* If this entry isn't new, we already have a stub.  */
01003              if (sh->target_section != NULL)
01004               {
01005                 free (stub_name);
01006                 continue;
01007               }
01008 
01009              sh->target_section = sym_sec;
01010              if (h != NULL)
01011               sh->target_off = h->root.u.def.value;
01012              else
01013               sh->target_off = sym->st_value;
01014              sh->target_off += irela->r_addend;
01015 
01016              stubs.count += 1;
01017            }
01018 
01019          /* We're done with the internal relocs, free them.  */
01020          if (elf_section_data (section)->relocs != internal_relocs)
01021            free (internal_relocs);
01022        }
01023 
01024       if (local_syms != NULL
01025          && symtab_hdr->contents != (unsigned char *) local_syms)
01026        {
01027          if (!info->keep_memory)
01028            free (local_syms);
01029          else
01030            symtab_hdr->contents = (unsigned char *) local_syms;
01031        }
01032     }
01033 
01034   elf_link_hash_traverse (&htab->elf, allocate_spuear_stubs, &stubs);
01035   if (stubs.err)
01036     return FALSE;
01037 
01038   *stub = NULL;
01039   if (stubs.count == 0)
01040     return TRUE;
01041 
01042   ibfd = info->input_bfds;
01043   flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY
01044           | SEC_HAS_CONTENTS | SEC_IN_MEMORY);
01045   htab->stub = bfd_make_section_anyway_with_flags (ibfd, ".stub", flags);
01046   *stub = htab->stub;
01047   if (htab->stub == NULL
01048       || !bfd_set_section_alignment (ibfd, htab->stub, 2))
01049     return FALSE;
01050 
01051   flags = (SEC_ALLOC | SEC_LOAD
01052           | SEC_HAS_CONTENTS | SEC_IN_MEMORY);
01053   htab->ovtab = bfd_make_section_anyway_with_flags (ibfd, ".ovtab", flags);
01054   *ovtab = htab->ovtab;
01055   if (htab->ovtab == NULL
01056       || !bfd_set_section_alignment (ibfd, htab->stub, 4))
01057     return FALSE;
01058 
01059   *toe = bfd_make_section_anyway_with_flags (ibfd, ".toe", SEC_ALLOC);
01060   if (*toe == NULL
01061       || !bfd_set_section_alignment (ibfd, *toe, 4))
01062     return FALSE;
01063   (*toe)->size = 16;
01064 
01065   /* Retrieve all the stubs and sort.  */
01066   stubs.sh = bfd_malloc (stubs.count * sizeof (*stubs.sh));
01067   if (stubs.sh == NULL)
01068     return FALSE;
01069   i = stubs.count;
01070   bfd_hash_traverse (&htab->stub_hash_table, populate_stubs, &stubs);
01071   BFD_ASSERT (stubs.count == 0);
01072 
01073   stubs.count = i;
01074   qsort (stubs.sh, stubs.count, sizeof (*stubs.sh), sort_stubs);
01075 
01076   /* Now that the stubs are sorted, place them in the stub section.
01077      Stubs are grouped per overlay
01078      .     ila $79,func1
01079      .     br 1f
01080      .     ila $79,func2
01081      .     br 1f
01082      .
01083      .
01084      .     ila $79,funcn
01085      .     nop
01086      . 1:
01087      .     ila $78,ovl_index
01088      .     br __ovly_load  */
01089 
01090   group = 0;
01091   for (i = 0; i < stubs.count; i++)
01092     {
01093       if (spu_elf_section_data (stubs.sh[group]->target_section
01094                             ->output_section)->ovl_index
01095          != spu_elf_section_data (stubs.sh[i]->target_section
01096                                ->output_section)->ovl_index)
01097        {
01098          htab->stub->size += SIZEOF_STUB2;
01099          for (; group != i; group++)
01100            stubs.sh[group]->delta
01101              = stubs.sh[i - 1]->off - stubs.sh[group]->off;
01102        }
01103       if (group == i
01104          || ((stubs.sh[i - 1]->target_section->output_section->vma
01105               + stubs.sh[i - 1]->target_section->output_offset
01106               + stubs.sh[i - 1]->target_off)
01107              != (stubs.sh[i]->target_section->output_section->vma
01108                 + stubs.sh[i]->target_section->output_offset
01109                 + stubs.sh[i]->target_off)))
01110        {
01111          stubs.sh[i]->off = htab->stub->size;
01112          htab->stub->size += SIZEOF_STUB1;
01113        }
01114       else
01115        stubs.sh[i]->off = stubs.sh[i - 1]->off;
01116     }
01117   if (group != i)
01118     htab->stub->size += SIZEOF_STUB2;
01119   for (; group != i; group++)
01120     stubs.sh[group]->delta = stubs.sh[i - 1]->off - stubs.sh[group]->off;
01121 
01122  /* htab->ovtab consists of two arrays.
01123     .  struct {
01124     .    u32 vma;
01125     .    u32 size;
01126     .    u32 file_off;
01127     .    u32 buf;
01128     .  } _ovly_table[];
01129     .
01130     .  struct {
01131     .    u32 mapped;
01132     .  } _ovly_buf_table[];  */
01133 
01134   htab->ovtab->alignment_power = 4;
01135   htab->ovtab->size = htab->num_overlays * 16 + htab->num_buf * 4;
01136 
01137   return TRUE;
01138 }
01139 
01140 /* Functions to handle embedded spu_ovl.o object.  */
01141 
01142 static void *
01143 ovl_mgr_open (struct bfd *nbfd ATTRIBUTE_UNUSED, void *stream)
01144 {
01145   return stream;
01146 }
01147 
01148 static file_ptr
01149 ovl_mgr_pread (struct bfd *abfd ATTRIBUTE_UNUSED,
01150               void *stream,
01151               void *buf,
01152               file_ptr nbytes,
01153               file_ptr offset)
01154 {
01155   struct _ovl_stream *os;
01156   size_t count;
01157   size_t max;
01158 
01159   os = (struct _ovl_stream *) stream;
01160   max = (const char *) os->end - (const char *) os->start;
01161 
01162   if ((ufile_ptr) offset >= max)
01163     return 0;
01164 
01165   count = nbytes;
01166   if (count > max - offset)
01167     count = max - offset;
01168 
01169   memcpy (buf, (const char *) os->start + offset, count);
01170   return count;
01171 }
01172 
01173 bfd_boolean
01174 spu_elf_open_builtin_lib (bfd **ovl_bfd, const struct _ovl_stream *stream)
01175 {
01176   *ovl_bfd = bfd_openr_iovec ("builtin ovl_mgr",
01177                            "elf32-spu",
01178                            ovl_mgr_open,
01179                            (void *) stream,
01180                            ovl_mgr_pread,
01181                            NULL,
01182                            NULL);
01183   return *ovl_bfd != NULL;
01184 }
01185 
01186 /* Fill in the ila and br for a stub.  On the last stub for a group,
01187    write the stub that sets the overlay number too.  */
01188 
01189 static bfd_boolean
01190 write_one_stub (struct bfd_hash_entry *bh, void *inf)
01191 {
01192   struct spu_stub_hash_entry *ent = (struct spu_stub_hash_entry *) bh;
01193   struct spu_link_hash_table *htab = inf;
01194   asection *sec = htab->stub;
01195   asection *s = ent->target_section;
01196   unsigned int ovl;
01197   bfd_vma val;
01198 
01199   val = ent->target_off + s->output_offset + s->output_section->vma;
01200   bfd_put_32 (sec->owner, ILA_79 + ((val << 7) & 0x01ffff80),
01201              sec->contents + ent->off);
01202   val = ent->delta + 4;
01203   bfd_put_32 (sec->owner, BR + ((val << 5) & 0x007fff80),
01204              sec->contents + ent->off + 4);
01205 
01206   /* If this is the last stub of this group, write stub2.  */
01207   if (ent->delta == 0)
01208     {
01209       bfd_put_32 (sec->owner, NOP,
01210                 sec->contents + ent->off + 4);
01211 
01212       ovl = spu_elf_section_data (s->output_section)->ovl_index;
01213       bfd_put_32 (sec->owner, ILA_78 + ((ovl << 7) & 0x01ffff80),
01214                 sec->contents + ent->off + 8);
01215 
01216       val = (htab->ovly_load->root.u.def.section->output_section->vma
01217             + htab->ovly_load->root.u.def.section->output_offset
01218             + htab->ovly_load->root.u.def.value
01219             - (sec->output_section->vma
01220               + sec->output_offset
01221               + ent->off + 12));
01222 
01223       if (val + 0x20000 >= 0x40000)
01224        htab->stub_overflow = TRUE;
01225 
01226       bfd_put_32 (sec->owner, BR + ((val << 5) & 0x007fff80),
01227                 sec->contents + ent->off + 12);
01228     }
01229 
01230   if (htab->emit_stub_syms)
01231     {
01232       struct elf_link_hash_entry *h;
01233       size_t len1, len2;
01234       char *name;
01235 
01236       len1 = sizeof ("00000000.ovl_call.") - 1;
01237       len2 = strlen (ent->root.string);
01238       name = bfd_malloc (len1 + len2 + 1);
01239       if (name == NULL)
01240        return FALSE;
01241       memcpy (name, "00000000.ovl_call.", len1);
01242       memcpy (name + len1, ent->root.string, len2 + 1);
01243       h = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE);
01244       if (h == NULL)
01245        return FALSE;
01246       if (h->root.type == bfd_link_hash_new)
01247        {
01248          h->root.type = bfd_link_hash_defined;
01249          h->root.u.def.section = sec;
01250          h->root.u.def.value = ent->off;
01251          h->size = (ent->delta == 0
01252                    ? SIZEOF_STUB1 + SIZEOF_STUB2 : SIZEOF_STUB1);
01253          h->type = STT_FUNC;
01254          h->ref_regular = 1;
01255          h->def_regular = 1;
01256          h->ref_regular_nonweak = 1;
01257          h->forced_local = 1;
01258          h->non_elf = 0;
01259        }
01260     }
01261 
01262   return TRUE;
01263 }
01264 
01265 /* Define an STT_OBJECT symbol.  */
01266 
01267 static struct elf_link_hash_entry *
01268 define_ovtab_symbol (struct spu_link_hash_table *htab, const char *name)
01269 {
01270   struct elf_link_hash_entry *h;
01271 
01272   h = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE);
01273   if (h == NULL)
01274     return NULL;
01275 
01276   if (h->root.type != bfd_link_hash_defined
01277       || !h->def_regular)
01278     {
01279       h->root.type = bfd_link_hash_defined;
01280       h->root.u.def.section = htab->ovtab;
01281       h->type = STT_OBJECT;
01282       h->ref_regular = 1;
01283       h->def_regular = 1;
01284       h->ref_regular_nonweak = 1;
01285       h->non_elf = 0;
01286     }
01287   else
01288     {
01289       (*_bfd_error_handler) (_("%B is not allowed to define %s"),
01290                           h->root.u.def.section->owner,
01291                           h->root.root.string);
01292       bfd_set_error (bfd_error_bad_value);
01293       return NULL;
01294     }
01295 
01296   return h;
01297 }
01298 
01299 /* Fill in all stubs and the overlay tables.  */
01300 
01301 bfd_boolean
01302 spu_elf_build_stubs (struct bfd_link_info *info, int emit_syms, asection *toe)
01303 {
01304   struct spu_link_hash_table *htab = spu_hash_table (info);
01305   struct elf_link_hash_entry *h;
01306   bfd_byte *p;
01307   asection *s;
01308   bfd *obfd;
01309   unsigned int i;
01310 
01311   htab->emit_stub_syms = emit_syms;
01312   htab->stub->contents = bfd_zalloc (htab->stub->owner, htab->stub->size);
01313   if (htab->stub->contents == NULL)
01314     return FALSE;
01315 
01316   h = elf_link_hash_lookup (&htab->elf, "__ovly_load", FALSE, FALSE, FALSE);
01317   htab->ovly_load = h;
01318   BFD_ASSERT (h != NULL
01319              && (h->root.type == bfd_link_hash_defined
01320                 || h->root.type == bfd_link_hash_defweak)
01321              && h->def_regular);
01322 
01323   s = h->root.u.def.section->output_section;
01324   if (spu_elf_section_data (s)->ovl_index)
01325     {
01326       (*_bfd_error_handler) (_("%s in overlay section"),
01327                           h->root.u.def.section->owner);
01328       bfd_set_error (bfd_error_bad_value);
01329       return FALSE;
01330     }
01331 
01332   /* Write out all the stubs.  */
01333   bfd_hash_traverse (&htab->stub_hash_table, write_one_stub, htab);
01334 
01335   if (htab->stub_overflow)
01336     {
01337       (*_bfd_error_handler) (_("overlay stub relocation overflow"));
01338       bfd_set_error (bfd_error_bad_value);
01339       return FALSE;
01340     }
01341 
01342   htab->ovtab->contents = bfd_zalloc (htab->ovtab->owner, htab->ovtab->size);
01343   if (htab->ovtab->contents == NULL)
01344     return FALSE;
01345 
01346   /* Write out _ovly_table.  */
01347   p = htab->ovtab->contents;
01348   obfd = htab->ovtab->output_section->owner;
01349   for (s = obfd->sections; s != NULL; s = s->next)
01350     {
01351       unsigned int ovl_index = spu_elf_section_data (s)->ovl_index;
01352 
01353       if (ovl_index != 0)
01354        {
01355          unsigned int lo, hi, mid;
01356          unsigned long off = (ovl_index - 1) * 16;
01357          bfd_put_32 (htab->ovtab->owner, s->vma, p + off);
01358          bfd_put_32 (htab->ovtab->owner, (s->size + 15) & -16, p + off + 4);
01359          /* file_off written later in spu_elf_modify_program_headers.  */
01360 
01361          lo = 0;
01362          hi = htab->num_buf;
01363          while (lo < hi)
01364            {
01365              mid = (lo + hi) >> 1;
01366              if (htab->ovl_region[2 * mid + 1]->vma
01367                 + htab->ovl_region[2 * mid + 1]->size <= s->vma)
01368               lo = mid + 1;
01369              else if (htab->ovl_region[2 * mid]->vma > s->vma)
01370               hi = mid;
01371              else
01372               {
01373                 bfd_put_32 (htab->ovtab->owner, mid + 1, p + off + 12);
01374                 break;
01375               }
01376            }
01377          BFD_ASSERT (lo < hi);
01378        }
01379     }
01380 
01381   /* Write out _ovly_buf_table.  */
01382   p = htab->ovtab->contents + htab->num_overlays * 16;
01383   for (i = 0; i < htab->num_buf; i++)
01384     {
01385       bfd_put_32 (htab->ovtab->owner, 0, p);
01386       p += 4;
01387     }
01388 
01389   h = define_ovtab_symbol (htab, "_ovly_table");
01390   if (h == NULL)
01391     return FALSE;
01392   h->root.u.def.value = 0;
01393   h->size = htab->num_overlays * 16;
01394 
01395   h = define_ovtab_symbol (htab, "_ovly_table_end");
01396   if (h == NULL)
01397     return FALSE;
01398   h->root.u.def.value = htab->num_overlays * 16;
01399   h->size = 0;
01400 
01401   h = define_ovtab_symbol (htab, "_ovly_buf_table");
01402   if (h == NULL)
01403     return FALSE;
01404   h->root.u.def.value = htab->num_overlays * 16;
01405   h->size = htab->num_buf * 4;
01406 
01407   h = define_ovtab_symbol (htab, "_ovly_buf_table_end");
01408   if (h == NULL)
01409     return FALSE;
01410   h->root.u.def.value = htab->num_overlays * 16 + htab->num_buf * 4;
01411   h->size = 0;
01412 
01413   h = define_ovtab_symbol (htab, "_EAR_");
01414   if (h == NULL)
01415     return FALSE;
01416   h->root.u.def.section = toe;
01417   h->root.u.def.value = 0;
01418   h->size = 16;
01419 
01420   return TRUE;
01421 }
01422 
01423 /* Apply RELOCS to CONTENTS of INPUT_SECTION from INPUT_BFD.  */
01424 
01425 static bfd_boolean
01426 spu_elf_relocate_section (bfd *output_bfd,
01427                        struct bfd_link_info *info,
01428                        bfd *input_bfd,
01429                        asection *input_section,
01430                        bfd_byte *contents,
01431                        Elf_Internal_Rela *relocs,
01432                        Elf_Internal_Sym *local_syms,
01433                        asection **local_sections)
01434 {
01435   Elf_Internal_Shdr *symtab_hdr;
01436   struct elf_link_hash_entry **sym_hashes;
01437   Elf_Internal_Rela *rel, *relend;
01438   struct spu_link_hash_table *htab;
01439   bfd_boolean ret = TRUE;
01440 
01441   htab = spu_hash_table (info);
01442   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
01443   sym_hashes = (struct elf_link_hash_entry **) (elf_sym_hashes (input_bfd));
01444 
01445   rel = relocs;
01446   relend = relocs + input_section->reloc_count;
01447   for (; rel < relend; rel++)
01448     {
01449       int r_type;
01450       reloc_howto_type *howto;
01451       unsigned long r_symndx;
01452       Elf_Internal_Sym *sym;
01453       asection *sec;
01454       struct elf_link_hash_entry *h;
01455       const char *sym_name;
01456       bfd_vma relocation;
01457       bfd_vma addend;
01458       bfd_reloc_status_type r;
01459       bfd_boolean unresolved_reloc;
01460       bfd_boolean warned;
01461 
01462       r_symndx = ELF32_R_SYM (rel->r_info);
01463       r_type = ELF32_R_TYPE (rel->r_info);
01464       howto = elf_howto_table + r_type;
01465       unresolved_reloc = FALSE;
01466       warned = FALSE;
01467 
01468       h = NULL;
01469       sym = NULL;
01470       sec = NULL;
01471       if (r_symndx < symtab_hdr->sh_info)
01472        {
01473          sym = local_syms + r_symndx;
01474          sec = local_sections[r_symndx];
01475          sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
01476          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
01477        }
01478       else
01479        {
01480          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
01481                                r_symndx, symtab_hdr, sym_hashes,
01482                                h, sec, relocation,
01483                                unresolved_reloc, warned);
01484          sym_name = h->root.root.string;
01485        }
01486 
01487       if (sec != NULL && elf_discarded_section (sec))
01488        {
01489          /* For relocs against symbols from removed linkonce sections,
01490             or sections discarded by a linker script, we just want the
01491             section contents zeroed.  Avoid any special processing.  */
01492          _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
01493          rel->r_info = 0;
01494          rel->r_addend = 0;
01495          continue;
01496        }
01497 
01498       if (info->relocatable)
01499        continue;
01500 
01501       if (unresolved_reloc)
01502        {
01503          (*_bfd_error_handler)
01504            (_("%B(%s+0x%lx): unresolvable %s relocation against symbol `%s'"),
01505             input_bfd,
01506             bfd_get_section_name (input_bfd, input_section),
01507             (long) rel->r_offset,
01508             howto->name,
01509             sym_name);
01510          ret = FALSE;
01511        }
01512 
01513       /* If this symbol is in an overlay area, we may need to relocate
01514         to the overlay stub.  */
01515       addend = rel->r_addend;
01516       if (needs_ovl_stub (sym_name, sec, input_section, htab,
01517                        is_branch (contents + rel->r_offset)))
01518        {
01519          char *stub_name;
01520          struct spu_stub_hash_entry *sh;
01521 
01522          stub_name = spu_stub_name (sec, h, rel);
01523          if (stub_name == NULL)
01524            return FALSE;
01525 
01526          sh = (struct spu_stub_hash_entry *)
01527            bfd_hash_lookup (&htab->stub_hash_table, stub_name, FALSE, FALSE);
01528          if (sh != NULL)
01529            {
01530              relocation = (htab->stub->output_section->vma
01531                          + htab->stub->output_offset
01532                          + sh->off);
01533              addend = 0;
01534            }
01535          free (stub_name);
01536        }
01537 
01538       r = _bfd_final_link_relocate (howto,
01539                                 input_bfd,
01540                                 input_section,
01541                                 contents,
01542                                 rel->r_offset, relocation, addend);
01543 
01544       if (r != bfd_reloc_ok)
01545        {
01546          const char *msg = (const char *) 0;
01547 
01548          switch (r)
01549            {
01550            case bfd_reloc_overflow:
01551              if (!((*info->callbacks->reloc_overflow)
01552                   (info, (h ? &h->root : NULL), sym_name, howto->name,
01553                    (bfd_vma) 0, input_bfd, input_section, rel->r_offset)))
01554               return FALSE;
01555              break;
01556 
01557            case bfd_reloc_undefined:
01558              if (!((*info->callbacks->undefined_symbol)
01559                   (info, sym_name, input_bfd, input_section,
01560                    rel->r_offset, TRUE)))
01561               return FALSE;
01562              break;
01563 
01564            case bfd_reloc_outofrange:
01565              msg = _("internal error: out of range error");
01566              goto common_error;
01567 
01568            case bfd_reloc_notsupported:
01569              msg = _("internal error: unsupported relocation error");
01570              goto common_error;
01571 
01572            case bfd_reloc_dangerous:
01573              msg = _("internal error: dangerous error");
01574              goto common_error;
01575 
01576            default:
01577              msg = _("internal error: unknown error");
01578              /* fall through */
01579 
01580            common_error:
01581              if (!((*info->callbacks->warning)
01582                   (info, msg, sym_name, input_bfd, input_section,
01583                    rel->r_offset)))
01584               return FALSE;
01585              break;
01586            }
01587        }
01588     }
01589 
01590   return ret;
01591 }
01592 
01593 static int spu_plugin = 0;
01594 
01595 void
01596 spu_elf_plugin (int val)
01597 {
01598   spu_plugin = val;
01599 }
01600 
01601 /* Set ELF header e_type for plugins.  */
01602 
01603 static void
01604 spu_elf_post_process_headers (bfd *abfd,
01605                            struct bfd_link_info *info ATTRIBUTE_UNUSED)
01606 {
01607   if (spu_plugin)
01608     {
01609       Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
01610 
01611       i_ehdrp->e_type = ET_DYN;
01612     }
01613 }
01614 
01615 /* We may add an extra PT_LOAD segment for .toe.  We also need extra
01616    segments for overlays.  */
01617 
01618 static int
01619 spu_elf_additional_program_headers (bfd *abfd, struct bfd_link_info *info)
01620 {
01621   struct spu_link_hash_table *htab = spu_hash_table (info);
01622   int extra = htab->num_overlays;
01623   asection *sec;
01624 
01625   if (extra)
01626     ++extra;
01627 
01628   sec = bfd_get_section_by_name (abfd, ".toe");
01629   if (sec != NULL && (sec->flags & SEC_LOAD) != 0)
01630     ++extra;
01631 
01632   return extra;
01633 }
01634 
01635 /* Remove .toe section from other PT_LOAD segments and put it in
01636    a segment of its own.  Put overlays in separate segments too.  */
01637 
01638 static bfd_boolean
01639 spu_elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
01640 {
01641   asection *toe, *s;
01642   struct elf_segment_map *m;
01643   unsigned int i;
01644 
01645   if (info == NULL)
01646     return TRUE;
01647 
01648   toe = bfd_get_section_by_name (abfd, ".toe");
01649   for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
01650     if (m->p_type == PT_LOAD && m->count > 1)
01651       for (i = 0; i < m->count; i++)
01652        if ((s = m->sections[i]) == toe
01653            || spu_elf_section_data (s)->ovl_index != 0)
01654          {
01655            struct elf_segment_map *m2;
01656            bfd_vma amt;
01657 
01658            if (i + 1 < m->count)
01659              {
01660               amt = sizeof (struct elf_segment_map);
01661               amt += (m->count - (i + 2)) * sizeof (m->sections[0]);
01662               m2 = bfd_zalloc (abfd, amt);
01663               if (m2 == NULL)
01664                 return FALSE;
01665               m2->count = m->count - (i + 1);
01666               memcpy (m2->sections, m->sections + i + 1,
01667                      m2->count * sizeof (m->sections[0]));
01668               m2->p_type = PT_LOAD;
01669               m2->next = m->next;
01670               m->next = m2;
01671              }
01672            m->count = 1;
01673            if (i != 0)
01674              {
01675               m->count = i;
01676               amt = sizeof (struct elf_segment_map);
01677               m2 = bfd_zalloc (abfd, amt);
01678               if (m2 == NULL)
01679                 return FALSE;
01680               m2->p_type = PT_LOAD;
01681               m2->count = 1;
01682               m2->sections[0] = s;
01683               m2->next = m->next;
01684               m->next = m2;
01685              }
01686            break;
01687          }
01688 
01689   return TRUE;
01690 }
01691 
01692 /* Check that all loadable section VMAs lie in the range
01693    LO .. HI inclusive.  */
01694 
01695 asection *
01696 spu_elf_check_vma (bfd *abfd, bfd_vma lo, bfd_vma hi)
01697 {
01698   struct elf_segment_map *m;
01699   unsigned int i;
01700 
01701   for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
01702     if (m->p_type == PT_LOAD)
01703       for (i = 0; i < m->count; i++)
01704        if (m->sections[i]->size != 0
01705            && (m->sections[i]->vma < lo
01706               || m->sections[i]->vma > hi
01707               || m->sections[i]->vma + m->sections[i]->size - 1 > hi))
01708          return m->sections[i];
01709 
01710   return NULL;
01711 }
01712 
01713 /* Tweak phdrs before writing them out.  */
01714 
01715 static int
01716 spu_elf_modify_program_headers (bfd *abfd, struct bfd_link_info *info)
01717 {
01718   const struct elf_backend_data *bed;
01719   struct elf_obj_tdata *tdata;
01720   Elf_Internal_Phdr *phdr, *last;
01721   struct spu_link_hash_table *htab;
01722   unsigned int count;
01723   unsigned int i;
01724 
01725   if (info == NULL)
01726     return TRUE;
01727 
01728   bed = get_elf_backend_data (abfd);
01729   tdata = elf_tdata (abfd);
01730   phdr = tdata->phdr;
01731   count = tdata->program_header_size / bed->s->sizeof_phdr;
01732   htab = spu_hash_table (info);
01733   if (htab->num_overlays != 0)
01734     {
01735       struct elf_segment_map *m;
01736       unsigned int o;
01737 
01738       for (i = 0, m = elf_tdata (abfd)->segment_map; m; ++i, m = m->next)
01739        if (m->count != 0
01740            && (o = spu_elf_section_data (m->sections[0])->ovl_index) != 0)
01741          {
01742            /* Mark this as an overlay header.  */
01743            phdr[i].p_flags |= PF_OVERLAY;
01744 
01745            if (htab->ovtab != NULL && htab->ovtab->size != 0)
01746              {
01747               bfd_byte *p = htab->ovtab->contents;
01748               unsigned int off = (o - 1) * 16 + 8;
01749 
01750               /* Write file_off into _ovly_table.  */
01751               bfd_put_32 (htab->ovtab->owner, phdr[i].p_offset, p + off);
01752              }
01753          }
01754     }
01755 
01756   /* Round up p_filesz and p_memsz of PT_LOAD segments to multiples
01757      of 16.  This should always be possible when using the standard
01758      linker scripts, but don't create overlapping segments if
01759      someone is playing games with linker scripts.  */
01760   last = NULL;
01761   for (i = count; i-- != 0; )
01762     if (phdr[i].p_type == PT_LOAD)
01763       {
01764        unsigned adjust;
01765 
01766        adjust = -phdr[i].p_filesz & 15;
01767        if (adjust != 0
01768            && last != NULL
01769            && phdr[i].p_offset + phdr[i].p_filesz > last->p_offset - adjust)
01770          break;
01771 
01772        adjust = -phdr[i].p_memsz & 15;
01773        if (adjust != 0
01774            && last != NULL
01775            && phdr[i].p_filesz != 0
01776            && phdr[i].p_vaddr + phdr[i].p_memsz > last->p_vaddr - adjust
01777            && phdr[i].p_vaddr + phdr[i].p_memsz <= last->p_vaddr)
01778          break;
01779 
01780        if (phdr[i].p_filesz != 0)
01781          last = &phdr[i];
01782       }
01783 
01784   if (i == (unsigned int) -1)
01785     for (i = count; i-- != 0; )
01786       if (phdr[i].p_type == PT_LOAD)
01787        {
01788        unsigned adjust;
01789 
01790        adjust = -phdr[i].p_filesz & 15;
01791        phdr[i].p_filesz += adjust;
01792 
01793        adjust = -phdr[i].p_memsz & 15;
01794        phdr[i].p_memsz += adjust;
01795       }
01796 
01797   return TRUE;
01798 }
01799 
01800 /* Arrange for our linker created section to be output.  */
01801 
01802 static bfd_boolean
01803 spu_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED,
01804                          Elf_Internal_Shdr *i_shdrp)
01805 {
01806   asection *sec;
01807 
01808   sec = i_shdrp->bfd_section;
01809   if (sec != NULL
01810       && (sec->flags & SEC_LINKER_CREATED) != 0
01811       && sec->name != NULL
01812       && strcmp (sec->name, SPU_PTNOTE_SPUNAME) == 0)
01813     i_shdrp->contents = sec->contents;
01814 
01815   return TRUE;
01816 }
01817 
01818 #define TARGET_BIG_SYM             bfd_elf32_spu_vec
01819 #define TARGET_BIG_NAME            "elf32-spu"
01820 #define ELF_ARCH            bfd_arch_spu
01821 #define ELF_MACHINE_CODE    EM_SPU
01822 /* This matches the alignment need for DMA.  */
01823 #define ELF_MAXPAGESIZE            0x80
01824 #define elf_backend_rela_normal         1
01825 #define elf_backend_can_gc_sections       1
01826 
01827 #define bfd_elf32_bfd_reloc_type_lookup          spu_elf_reloc_type_lookup
01828 #define bfd_elf32_bfd_reloc_name_lookup   spu_elf_reloc_name_lookup
01829 #define elf_info_to_howto                 spu_elf_info_to_howto
01830 #define elf_backend_gc_mark_hook          spu_elf_gc_mark_hook
01831 #define elf_backend_relocate_section             spu_elf_relocate_section
01832 #define elf_backend_symbol_processing            spu_elf_backend_symbol_processing
01833 #define bfd_elf32_new_section_hook        spu_elf_new_section_hook
01834 #define bfd_elf32_bfd_link_hash_table_create     spu_elf_link_hash_table_create
01835 #define bfd_elf32_bfd_link_hash_table_free       spu_elf_link_hash_table_free
01836 
01837 #define elf_backend_additional_program_headers   spu_elf_additional_program_headers
01838 #define elf_backend_modify_segment_map           spu_elf_modify_segment_map
01839 #define elf_backend_modify_program_headers       spu_elf_modify_program_headers
01840 #define elf_backend_post_process_headers        spu_elf_post_process_headers
01841 #define elf_backend_section_processing           spu_elf_section_processing
01842 #define elf_backend_special_sections             spu_elf_special_sections
01843 
01844 #include "elf32-target.h"