Develop and Download Open Source Software

Browse Subversion Repository

Diff of /trunk/bfd/elf32-spu.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 20 by monabuilder, Tue Dec 23 04:51:51 2008 UTC revision 21 by monamour, Mon Jul 27 20:34:36 2009 UTC
# Line 1  Line 1 
1  /* SPU specific support for 32-bit ELF  /* SPU specific support for 32-bit ELF
2    
3     Copyright 2006, 2007, 2008 Free Software Foundation, Inc.     Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
4    
5     This file is part of BFD, the Binary File Descriptor library.     This file is part of BFD, the Binary File Descriptor library.
6    
# Line 88  static reloc_howto_type elf_howto_table[ Line 88  static reloc_howto_type elf_howto_table[
88    HOWTO (R_SPU_PPU64,      0, 4, 64, FALSE,  0, complain_overflow_dont,    HOWTO (R_SPU_PPU64,      0, 4, 64, FALSE,  0, complain_overflow_dont,
89           bfd_elf_generic_reloc, "SPU_PPU64",           bfd_elf_generic_reloc, "SPU_PPU64",
90           FALSE, 0, -1, FALSE),           FALSE, 0, -1, FALSE),
91      HOWTO (R_SPU_ADD_PIC,      0, 0, 0, FALSE,  0, complain_overflow_dont,
92             bfd_elf_generic_reloc, "SPU_ADD_PIC",
93             FALSE, 0, 0x00000000, FALSE),
94  };  };
95    
96  static struct bfd_elf_special_section const spu_elf_special_sections[] = {  static struct bfd_elf_special_section const spu_elf_special_sections[] = {
# Line 135  spu_elf_bfd_to_reloc_type (bfd_reloc_cod Line 138  spu_elf_bfd_to_reloc_type (bfd_reloc_cod
138        return R_SPU_PPU32;        return R_SPU_PPU32;
139      case BFD_RELOC_SPU_PPU64:      case BFD_RELOC_SPU_PPU64:
140        return R_SPU_PPU64;        return R_SPU_PPU64;
141        case BFD_RELOC_SPU_ADD_PIC:
142          return R_SPU_ADD_PIC;
143      }      }
144  }  }
145    
# Line 301  struct spu_link_hash_table Line 306  struct spu_link_hash_table
306    
307    /* Shortcuts to overlay sections.  */    /* Shortcuts to overlay sections.  */
308    asection *ovtab;    asection *ovtab;
309      asection *init;
310    asection *toe;    asection *toe;
311    asection **ovl_sec;    asection **ovl_sec;
312    
# Line 310  struct spu_link_hash_table Line 316  struct spu_link_hash_table
316    /* The stub section for each overlay section.  */    /* The stub section for each overlay section.  */
317    asection **stub_sec;    asection **stub_sec;
318    
319    struct elf_link_hash_entry *ovly_load;    struct elf_link_hash_entry *ovly_entry[2];
   struct elf_link_hash_entry *ovly_return;  
   unsigned long ovly_load_r_symndx;  
320    
321    /* Number of overlay buffers.  */    /* Number of overlay buffers.  */
322    unsigned int num_buf;    unsigned int num_buf;
# Line 320  struct spu_link_hash_table Line 324  struct spu_link_hash_table
324    /* Total number of overlays.  */    /* Total number of overlays.  */
325    unsigned int num_overlays;    unsigned int num_overlays;
326    
327      /* For soft icache.  */
328      unsigned int line_size_log2;
329      unsigned int num_lines_log2;
330      unsigned int fromelem_size_log2;
331    
332    /* How much memory we have.  */    /* How much memory we have.  */
333    unsigned int local_store;    unsigned int local_store;
334    /* Local store --auto-overlay should reserve for non-overlay    /* Local store --auto-overlay should reserve for non-overlay
# Line 345  struct got_entry Line 354  struct got_entry
354  {  {
355    struct got_entry *next;    struct got_entry *next;
356    unsigned int ovl;    unsigned int ovl;
357    bfd_vma addend;    union {
358        bfd_vma addend;
359        bfd_vma br_addr;
360      };
361    bfd_vma stub_addr;    bfd_vma stub_addr;
362  };  };
363    
# Line 360  struct call_info Line 372  struct call_info
372    unsigned int max_depth;    unsigned int max_depth;
373    unsigned int is_tail : 1;    unsigned int is_tail : 1;
374    unsigned int is_pasted : 1;    unsigned int is_pasted : 1;
375      unsigned int broken_cycle : 1;
376      unsigned int priority : 13;
377  };  };
378    
379  struct function_info  struct function_info
# Line 382  struct function_info Line 396  struct function_info
396    unsigned int call_count;    unsigned int call_count;
397    /* Address range of (this part of) function.  */    /* Address range of (this part of) function.  */
398    bfd_vma lo, hi;    bfd_vma lo, hi;
399      /* Offset where we found a store of lr, or -1 if none found.  */
400      bfd_vma lr_store;
401      /* Offset where we found the stack adjustment insn.  */
402      bfd_vma sp_adjust;
403    /* Stack usage.  */    /* Stack usage.  */
404    int stack;    int stack;
405    /* Distance from root of call tree.  Tail and hot/cold branches    /* Distance from root of call tree.  Tail and hot/cold branches
# Line 415  struct spu_elf_stack_info Line 433  struct spu_elf_stack_info
433    struct function_info fun[1];    struct function_info fun[1];
434  };  };
435    
436    static struct function_info *find_function (asection *, bfd_vma,
437                                                struct bfd_link_info *);
438    
439  /* Create a spu ELF linker hash table.  */  /* Create a spu ELF linker hash table.  */
440    
441  static struct bfd_link_hash_table *  static struct bfd_link_hash_table *
# Line 447  spu_elf_link_hash_table_create (bfd *abf Line 468  spu_elf_link_hash_table_create (bfd *abf
468  void  void
469  spu_elf_setup (struct bfd_link_info *info, struct spu_elf_params *params)  spu_elf_setup (struct bfd_link_info *info, struct spu_elf_params *params)
470  {  {
471      bfd_vma max_branch_log2;
472    
473    struct spu_link_hash_table *htab = spu_hash_table (info);    struct spu_link_hash_table *htab = spu_hash_table (info);
474    htab->params = params;    htab->params = params;
475      htab->line_size_log2 = bfd_log2 (htab->params->line_size);
476      htab->num_lines_log2 = bfd_log2 (htab->params->num_lines);
477    
478      /* For the software i-cache, we provide a "from" list whose size
479         is a power-of-two number of quadwords, big enough to hold one
480         byte per outgoing branch.  Compute this number here.  */
481      max_branch_log2 = bfd_log2 (htab->params->max_branch);
482      htab->fromelem_size_log2 = max_branch_log2 > 4 ? max_branch_log2 - 4 : 0;
483  }  }
484    
485  /* Find the symbol for the given R_SYMNDX in IBFD and set *HP and *SYMP  /* Find the symbol for the given R_SYMNDX in IBFD and set *HP and *SYMP
# Line 587  sort_sections (const void *a, const void Line 618  sort_sections (const void *a, const void
618    return (*s1)->index - (*s2)->index;    return (*s1)->index - (*s2)->index;
619  }  }
620    
621  /* Identify overlays in the output bfd, and number them.  */  /* Identify overlays in the output bfd, and number them.
622       Returns 0 on error, 1 if no overlays, 2 if overlays.  */
623    
624  bfd_boolean  int
625  spu_elf_find_overlays (struct bfd_link_info *info)  spu_elf_find_overlays (struct bfd_link_info *info)
626  {  {
627    struct spu_link_hash_table *htab = spu_hash_table (info);    struct spu_link_hash_table *htab = spu_hash_table (info);
# Line 597  spu_elf_find_overlays (struct bfd_link_i Line 629  spu_elf_find_overlays (struct bfd_link_i
629    unsigned int i, n, ovl_index, num_buf;    unsigned int i, n, ovl_index, num_buf;
630    asection *s;    asection *s;
631    bfd_vma ovl_end;    bfd_vma ovl_end;
632      static const char *const entry_names[2][2] = {
633        { "__ovly_load", "__icache_br_handler" },
634        { "__ovly_return", "__icache_call_handler" }
635      };
636    
637    if (info->output_bfd->section_count < 2)    if (info->output_bfd->section_count < 2)
638      return FALSE;      return 1;
639    
640    alloc_sec    alloc_sec
641      = bfd_malloc (info->output_bfd->section_count * sizeof (*alloc_sec));      = bfd_malloc (info->output_bfd->section_count * sizeof (*alloc_sec));
642    if (alloc_sec == NULL)    if (alloc_sec == NULL)
643      return FALSE;      return 0;
644    
645    /* Pick out all the alloced sections.  */    /* Pick out all the alloced sections.  */
646    for (n = 0, s = info->output_bfd->sections; s != NULL; s = s->next)    for (n = 0, s = info->output_bfd->sections; s != NULL; s = s->next)
# Line 616  spu_elf_find_overlays (struct bfd_link_i Line 652  spu_elf_find_overlays (struct bfd_link_i
652    if (n == 0)    if (n == 0)
653      {      {
654        free (alloc_sec);        free (alloc_sec);
655        return FALSE;        return 1;
656      }      }
657    
658    /* Sort them by vma.  */    /* Sort them by vma.  */
659    qsort (alloc_sec, n, sizeof (*alloc_sec), sort_sections);    qsort (alloc_sec, n, sizeof (*alloc_sec), sort_sections);
660    
   /* Look for overlapping vmas.  Any with overlap must be overlays.  
      Count them.  Also count the number of overlay regions.  */  
661    ovl_end = alloc_sec[0]->vma + alloc_sec[0]->size;    ovl_end = alloc_sec[0]->vma + alloc_sec[0]->size;
662    for (ovl_index = 0, num_buf = 0, i = 1; i < n; i++)    if (htab->params->ovly_flavour == ovly_soft_icache)
663      {      {
664        s = alloc_sec[i];        /* Look for an overlapping vma to find the first overlay section.  */
665        if (s->vma < ovl_end)        bfd_vma vma_start = 0;
666          bfd_vma lma_start = 0;
667    
668          for (i = 1; i < n; i++)
669          {          {
670            asection *s0 = alloc_sec[i - 1];            s = alloc_sec[i];
671              if (s->vma < ovl_end)
672                {
673                  asection *s0 = alloc_sec[i - 1];
674                  vma_start = s0->vma;
675                  if (strncmp (s0->name, ".ovl.init", 9) != 0)
676                    lma_start = s0->lma;
677                  else
678                    lma_start = s->lma;
679                  ovl_end = (s0->vma
680                             + ((bfd_vma) 1
681                                << (htab->num_lines_log2 + htab->line_size_log2)));
682                  --i;
683                  break;
684                }
685              else
686                ovl_end = s->vma + s->size;
687            }
688    
689            if (spu_elf_section_data (s0)->u.o.ovl_index == 0)        /* Now find any sections within the cache area.  */
690          for (ovl_index = 0, num_buf = 0; i < n; i++)
691            {
692              s = alloc_sec[i];
693              if (s->vma >= ovl_end)
694                break;
695    
696              /* A section in an overlay area called .ovl.init is not
697                 an overlay, in the sense that it might be loaded in
698                 by the overlay manager, but rather the initial
699                 section contents for the overlay buffer.  */
700              if (strncmp (s->name, ".ovl.init", 9) != 0)
701              {              {
702                alloc_sec[ovl_index] = s0;                num_buf = ((s->vma - vma_start) >> htab->line_size_log2) + 1;
703                spu_elf_section_data (s0)->u.o.ovl_index = ++ovl_index;                if (((s->vma - vma_start) & (htab->params->line_size - 1))
704                spu_elf_section_data (s0)->u.o.ovl_buf = ++num_buf;                    || ((s->lma - lma_start) & (htab->params->line_size - 1)))
705                    {
706                      info->callbacks->einfo (_("%X%P: overlay section %A "
707                                                "does not start on a cache line.\n"),
708                                              s);
709                      bfd_set_error (bfd_error_bad_value);
710                      return 0;
711                    }
712                  else if (s->size > htab->params->line_size)
713                    {
714                      info->callbacks->einfo (_("%X%P: overlay section %A "
715                                                "is larger than a cache line.\n"),
716                                              s);
717                      bfd_set_error (bfd_error_bad_value);
718                      return 0;
719                    }
720    
721                  alloc_sec[ovl_index++] = s;
722                  spu_elf_section_data (s)->u.o.ovl_index
723                    = ((s->lma - lma_start) >>  htab->line_size_log2) + 1;
724                  spu_elf_section_data (s)->u.o.ovl_buf = num_buf;
725              }              }
726            alloc_sec[ovl_index] = s;          }
727            spu_elf_section_data (s)->u.o.ovl_index = ++ovl_index;  
728            spu_elf_section_data (s)->u.o.ovl_buf = num_buf;        /* Ensure there are no more overlay sections.  */
729            if (s0->vma != s->vma)        for ( ; i < n; i++)
730            {
731              s = alloc_sec[i];
732              if (s->vma < ovl_end)
733              {              {
734                info->callbacks->einfo (_("%X%P: overlay sections %A and %A "                info->callbacks->einfo (_("%X%P: overlay section %A "
735                                          "do not start at the same address.\n"),                                          "is not in cache area.\n"),
736                                        s0, s);                                        alloc_sec[i-1]);
737                return FALSE;                bfd_set_error (bfd_error_bad_value);
738                  return 0;
739                }
740              else
741                ovl_end = s->vma + s->size;
742            }
743        }
744      else
745        {
746          /* Look for overlapping vmas.  Any with overlap must be overlays.
747             Count them.  Also count the number of overlay regions.  */
748          for (ovl_index = 0, num_buf = 0, i = 1; i < n; i++)
749            {
750              s = alloc_sec[i];
751              if (s->vma < ovl_end)
752                {
753                  asection *s0 = alloc_sec[i - 1];
754    
755                  if (spu_elf_section_data (s0)->u.o.ovl_index == 0)
756                    {
757                      ++num_buf;
758                      if (strncmp (s0->name, ".ovl.init", 9) != 0)
759                        {
760                          alloc_sec[ovl_index] = s0;
761                          spu_elf_section_data (s0)->u.o.ovl_index = ++ovl_index;
762                          spu_elf_section_data (s0)->u.o.ovl_buf = num_buf;
763                        }
764                      else
765                        ovl_end = s->vma + s->size;
766                    }
767                  if (strncmp (s->name, ".ovl.init", 9) != 0)
768                    {
769                      alloc_sec[ovl_index] = s;
770                      spu_elf_section_data (s)->u.o.ovl_index = ++ovl_index;
771                      spu_elf_section_data (s)->u.o.ovl_buf = num_buf;
772                      if (s0->vma != s->vma)
773                        {
774                          info->callbacks->einfo (_("%X%P: overlay sections %A "
775                                                    "and %A do not start at the "
776                                                    "same address.\n"),
777                                                  s0, s);
778                          bfd_set_error (bfd_error_bad_value);
779                          return 0;
780                        }
781                      if (ovl_end < s->vma + s->size)
782                        ovl_end = s->vma + s->size;
783                    }
784              }              }
785            if (ovl_end < s->vma + s->size)            else
786              ovl_end = s->vma + s->size;              ovl_end = s->vma + s->size;
787          }          }
       else  
         ovl_end = s->vma + s->size;  
788      }      }
789    
790    htab->num_overlays = ovl_index;    htab->num_overlays = ovl_index;
791    htab->num_buf = num_buf;    htab->num_buf = num_buf;
792    htab->ovl_sec = alloc_sec;    htab->ovl_sec = alloc_sec;
793    htab->ovly_load = elf_link_hash_lookup (&htab->elf, "__ovly_load",  
794                                            FALSE, FALSE, FALSE);    if (ovl_index == 0)
795    htab->ovly_return = elf_link_hash_lookup (&htab->elf, "__ovly_return",      return 1;
796                                              FALSE, FALSE, FALSE);  
797    return ovl_index != 0;    for (i = 0; i < 2; i++)
798        {
799          const char *name;
800          struct elf_link_hash_entry *h;
801    
802          name = entry_names[i][htab->params->ovly_flavour];
803          h = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE);
804          if (h == NULL)
805            return 0;
806    
807          if (h->root.type == bfd_link_hash_new)
808            {
809              h->root.type = bfd_link_hash_undefined;
810              h->ref_regular = 1;
811              h->ref_regular_nonweak = 1;
812              h->non_elf = 0;
813            }
814          htab->ovly_entry[i] = h;
815        }
816    
817      return 2;
818  }  }
819    
820  #define BRSL    0x33000000  /* Non-zero to use bra in overlay stubs rather than br.  */
821    #define BRA_STUBS 0
822    
823    #define BRA     0x30000000
824    #define BRASL   0x31000000
825  #define BR      0x32000000  #define BR      0x32000000
826    #define BRSL    0x33000000
827  #define NOP     0x40200000  #define NOP     0x40200000
828  #define LNOP    0x00200000  #define LNOP    0x00200000
829  #define ILA     0x42000000  #define ILA     0x42000000
# Line 736  maybe_needs_stubs (asection *input_secti Line 893  maybe_needs_stubs (asection *input_secti
893  enum _stub_type  enum _stub_type
894  {  {
895    no_stub,    no_stub,
896    ovl_stub,    call_ovl_stub,
897      br000_ovl_stub,
898      br001_ovl_stub,
899      br010_ovl_stub,
900      br011_ovl_stub,
901      br100_ovl_stub,
902      br101_ovl_stub,
903      br110_ovl_stub,
904      br111_ovl_stub,
905    nonovl_stub,    nonovl_stub,
906    stub_error    stub_error
907  };  };
# Line 756  needs_ovl_stub (struct elf_link_hash_ent Line 921  needs_ovl_stub (struct elf_link_hash_ent
921    struct spu_link_hash_table *htab = spu_hash_table (info);    struct spu_link_hash_table *htab = spu_hash_table (info);
922    enum elf_spu_reloc_type r_type;    enum elf_spu_reloc_type r_type;
923    unsigned int sym_type;    unsigned int sym_type;
924    bfd_boolean branch;    bfd_boolean branch, hint, call;
925    enum _stub_type ret = no_stub;    enum _stub_type ret = no_stub;
926      bfd_byte insn[4];
927    
928    if (sym_sec == NULL    if (sym_sec == NULL
929        || sym_sec->output_section == bfd_abs_section_ptr        || sym_sec->output_section == bfd_abs_section_ptr
# Line 767  needs_ovl_stub (struct elf_link_hash_ent Line 933  needs_ovl_stub (struct elf_link_hash_ent
933    if (h != NULL)    if (h != NULL)
934      {      {
935        /* Ensure no stubs for user supplied overlay manager syms.  */        /* Ensure no stubs for user supplied overlay manager syms.  */
936        if (h == htab->ovly_load || h == htab->ovly_return)        if (h == htab->ovly_entry[0] || h == htab->ovly_entry[1])
937          return ret;          return ret;
938    
939        /* setjmp always goes via an overlay stub, because then the return        /* setjmp always goes via an overlay stub, because then the return
# Line 775  needs_ovl_stub (struct elf_link_hash_ent Line 941  needs_ovl_stub (struct elf_link_hash_ent
941           makes setjmp/longjmp between overlays work.  */           makes setjmp/longjmp between overlays work.  */
942        if (strncmp (h->root.root.string, "setjmp", 6) == 0        if (strncmp (h->root.root.string, "setjmp", 6) == 0
943            && (h->root.root.string[6] == '\0' || h->root.root.string[6] == '@'))            && (h->root.root.string[6] == '\0' || h->root.root.string[6] == '@'))
944          ret = ovl_stub;          ret = call_ovl_stub;
945      }      }
946    
   /* Usually, symbols in non-overlay sections don't need stubs.  */  
   if (spu_elf_section_data (sym_sec->output_section)->u.o.ovl_index == 0  
       && !htab->params->non_overlay_stubs)  
     return ret;  
   
947    if (h != NULL)    if (h != NULL)
948      sym_type = h->type;      sym_type = h->type;
949    else    else
# Line 790  needs_ovl_stub (struct elf_link_hash_ent Line 951  needs_ovl_stub (struct elf_link_hash_ent
951    
952    r_type = ELF32_R_TYPE (irela->r_info);    r_type = ELF32_R_TYPE (irela->r_info);
953    branch = FALSE;    branch = FALSE;
954      hint = FALSE;
955      call = FALSE;
956    if (r_type == R_SPU_REL16 || r_type == R_SPU_ADDR16)    if (r_type == R_SPU_REL16 || r_type == R_SPU_ADDR16)
957      {      {
       bfd_byte insn[4];  
   
958        if (contents == NULL)        if (contents == NULL)
959          {          {
960            contents = insn;            contents = insn;
# Line 806  needs_ovl_stub (struct elf_link_hash_ent Line 967  needs_ovl_stub (struct elf_link_hash_ent
967        else        else
968          contents += irela->r_offset;          contents += irela->r_offset;
969    
970        if (is_branch (contents) || is_hint (contents))        branch = is_branch (contents);
971          hint = is_hint (contents);
972          if (branch || hint)
973          {          {
974            branch = TRUE;            call = (contents[0] & 0xfd) == 0x31;
975            if ((contents[0] & 0xfd) == 0x31            if (call
976                && sym_type != STT_FUNC                && sym_type != STT_FUNC
977                && contents != insn)                && contents != insn)
978              {              {
# Line 840  needs_ovl_stub (struct elf_link_hash_ent Line 1003  needs_ovl_stub (struct elf_link_hash_ent
1003          }          }
1004      }      }
1005    
1006    if (sym_type != STT_FUNC    if ((!branch && htab->params->ovly_flavour == ovly_soft_icache)
1007        && !branch        || (sym_type != STT_FUNC
1008        && (sym_sec->flags & SEC_CODE) == 0)            && !(branch || hint)
1009              && (sym_sec->flags & SEC_CODE) == 0))
1010        return no_stub;
1011    
1012      /* Usually, symbols in non-overlay sections don't need stubs.  */
1013      if (spu_elf_section_data (sym_sec->output_section)->u.o.ovl_index == 0
1014          && !htab->params->non_overlay_stubs)
1015      return ret;      return ret;
1016    
1017    /* A reference from some other section to a symbol in an overlay    /* A reference from some other section to a symbol in an overlay
1018       section needs a stub.  */       section needs a stub.  */
1019    if (spu_elf_section_data (sym_sec->output_section)->u.o.ovl_index    if (spu_elf_section_data (sym_sec->output_section)->u.o.ovl_index
1020         != spu_elf_section_data (input_section->output_section)->u.o.ovl_index)         != spu_elf_section_data (input_section->output_section)->u.o.ovl_index)
1021      ret = ovl_stub;      {
1022          unsigned int lrlive = 0;
1023          if (branch)
1024            lrlive = (contents[1] & 0x70) >> 4;
1025    
1026          if (!lrlive && (call || sym_type == STT_FUNC))
1027            ret = call_ovl_stub;
1028          else
1029            ret = br000_ovl_stub + lrlive;
1030        }
1031    
1032    /* If this insn isn't a branch then we are possibly taking the    /* If this insn isn't a branch then we are possibly taking the
1033       address of a function and passing it out somehow.  */       address of a function and passing it out somehow.  Soft-icache code
1034    return !branch && sym_type == STT_FUNC ? nonovl_stub : ret;       always generates inline code to do indirect branches.  */
1035      if (!(branch || hint)
1036          && sym_type == STT_FUNC
1037          && htab->params->ovly_flavour != ovly_soft_icache)
1038        ret = nonovl_stub;
1039    
1040      return ret;
1041  }  }
1042    
1043  static bfd_boolean  static bfd_boolean
# Line 891  count_stub (struct spu_link_hash_table * Line 1075  count_stub (struct spu_link_hash_table *
1075        head = elf_local_got_ents (ibfd) + ELF32_R_SYM (irela->r_info);        head = elf_local_got_ents (ibfd) + ELF32_R_SYM (irela->r_info);
1076      }      }
1077    
1078      if (htab->params->ovly_flavour == ovly_soft_icache)
1079        {
1080          htab->stub_count[ovl] += 1;
1081          return TRUE;
1082        }
1083    
1084    addend = 0;    addend = 0;
1085    if (irela != NULL)    if (irela != NULL)
1086      addend = irela->r_addend;      addend = irela->r_addend;
# Line 942  count_stub (struct spu_link_hash_table * Line 1132  count_stub (struct spu_link_hash_table *
1132  }  }
1133    
1134  /* Support two sizes of overlay stubs, a slower more compact stub of two  /* Support two sizes of overlay stubs, a slower more compact stub of two
1135     intructions, and a faster stub of four instructions.  */     intructions, and a faster stub of four instructions.
1136       Soft-icache stubs are four or eight words.  */
1137    
1138    static unsigned int
1139    ovl_stub_size (struct spu_elf_params *params)
1140    {
1141      return 16 << params->ovly_flavour >> params->compact_stub;
1142    }
1143    
1144  static unsigned int  static unsigned int
1145  ovl_stub_size (enum _ovly_flavour ovly_flavour)  ovl_stub_size_log2 (struct spu_elf_params *params)
1146  {  {
1147    return 8 << ovly_flavour;    return 4 + params->ovly_flavour - params->compact_stub;
1148  }  }
1149    
1150  /* Two instruction overlay stubs look like:  /* Two instruction overlay stubs look like:
# Line 963  ovl_stub_size (enum _ovly_flavour ovly_f Line 1160  ovl_stub_size (enum _ovly_flavour ovly_f
1160     ila $78,ovl_number     ila $78,ovl_number
1161     lnop     lnop
1162     ila $79,target_address     ila $79,target_address
1163     br __ovly_load  */     br __ovly_load
1164    
1165       Software icache stubs are:
1166    
1167       .word target_index
1168       .word target_ia;
1169       .word lrlive_branchlocalstoreaddr;
1170       brasl $75,__icache_br_handler
1171       .quad xor_pattern
1172    */
1173    
1174  static bfd_boolean  static bfd_boolean
1175  build_stub (struct spu_link_hash_table *htab,  build_stub (struct bfd_link_info *info,
1176              bfd *ibfd,              bfd *ibfd,
1177              asection *isec,              asection *isec,
1178              enum _stub_type stub_type,              enum _stub_type stub_type,
# Line 975  build_stub (struct spu_link_hash_table * Line 1181  build_stub (struct spu_link_hash_table *
1181              bfd_vma dest,              bfd_vma dest,
1182              asection *dest_sec)              asection *dest_sec)
1183  {  {
1184    unsigned int ovl, dest_ovl;    struct spu_link_hash_table *htab = spu_hash_table (info);
1185      unsigned int ovl, dest_ovl, set_id;
1186    struct got_entry *g, **head;    struct got_entry *g, **head;
1187    asection *sec;    asection *sec;
1188    bfd_vma addend, from, to;    bfd_vma addend, from, to, br_dest, patt;
1189      unsigned int lrlive;
1190    
1191    ovl = 0;    ovl = 0;
1192    if (stub_type != nonovl_stub)    if (stub_type != nonovl_stub)
# Line 993  build_stub (struct spu_link_hash_table * Line 1201  build_stub (struct spu_link_hash_table *
1201    if (irela != NULL)    if (irela != NULL)
1202      addend = irela->r_addend;      addend = irela->r_addend;
1203    
1204    for (g = *head; g != NULL; g = g->next)    if (htab->params->ovly_flavour == ovly_soft_icache)
1205      if (g->addend == addend && (g->ovl == ovl || g->ovl == 0))      {
1206        break;        g = bfd_malloc (sizeof *g);
1207    if (g == NULL)        if (g == NULL)
1208      abort ();          return FALSE;
1209          g->ovl = ovl;
1210          g->br_addr = 0;
1211          if (irela != NULL)
1212            g->br_addr = (irela->r_offset
1213                          + isec->output_offset
1214                          + isec->output_section->vma);
1215          g->next = *head;
1216          *head = g;
1217        }
1218      else
1219        {
1220          for (g = *head; g != NULL; g = g->next)
1221            if (g->addend == addend && (g->ovl == ovl || g->ovl == 0))
1222              break;
1223          if (g == NULL)
1224            abort ();
1225    
1226    if (g->ovl == 0 && ovl != 0)        if (g->ovl == 0 && ovl != 0)
1227      return TRUE;          return TRUE;
1228    
1229    if (g->stub_addr != (bfd_vma) -1)        if (g->stub_addr != (bfd_vma) -1)
1230      return TRUE;          return TRUE;
1231        }
1232    
1233    sec = htab->stub_sec[ovl];    sec = htab->stub_sec[ovl];
1234    dest += dest_sec->output_offset + dest_sec->output_section->vma;    dest += dest_sec->output_offset + dest_sec->output_section->vma;
1235    from = sec->size + sec->output_offset + sec->output_section->vma;    from = sec->size + sec->output_offset + sec->output_section->vma;
1236    g->stub_addr = from;    g->stub_addr = from;
1237    to = (htab->ovly_load->root.u.def.value    to = (htab->ovly_entry[0]->root.u.def.value
1238          + htab->ovly_load->root.u.def.section->output_offset          + htab->ovly_entry[0]->root.u.def.section->output_offset
1239          + htab->ovly_load->root.u.def.section->output_section->vma);          + htab->ovly_entry[0]->root.u.def.section->output_section->vma);
1240    
1241    if (((dest | to | from) & 3) != 0)    if (((dest | to | from) & 3) != 0)
1242      {      {
# Line 1020  build_stub (struct spu_link_hash_table * Line 1245  build_stub (struct spu_link_hash_table *
1245      }      }
1246    dest_ovl = spu_elf_section_data (dest_sec->output_section)->u.o.ovl_index;    dest_ovl = spu_elf_section_data (dest_sec->output_section)->u.o.ovl_index;
1247    
1248    switch (htab->params->ovly_flavour)    if (htab->params->ovly_flavour == ovly_normal
1249          && !htab->params->compact_stub)
1250      {      {
     case ovly_normal:  
1251        bfd_put_32 (sec->owner, ILA + ((dest_ovl << 7) & 0x01ffff80) + 78,        bfd_put_32 (sec->owner, ILA + ((dest_ovl << 7) & 0x01ffff80) + 78,
1252                    sec->contents + sec->size);                    sec->contents + sec->size);
1253        bfd_put_32 (sec->owner, LNOP,        bfd_put_32 (sec->owner, LNOP,
1254                    sec->contents + sec->size + 4);                    sec->contents + sec->size + 4);
1255        bfd_put_32 (sec->owner, ILA + ((dest << 7) & 0x01ffff80) + 79,        bfd_put_32 (sec->owner, ILA + ((dest << 7) & 0x01ffff80) + 79,
1256                    sec->contents + sec->size + 8);                    sec->contents + sec->size + 8);
1257        bfd_put_32 (sec->owner, BR + (((to - (from + 12)) << 5) & 0x007fff80),        if (!BRA_STUBS)
1258                    sec->contents + sec->size + 12);          bfd_put_32 (sec->owner, BR + (((to - (from + 12)) << 5) & 0x007fff80),
1259        break;                      sec->contents + sec->size + 12);
1260          else
1261            bfd_put_32 (sec->owner, BRA + ((to << 5) & 0x007fff80),
1262                        sec->contents + sec->size + 12);
1263        }
1264      else if (htab->params->ovly_flavour == ovly_normal
1265               && htab->params->compact_stub)
1266        {
1267          if (!BRA_STUBS)
1268            bfd_put_32 (sec->owner, BRSL + (((to - from) << 5) & 0x007fff80) + 75,
1269                        sec->contents + sec->size);
1270          else
1271            bfd_put_32 (sec->owner, BRASL + ((to << 5) & 0x007fff80) + 75,
1272                        sec->contents + sec->size);
1273          bfd_put_32 (sec->owner, (dest & 0x3ffff) | (dest_ovl << 18),
1274                      sec->contents + sec->size + 4);
1275        }
1276      else if (htab->params->ovly_flavour == ovly_soft_icache
1277               && htab->params->compact_stub)
1278        {
1279          lrlive = 0;
1280          if (stub_type == nonovl_stub)
1281            ;
1282          else if (stub_type == call_ovl_stub)
1283            /* A brsl makes lr live and *(*sp+16) is live.
1284               Tail calls have the same liveness.  */
1285            lrlive = 5;
1286          else if (!htab->params->lrlive_analysis)
1287            /* Assume stack frame and lr save.  */
1288            lrlive = 1;
1289          else if (irela != NULL)
1290            {
1291              /* Analyse branch instructions.  */
1292              struct function_info *caller;
1293              bfd_vma off;
1294    
1295              caller = find_function (isec, irela->r_offset, info);
1296              if (caller->start == NULL)
1297                off = irela->r_offset;
1298              else
1299                {
1300                  struct function_info *found = NULL;
1301    
1302                  /* Find the earliest piece of this function that
1303                     has frame adjusting instructions.  We might
1304                     see dynamic frame adjustment (eg. for alloca)
1305                     in some later piece, but functions using
1306                     alloca always set up a frame earlier.  Frame
1307                     setup instructions are always in one piece.  */
1308                  if (caller->lr_store != (bfd_vma) -1
1309                      || caller->sp_adjust != (bfd_vma) -1)
1310                    found = caller;
1311                  while (caller->start != NULL)
1312                    {
1313                      caller = caller->start;
1314                      if (caller->lr_store != (bfd_vma) -1
1315                          || caller->sp_adjust != (bfd_vma) -1)
1316                        found = caller;
1317                    }
1318                  if (found != NULL)
1319                    caller = found;
1320                  off = (bfd_vma) -1;
1321                }
1322    
1323              if (off > caller->sp_adjust)
1324                {
1325                  if (off > caller->lr_store)
1326                    /* Only *(*sp+16) is live.  */
1327                    lrlive = 1;
1328                  else
1329                    /* If no lr save, then we must be in a
1330                       leaf function with a frame.
1331                       lr is still live.  */
1332                    lrlive = 4;
1333                }
1334              else if (off > caller->lr_store)
1335                {
1336                  /* Between lr save and stack adjust.  */
1337                  lrlive = 3;
1338                  /* This should never happen since prologues won't
1339                     be split here.  */
1340                  BFD_ASSERT (0);
1341                }
1342              else
1343                /* On entry to function.  */
1344                lrlive = 5;
1345    
1346              if (stub_type != br000_ovl_stub
1347                  && lrlive != stub_type - br000_ovl_stub)
1348                info->callbacks->einfo (_("%A:0x%v lrlive .brinfo (%u) differs "
1349                                          "from analysis (%u)\n"),
1350                                        isec, irela->r_offset, lrlive,
1351                                        stub_type - br000_ovl_stub);
1352            }
1353    
1354          /* If given lrlive info via .brinfo, use it.  */
1355          if (stub_type > br000_ovl_stub)
1356            lrlive = stub_type - br000_ovl_stub;
1357    
1358          if (ovl == 0)
1359            to = (htab->ovly_entry[1]->root.u.def.value
1360                  + htab->ovly_entry[1]->root.u.def.section->output_offset
1361                  + htab->ovly_entry[1]->root.u.def.section->output_section->vma);
1362    
1363          /* The branch that uses this stub goes to stub_addr + 4.  We'll
1364             set up an xor pattern that can be used by the icache manager
1365             to modify this branch to go directly to its destination.  */
1366          g->stub_addr += 4;
1367          br_dest = g->stub_addr;
1368          if (irela == NULL)
1369            {
1370              /* Except in the case of _SPUEAR_ stubs, the branch in
1371                 question is the one in the stub itself.  */
1372              BFD_ASSERT (stub_type == nonovl_stub);
1373              g->br_addr = g->stub_addr;
1374              br_dest = to;
1375            }
1376    
1377      case ovly_compact:        set_id = ((dest_ovl - 1) >> htab->num_lines_log2) + 1;
1378        bfd_put_32 (sec->owner, BRSL + (((to - from) << 5) & 0x007fff80) + 75,        bfd_put_32 (sec->owner, (set_id << 18) | (dest & 0x3ffff),
1379                    sec->contents + sec->size);                    sec->contents + sec->size);
1380        bfd_put_32 (sec->owner, (dest & 0x3ffff) | (dest_ovl << 18),        bfd_put_32 (sec->owner, BRASL + ((to << 5) & 0x007fff80) + 75,
1381                    sec->contents + sec->size + 4);                    sec->contents + sec->size + 4);
1382        break;        bfd_put_32 (sec->owner, (lrlive << 29) | (g->br_addr & 0x3ffff),
1383                      sec->contents + sec->size + 8);
1384          patt = dest ^ br_dest;
1385          if (irela != NULL && ELF32_R_TYPE (irela->r_info) == R_SPU_REL16)
1386            patt = (dest - g->br_addr) ^ (br_dest - g->br_addr);
1387          bfd_put_32 (sec->owner, (patt << 5) & 0x007fff80,
1388                      sec->contents + sec->size + 12);
1389    
1390      default:        if (ovl == 0)
1391        abort ();          /* Extra space for linked list entries.  */
1392            sec->size += 16;
1393      }      }
1394    sec->size += ovl_stub_size (htab->params->ovly_flavour);    else
1395        abort ();
1396    
1397      sec->size += ovl_stub_size (htab->params);
1398    
1399    if (htab->params->emit_stub_syms)    if (htab->params->emit_stub_syms)
1400      {      {
# Line 1083  build_stub (struct spu_link_hash_table * Line 1434  build_stub (struct spu_link_hash_table *
1434          {          {
1435            h->root.type = bfd_link_hash_defined;            h->root.type = bfd_link_hash_defined;
1436            h->root.u.def.section = sec;            h->root.u.def.section = sec;
1437            h->size = ovl_stub_size (htab->params->ovly_flavour);            h->size = ovl_stub_size (htab->params);
1438            h->root.u.def.value = sec->size - h->size;            h->root.u.def.value = sec->size - h->size;
1439            h->type = STT_FUNC;            h->type = STT_FUNC;
1440            h->ref_regular = 1;            h->ref_regular = 1;
# Line 1144  build_spuear_stubs (struct elf_link_hash Line 1495  build_spuear_stubs (struct elf_link_hash
1495        && (spu_elf_section_data (sym_sec->output_section)->u.o.ovl_index != 0        && (spu_elf_section_data (sym_sec->output_section)->u.o.ovl_index != 0
1496            || htab->params->non_overlay_stubs))            || htab->params->non_overlay_stubs))
1497      {      {
1498        return build_stub (htab, NULL, NULL, nonovl_stub, h, NULL,        return build_stub (info, NULL, NULL, nonovl_stub, h, NULL,
1499                           h->root.u.def.value, sym_sec);                           h->root.u.def.value, sym_sec);
1500      }      }
1501        
# Line 1256  process_stubs (struct bfd_link_info *inf Line 1607  process_stubs (struct bfd_link_info *inf
1607                    else                    else
1608                      dest = sym->st_value;                      dest = sym->st_value;
1609                    dest += irela->r_addend;                    dest += irela->r_addend;
1610                    if (!build_stub (htab, ibfd, isec, stub_type, h, irela,                    if (!build_stub (info, ibfd, isec, stub_type, h, irela,
1611                                     dest, sym_sec))                                     dest, sym_sec))
1612                      goto error_ret_free_internal;                      goto error_ret_free_internal;
1613                  }                  }
# Line 1280  process_stubs (struct bfd_link_info *inf Line 1631  process_stubs (struct bfd_link_info *inf
1631    return TRUE;    return TRUE;
1632  }  }
1633    
1634  /* Allocate space for overlay call and return stubs.  */  /* Allocate space for overlay call and return stubs.
1635       Return 0 on error, 1 if no overlays, 2 otherwise.  */
1636    
1637  int  int
1638  spu_elf_size_stubs (struct bfd_link_info *info)  spu_elf_size_stubs (struct bfd_link_info *info)
# Line 1300  spu_elf_size_stubs (struct bfd_link_info Line 1652  spu_elf_size_stubs (struct bfd_link_info
1652    if (htab->stub_err)    if (htab->stub_err)
1653      return 0;      return 0;
1654    
   if (htab->stub_count == NULL)  
     return 1;  
   
1655    ibfd = info->input_bfds;    ibfd = info->input_bfds;
1656    amt = (htab->num_overlays + 1) * sizeof (*htab->stub_sec);    if (htab->stub_count != NULL)
   htab->stub_sec = bfd_zmalloc (amt);  
   if (htab->stub_sec == NULL)  
     return 0;  
   
   flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY  
            | SEC_HAS_CONTENTS | SEC_IN_MEMORY);  
   stub = bfd_make_section_anyway_with_flags (ibfd, ".stub", flags);  
   htab->stub_sec[0] = stub;  
   if (stub == NULL  
       || !bfd_set_section_alignment (ibfd, stub,  
                                      htab->params->ovly_flavour + 3))  
     return 0;  
   stub->size = htab->stub_count[0] * ovl_stub_size (htab->params->ovly_flavour);  
   (*htab->params->place_spu_section) (stub, NULL, ".text");  
   
   for (i = 0; i < htab->num_overlays; ++i)  
1657      {      {
1658        asection *osec = htab->ovl_sec[i];        amt = (htab->num_overlays + 1) * sizeof (*htab->stub_sec);
1659        unsigned int ovl = spu_elf_section_data (osec)->u.o.ovl_index;        htab->stub_sec = bfd_zmalloc (amt);
1660          if (htab->stub_sec == NULL)
1661            return 0;
1662    
1663          flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY
1664                   | SEC_HAS_CONTENTS | SEC_IN_MEMORY);
1665        stub = bfd_make_section_anyway_with_flags (ibfd, ".stub", flags);        stub = bfd_make_section_anyway_with_flags (ibfd, ".stub", flags);
1666        htab->stub_sec[ovl] = stub;        htab->stub_sec[0] = stub;
1667        if (stub == NULL        if (stub == NULL
1668            || !bfd_set_section_alignment (ibfd, stub,            || !bfd_set_section_alignment (ibfd, stub,
1669                                           htab->params->ovly_flavour + 3))                                           ovl_stub_size_log2 (htab->params)))
1670          return 0;          return 0;
1671        stub->size = htab->stub_count[ovl] * ovl_stub_size (htab->params->ovly_flavour);        stub->size = htab->stub_count[0] * ovl_stub_size (htab->params);
1672        (*htab->params->place_spu_section) (stub, osec, NULL);        if (htab->params->ovly_flavour == ovly_soft_icache)
1673            /* Extra space for linked list entries.  */
1674            stub->size += htab->stub_count[0] * 16;
1675    
1676          for (i = 0; i < htab->num_overlays; ++i)
1677            {
1678              asection *osec = htab->ovl_sec[i];
1679              unsigned int ovl = spu_elf_section_data (osec)->u.o.ovl_index;
1680              stub = bfd_make_section_anyway_with_flags (ibfd, ".stub", flags);
1681              htab->stub_sec[ovl] = stub;
1682              if (stub == NULL
1683                  || !bfd_set_section_alignment (ibfd, stub,
1684                                                 ovl_stub_size_log2 (htab->params)))
1685                return 0;
1686              stub->size = htab->stub_count[ovl] * ovl_stub_size (htab->params);
1687            }
1688      }      }
1689    
1690   /* htab->ovtab consists of two arrays.    if (htab->params->ovly_flavour == ovly_soft_icache)
1691      .   struct {      {
1692      .     u32 vma;        /* Space for icache manager tables.
1693      .     u32 size;           a) Tag array, one quadword per cache line.
1694      .     u32 file_off;           b) Rewrite "to" list, one quadword per cache line.
1695      .     u32 buf;           c) Rewrite "from" list, one byte per outgoing branch (rounded up to
1696      .   } _ovly_table[];              a power-of-two number of full quadwords) per cache line.  */
1697      .  
1698      .   struct {        flags = SEC_ALLOC;
1699      .     u32 mapped;        htab->ovtab = bfd_make_section_anyway_with_flags (ibfd, ".ovtab", flags);
1700      .   } _ovly_buf_table[];        if (htab->ovtab == NULL
1701      .  */            || !bfd_set_section_alignment (ibfd, htab->ovtab, 4))
1702            return 0;
1703    flags = (SEC_ALLOC | SEC_LOAD  
1704             | SEC_HAS_CONTENTS | SEC_IN_MEMORY);        htab->ovtab->size = (16 + 16 + (16 << htab->fromelem_size_log2))
1705    htab->ovtab = bfd_make_section_anyway_with_flags (ibfd, ".ovtab", flags);                            << htab->num_lines_log2;
1706    if (htab->ovtab == NULL  
1707        || !bfd_set_section_alignment (ibfd, htab->ovtab, 4))        flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
1708      return 0;        htab->init = bfd_make_section_anyway_with_flags (ibfd, ".ovini", flags);
1709          if (htab->init == NULL
1710              || !bfd_set_section_alignment (ibfd, htab->init, 4))
1711            return 0;
1712    
1713          htab->init->size = 16;
1714        }
1715      else if (htab->stub_count == NULL)
1716        return 1;
1717      else
1718        {
1719          /* htab->ovtab consists of two arrays.
1720             .      struct {
1721             .        u32 vma;
1722             .        u32 size;
1723             .        u32 file_off;
1724             .        u32 buf;
1725             .      } _ovly_table[];
1726             .
1727             .      struct {
1728             .        u32 mapped;
1729             .      } _ovly_buf_table[];
1730             .  */
1731    
1732          flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
1733          htab->ovtab = bfd_make_section_anyway_with_flags (ibfd, ".ovtab", flags);
1734          if (htab->ovtab == NULL
1735              || !bfd_set_section_alignment (ibfd, htab->ovtab, 4))
1736            return 0;
1737    
1738    htab->ovtab->size = htab->num_overlays * 16 + 16 + htab->num_buf * 4;        htab->ovtab->size = htab->num_overlays * 16 + 16 + htab->num_buf * 4;
1739    (*htab->params->place_spu_section) (htab->ovtab, NULL, ".data");      }
1740    
1741    htab->toe = bfd_make_section_anyway_with_flags (ibfd, ".toe", SEC_ALLOC);    htab->toe = bfd_make_section_anyway_with_flags (ibfd, ".toe", SEC_ALLOC);
1742    if (htab->toe == NULL    if (htab->toe == NULL
1743        || !bfd_set_section_alignment (ibfd, htab->toe, 4))        || !bfd_set_section_alignment (ibfd, htab->toe, 4))
1744      return 0;      return 0;
1745    htab->toe->size = 16;    htab->toe->size = 16;
   (*htab->params->place_spu_section) (htab->toe, NULL, ".toe");  
1746    
1747    return 2;    return 2;
1748  }  }
1749    
1750    /* Called from ld to place overlay manager data sections.  This is done
1751       after the overlay manager itself is loaded, mainly so that the
1752       linker's htab->init section is placed after any other .ovl.init
1753       sections.  */
1754    
1755    void
1756    spu_elf_place_overlay_data (struct bfd_link_info *info)
1757    {
1758      struct spu_link_hash_table *htab = spu_hash_table (info);
1759      unsigned int i;
1760    
1761      if (htab->stub_sec != NULL)
1762        {
1763          (*htab->params->place_spu_section) (htab->stub_sec[0], NULL, ".text");
1764    
1765          for (i = 0; i < htab->num_overlays; ++i)
1766            {
1767              asection *osec = htab->ovl_sec[i];
1768              unsigned int ovl = spu_elf_section_data (osec)->u.o.ovl_index;
1769              (*htab->params->place_spu_section) (htab->stub_sec[ovl], osec, NULL);
1770            }
1771        }
1772    
1773      if (htab->params->ovly_flavour == ovly_soft_icache)
1774        (*htab->params->place_spu_section) (htab->init, NULL, ".ovl.init");
1775    
1776      if (htab->ovtab != NULL)
1777        {
1778          const char *ovout = ".data";
1779          if (htab->params->ovly_flavour == ovly_soft_icache)
1780            ovout = ".bss";
1781          (*htab->params->place_spu_section) (htab->ovtab, NULL, ovout);
1782        }
1783    
1784      if (htab->toe != NULL)
1785        (*htab->params->place_spu_section) (htab->toe, NULL, ".toe");
1786    }
1787    
1788  /* Functions to handle embedded spu_ovl.o object.  */  /* Functions to handle embedded spu_ovl.o object.  */
1789    
1790  static void *  static void *
# Line 1413  spu_elf_open_builtin_lib (bfd **ovl_bfd, Line 1831  spu_elf_open_builtin_lib (bfd **ovl_bfd,
1831    return *ovl_bfd != NULL;    return *ovl_bfd != NULL;
1832  }  }
1833    
1834    static unsigned int
1835    overlay_index (asection *sec)
1836    {
1837      if (sec == NULL
1838          || sec->output_section == bfd_abs_section_ptr)
1839        return 0;
1840      return spu_elf_section_data (sec->output_section)->u.o.ovl_index;
1841    }
1842    
1843  /* Define an STT_OBJECT symbol.  */  /* Define an STT_OBJECT symbol.  */
1844    
1845  static struct elf_link_hash_entry *  static struct elf_link_hash_entry *
# Line 1456  define_ovtab_symbol (struct spu_link_has Line 1883  define_ovtab_symbol (struct spu_link_has
1883    
1884  /* Fill in all stubs and the overlay tables.  */  /* Fill in all stubs and the overlay tables.  */
1885    
1886  bfd_boolean  static bfd_boolean
1887  spu_elf_build_stubs (struct bfd_link_info *info)  spu_elf_build_stubs (struct bfd_link_info *info)
1888  {  {
1889    struct spu_link_hash_table *htab = spu_hash_table (info);    struct spu_link_hash_table *htab = spu_hash_table (info);
# Line 1466  spu_elf_build_stubs (struct bfd_link_inf Line 1893  spu_elf_build_stubs (struct bfd_link_inf
1893    bfd *obfd;    bfd *obfd;
1894    unsigned int i;    unsigned int i;
1895    
1896    if (htab->stub_count == NULL)    if (htab->num_overlays != 0)
1897      return TRUE;      {
1898          for (i = 0; i < 2; i++)
1899    for (i = 0; i <= htab->num_overlays; i++)          {
1900      if (htab->stub_sec[i]->size != 0)            h = htab->ovly_entry[i];
1901        {            if (h != NULL
         htab->stub_sec[i]->contents = bfd_zalloc (htab->stub_sec[i]->owner,  
                                                   htab->stub_sec[i]->size);  
         if (htab->stub_sec[i]->contents == NULL)  
           return FALSE;  
         htab->stub_sec[i]->rawsize = htab->stub_sec[i]->size;  
         htab->stub_sec[i]->size = 0;  
       }  
   
   h = elf_link_hash_lookup (&htab->elf, "__ovly_load", FALSE, FALSE, FALSE);  
   htab->ovly_load = h;  
   BFD_ASSERT (h != NULL  
1902                && (h->root.type == bfd_link_hash_defined                && (h->root.type == bfd_link_hash_defined
1903                    || h->root.type == bfd_link_hash_defweak)                    || h->root.type == bfd_link_hash_defweak)
1904                && h->def_regular);                && h->def_regular)
1905                {
1906    s = h->root.u.def.section->output_section;                s = h->root.u.def.section->output_section;
1907    if (spu_elf_section_data (s)->u.o.ovl_index)                if (spu_elf_section_data (s)->u.o.ovl_index)
1908      {                  {
1909        (*_bfd_error_handler) (_("%s in overlay section"),                    (*_bfd_error_handler) (_("%s in overlay section"),
1910                               h->root.root.string);                                           h->root.root.string);
1911        bfd_set_error (bfd_error_bad_value);                    bfd_set_error (bfd_error_bad_value);
1912        return FALSE;                    return FALSE;
1913                    }
1914                }
1915            }
1916      }      }
1917    
1918    h = elf_link_hash_lookup (&htab->elf, "__ovly_return", FALSE, FALSE, FALSE);    if (htab->stub_sec != NULL)
   htab->ovly_return = h;  
   
   /* Fill in all the stubs.  */  
   process_stubs (info, TRUE);  
   if (!htab->stub_err)  
     elf_link_hash_traverse (&htab->elf, build_spuear_stubs, info);  
   
   if (htab->stub_err)  
1919      {      {
1920        (*_bfd_error_handler) (_("overlay stub relocation overflow"));        for (i = 0; i <= htab->num_overlays; i++)
1921        bfd_set_error (bfd_error_bad_value);          if (htab->stub_sec[i]->size != 0)
1922        return FALSE;            {
1923      }              htab->stub_sec[i]->contents = bfd_zalloc (htab->stub_sec[i]->owner,
1924                                                          htab->stub_sec[i]->size);
1925                if (htab->stub_sec[i]->contents == NULL)
1926                  return FALSE;
1927                htab->stub_sec[i]->rawsize = htab->stub_sec[i]->size;
1928                htab->stub_sec[i]->size = 0;
1929              }
1930    
1931    for (i = 0; i <= htab->num_overlays; i++)        /* Fill in all the stubs.  */
1932      {        process_stubs (info, TRUE);
1933        if (htab->stub_sec[i]->size != htab->stub_sec[i]->rawsize)        if (!htab->stub_err)
1934            elf_link_hash_traverse (&htab->elf, build_spuear_stubs, info);
1935    
1936          if (htab->stub_err)
1937          {          {
1938            (*_bfd_error_handler)  (_("stubs don't match calculated size"));            (*_bfd_error_handler) (_("overlay stub relocation overflow"));
1939            bfd_set_error (bfd_error_bad_value);            bfd_set_error (bfd_error_bad_value);
1940            return FALSE;            return FALSE;
1941          }          }
1942        htab->stub_sec[i]->rawsize = 0;  
1943          for (i = 0; i <= htab->num_overlays; i++)
1944            {
1945              if (htab->stub_sec[i]->size != htab->stub_sec[i]->rawsize)
1946                {
1947                  (*_bfd_error_handler)  (_("stubs don't match calculated size"));
1948                  bfd_set_error (bfd_error_bad_value);
1949                  return FALSE;
1950                }
1951              htab->stub_sec[i]->rawsize = 0;
1952            }
1953      }      }
1954    
1955      if (htab->ovtab == NULL || htab->ovtab->size == 0)
1956        return TRUE;
1957    
1958    htab->ovtab->contents = bfd_zalloc (htab->ovtab->owner, htab->ovtab->size);    htab->ovtab->contents = bfd_zalloc (htab->ovtab->owner, htab->ovtab->size);
1959    if (htab->ovtab->contents == NULL)    if (htab->ovtab->contents == NULL)
1960      return FALSE;      return FALSE;
1961    
   /* Write out _ovly_table.  */  
1962    p = htab->ovtab->contents;    p = htab->ovtab->contents;
1963    /* set low bit of .size to mark non-overlay area as present.  */    if (htab->params->ovly_flavour == ovly_soft_icache)
   p[7] = 1;  
   obfd = htab->ovtab->output_section->owner;  
   for (s = obfd->sections; s != NULL; s = s->next)  
1964      {      {
1965        unsigned int ovl_index = spu_elf_section_data (s)->u.o.ovl_index;        bfd_vma off;
1966    
1967          h = define_ovtab_symbol (htab, "__icache_tag_array");
1968          if (h == NULL)
1969            return FALSE;
1970          h->root.u.def.value = 0;
1971          h->size = 16 << htab->num_lines_log2;
1972          off = h->size;
1973    
1974          h = define_ovtab_symbol (htab, "__icache_tag_array_size");
1975          if (h == NULL)
1976            return FALSE;
1977          h->root.u.def.value = 16 << htab->num_lines_log2;
1978          h->root.u.def.section = bfd_abs_section_ptr;
1979    
1980          h = define_ovtab_symbol (htab, "__icache_rewrite_to");
1981          if (h == NULL)
1982            return FALSE;
1983          h->root.u.def.value = off;
1984          h->size = 16 << htab->num_lines_log2;
1985          off += h->size;
1986    
1987          h = define_ovtab_symbol (htab, "__icache_rewrite_to_size");
1988          if (h == NULL)
1989            return FALSE;
1990          h->root.u.def.value = 16 << htab->num_lines_log2;
1991          h->root.u.def.section = bfd_abs_section_ptr;
1992    
1993        if (ovl_index != 0)        h = define_ovtab_symbol (htab, "__icache_rewrite_from");
1994          if (h == NULL)
1995            return FALSE;
1996          h->root.u.def.value = off;
1997          h->size = 16 << (htab->fromelem_size_log2 + htab->num_lines_log2);
1998          off += h->size;
1999    
2000          h = define_ovtab_symbol (htab, "__icache_rewrite_from_size");
2001          if (h == NULL)
2002            return FALSE;
2003          h->root.u.def.value = 16 << (htab->fromelem_size_log2
2004                                       + htab->num_lines_log2);
2005          h->root.u.def.section = bfd_abs_section_ptr;
2006    
2007          h = define_ovtab_symbol (htab, "__icache_log2_fromelemsize");
2008          if (h == NULL)
2009            return FALSE;
2010          h->root.u.def.value = htab->fromelem_size_log2;
2011          h->root.u.def.section = bfd_abs_section_ptr;
2012    
2013          h = define_ovtab_symbol (htab, "__icache_base");
2014          if (h == NULL)
2015            return FALSE;
2016          h->root.u.def.value = htab->ovl_sec[0]->vma;
2017          h->root.u.def.section = bfd_abs_section_ptr;
2018          h->size = htab->num_buf << htab->line_size_log2;
2019    
2020          h = define_ovtab_symbol (htab, "__icache_linesize");
2021          if (h == NULL)
2022            return FALSE;
2023          h->root.u.def.value = 1 << htab->line_size_log2;
2024          h->root.u.def.section = bfd_abs_section_ptr;
2025    
2026          h = define_ovtab_symbol (htab, "__icache_log2_linesize");
2027          if (h == NULL)
2028            return FALSE;
2029          h->root.u.def.value = htab->line_size_log2;
2030          h->root.u.def.section = bfd_abs_section_ptr;
2031    
2032          h = define_ovtab_symbol (htab, "__icache_neg_log2_linesize");
2033          if (h == NULL)
2034            return FALSE;
2035          h->root.u.def.value = -htab->line_size_log2;
2036          h->root.u.def.section = bfd_abs_section_ptr;
2037    
2038          h = define_ovtab_symbol (htab, "__icache_cachesize");
2039          if (h == NULL)
2040            return FALSE;
2041          h->root.u.def.value = 1 << (htab->num_lines_log2 + htab->line_size_log2);
2042          h->root.u.def.section = bfd_abs_section_ptr;
2043    
2044          h = define_ovtab_symbol (htab, "__icache_log2_cachesize");
2045          if (h == NULL)
2046            return FALSE;
2047          h->root.u.def.value = htab->num_lines_log2 + htab->line_size_log2;
2048          h->root.u.def.section = bfd_abs_section_ptr;
2049    
2050          h = define_ovtab_symbol (htab, "__icache_neg_log2_cachesize");
2051          if (h == NULL)
2052            return FALSE;
2053          h->root.u.def.value = -(htab->num_lines_log2 + htab->line_size_log2);
2054          h->root.u.def.section = bfd_abs_section_ptr;
2055    
2056          if (htab->init != NULL && htab->init->size != 0)
2057          {          {
2058            unsigned long off = ovl_index * 16;            htab->init->contents = bfd_zalloc (htab->init->owner,
2059            unsigned int ovl_buf = spu_elf_section_data (s)->u.o.ovl_buf;                                               htab->init->size);
2060              if (htab->init->contents == NULL)
2061                return FALSE;
2062    
2063            bfd_put_32 (htab->ovtab->owner, s->vma, p + off);            h = define_ovtab_symbol (htab, "__icache_fileoff");
2064            bfd_put_32 (htab->ovtab->owner, (s->size + 15) & -16, p + off + 4);            if (h == NULL)
2065            /* file_off written later in spu_elf_modify_program_headers.  */              return FALSE;
2066            bfd_put_32 (htab->ovtab->owner, ovl_buf, p + off + 12);            h->root.u.def.value = 0;
2067              h->root.u.def.section = htab->init;
2068              h->size = 8;
2069          }          }
2070      }      }
2071      else
2072        {
2073          /* Write out _ovly_table.  */
2074          /* set low bit of .size to mark non-overlay area as present.  */
2075          p[7] = 1;
2076          obfd = htab->ovtab->output_section->owner;
2077          for (s = obfd->sections; s != NULL; s = s->next)
2078            {
2079              unsigned int ovl_index = spu_elf_section_data (s)->u.o.ovl_index;
2080    
2081    h = define_ovtab_symbol (htab, "_ovly_table");            if (ovl_index != 0)
2082    if (h == NULL)              {
2083      return FALSE;                unsigned long off = ovl_index * 16;
2084    h->root.u.def.value = 16;                unsigned int ovl_buf = spu_elf_section_data (s)->u.o.ovl_buf;
   h->size = htab->num_overlays * 16;  
2085    
2086    h = define_ovtab_symbol (htab, "_ovly_table_end");                bfd_put_32 (htab->ovtab->owner, s->vma, p + off);
2087    if (h == NULL)                bfd_put_32 (htab->ovtab->owner, (s->size + 15) & -16,
2088      return FALSE;                            p + off + 4);
2089    h->root.u.def.value = htab->num_overlays * 16 + 16;                /* file_off written later in spu_elf_modify_program_headers.  */
2090    h->size = 0;                bfd_put_32 (htab->ovtab->owner, ovl_buf, p + off + 12);
2091                }
2092            }
2093    
2094    h = define_ovtab_symbol (htab, "_ovly_buf_table");        h = define_ovtab_symbol (htab, "_ovly_table");
2095    if (h == NULL)        if (h == NULL)
2096      return FALSE;          return FALSE;
2097    h->root.u.def.value = htab->num_overlays * 16 + 16;        h->root.u.def.value = 16;
2098    h->size = htab->num_buf * 4;        h->size = htab->num_overlays * 16;
2099    
2100    h = define_ovtab_symbol (htab, "_ovly_buf_table_end");        h = define_ovtab_symbol (htab, "_ovly_table_end");
2101    if (h == NULL)        if (h == NULL)
2102      return FALSE;          return FALSE;
2103    h->root.u.def.value = htab->num_overlays * 16 + 16 + htab->num_buf * 4;        h->root.u.def.value = htab->num_overlays * 16 + 16;
2104    h->size = 0;        h->size = 0;
2105    
2106          h = define_ovtab_symbol (htab, "_ovly_buf_table");
2107          if (h == NULL)
2108            return FALSE;
2109          h->root.u.def.value = htab->num_overlays * 16 + 16;
2110          h->size = htab->num_buf * 4;
2111    
2112          h = define_ovtab_symbol (htab, "_ovly_buf_table_end");
2113          if (h == NULL)
2114            return FALSE;
2115          h->root.u.def.value = htab->num_overlays * 16 + 16 + htab->num_buf * 4;
2116          h->size = 0;
2117        }
2118    
2119    h = define_ovtab_symbol (htab, "_EAR_");    h = define_ovtab_symbol (htab, "_EAR_");
2120    if (h == NULL)    if (h == NULL)
# Line 1605  spu_elf_check_vma (struct bfd_link_info Line 2150  spu_elf_check_vma (struct bfd_link_info
2150                  || m->sections[i]->vma + m->sections[i]->size - 1 > hi))                  || m->sections[i]->vma + m->sections[i]->size - 1 > hi))
2151            return m->sections[i];            return m->sections[i];
2152    
   /* No need for overlays if it all fits.  */  
   htab->params->auto_overlay = 0;  
2153    return NULL;    return NULL;
2154  }  }
2155    
2156  /* OFFSET in SEC (presumably) is the beginning of a function prologue.  /* OFFSET in SEC (presumably) is the beginning of a function prologue.
2157     Search for stack adjusting insns, and return the sp delta.  */     Search for stack adjusting insns, and return the sp delta.
2158       If a store of lr is found save the instruction offset to *LR_STORE.
2159       If a stack adjusting instruction is found, save that offset to
2160       *SP_ADJUST.  */
2161    
2162  static int  static int
2163  find_function_stack_adjust (asection *sec, bfd_vma offset)  find_function_stack_adjust (asection *sec,
2164                                bfd_vma offset,
2165                                bfd_vma *lr_store,
2166                                bfd_vma *sp_adjust)
2167  {  {
2168    int reg[128];    int reg[128];
2169    
# Line 1629  find_function_stack_adjust (asection *se Line 2178  find_function_stack_adjust (asection *se
2178        if (!bfd_get_section_contents (sec->owner, sec, buf, offset, 4))        if (!bfd_get_section_contents (sec->owner, sec, buf, offset, 4))
2179          break;          break;
2180    
       if (buf[0] == 0x24 /* stqd */)  
         continue;  
   
2181        rt = buf[3] & 0x7f;        rt = buf[3] & 0x7f;
2182        ra = ((buf[2] & 0x3f) << 1) | (buf[3] >> 7);        ra = ((buf[2] & 0x3f) << 1) | (buf[3] >> 7);
2183    
2184          if (buf[0] == 0x24 /* stqd */)
2185            {
2186              if (rt == 0 /* lr */ && ra == 1 /* sp */)
2187                *lr_store = offset;
2188              continue;
2189            }
2190    
2191        /* Partly decoded immediate field.  */        /* Partly decoded immediate field.  */
2192        imm = (buf[1] << 9) | (buf[2] << 1) | (buf[3] >> 7);        imm = (buf[1] << 9) | (buf[2] << 1) | (buf[3] >> 7);
2193    
# Line 1647  find_function_stack_adjust (asection *se Line 2201  find_function_stack_adjust (asection *se
2201              {              {
2202                if (reg[rt] > 0)                if (reg[rt] > 0)
2203                  break;                  break;
2204                  *sp_adjust = offset;
2205                return reg[rt];                return reg[rt];
2206              }              }
2207          }          }
# Line 1659  find_function_stack_adjust (asection *se Line 2214  find_function_stack_adjust (asection *se
2214              {              {
2215                if (reg[rt] > 0)                if (reg[rt] > 0)
2216                  break;                  break;
2217                  *sp_adjust = offset;
2218                  return reg[rt];
2219                }
2220            }
2221          else if (buf[0] == 0x08 && (buf[1] & 0xe0) == 0 /* sf */)
2222            {
2223              int rb = ((buf[1] & 0x1f) << 2) | ((buf[2] & 0xc0) >> 6);
2224    
2225              reg[rt] = reg[rb] - reg[ra];
2226              if (rt == 1)
2227                {
2228                  if (reg[rt] > 0)
2229                    break;
2230                  *sp_adjust = offset;
2231                return reg[rt];                return reg[rt];
2232              }              }
2233          }          }
# Line 1859  maybe_insert_function (asection *sec, Line 2428  maybe_insert_function (asection *sec,
2428      sinfo->fun[i].u.sym = sym_h;      sinfo->fun[i].u.sym = sym_h;
2429    sinfo->fun[i].lo = off;    sinfo->fun[i].lo = off;
2430    sinfo->fun[i].hi = off + size;    sinfo->fun[i].hi = off + size;
2431    sinfo->fun[i].stack = -find_function_stack_adjust (sec, off);    sinfo->fun[i].lr_store = -1;
2432      sinfo->fun[i].sp_adjust = -1;
2433      sinfo->fun[i].stack = -find_function_stack_adjust (sec, off,
2434                                                         &sinfo->fun[i].lr_store,
2435                                                         &sinfo->fun[i].sp_adjust);
2436    sinfo->num_fun += 1;    sinfo->num_fun += 1;
2437    return &sinfo->fun[i];    return &sinfo->fun[i];
2438  }  }
# Line 2002  find_function (asection *sec, bfd_vma of Line 2575  find_function (asection *sec, bfd_vma of
2575      }      }
2576    info->callbacks->einfo (_("%A:0x%v not found in function table\n"),    info->callbacks->einfo (_("%A:0x%v not found in function table\n"),
2577                            sec, offset);                            sec, offset);
2578      bfd_set_error (bfd_error_bad_value);
2579    return NULL;    return NULL;
2580  }  }
2581    
# Line 2025  insert_callee (struct function_info *cal Line 2599  insert_callee (struct function_info *cal
2599              p->fun->start = NULL;              p->fun->start = NULL;
2600              p->fun->is_func = TRUE;              p->fun->is_func = TRUE;
2601            }            }
2602          p->count += 1;          p->count += callee->count;
2603          /* Reorder list so most recent call is first.  */          /* Reorder list so most recent call is first.  */
2604          *pp = p->next;          *pp = p->next;
2605          p->next = caller->call_list;          p->next = caller->call_list;
# Line 2033  insert_callee (struct function_info *cal Line 2607  insert_callee (struct function_info *cal
2607          return FALSE;          return FALSE;
2608        }        }
2609    callee->next = caller->call_list;    callee->next = caller->call_list;
   callee->count += 1;  
2610    caller->call_list = callee;    caller->call_list = callee;
2611    return TRUE;    return TRUE;
2612  }  }
# Line 2079  mark_functions_via_relocs (asection *sec Line 2652  mark_functions_via_relocs (asection *sec
2652    Elf_Internal_Rela *internal_relocs, *irelaend, *irela;    Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
2653    Elf_Internal_Shdr *symtab_hdr;    Elf_Internal_Shdr *symtab_hdr;
2654    void *psyms;    void *psyms;
2655      unsigned int priority = 0;
2656    static bfd_boolean warned;    static bfd_boolean warned;
2657    
2658    if (!interesting_section (sec)    if (!interesting_section (sec)
# Line 2135  mark_functions_via_relocs (asection *sec Line 2709  mark_functions_via_relocs (asection *sec
2709            if (is_branch (insn))            if (is_branch (insn))
2710              {              {
2711                is_call = (insn[0] & 0xfd) == 0x31;                is_call = (insn[0] & 0xfd) == 0x31;
2712                  priority = insn[1] & 0x0f;
2713                  priority <<= 8;
2714                  priority |= insn[2];
2715                  priority <<= 8;
2716                  priority |= insn[3];
2717                  priority >>= 7;
2718                if ((sym_sec->flags & (SEC_ALLOC | SEC_LOAD | SEC_CODE))                if ((sym_sec->flags & (SEC_ALLOC | SEC_LOAD | SEC_CODE))
2719                    != (SEC_ALLOC | SEC_LOAD | SEC_CODE))                    != (SEC_ALLOC | SEC_LOAD | SEC_CODE))
2720                  {                  {
# Line 2215  mark_functions_via_relocs (asection *sec Line 2795  mark_functions_via_relocs (asection *sec
2795          return FALSE;          return FALSE;
2796        callee->is_tail = !is_call;        callee->is_tail = !is_call;
2797        callee->is_pasted = FALSE;        callee->is_pasted = FALSE;
2798        callee->count = 0;        callee->broken_cycle = FALSE;
2799          callee->priority = priority;
2800          callee->count = 1;
2801        if (callee->fun->last_caller != sec)        if (callee->fun->last_caller != sec)
2802          {          {
2803            callee->fun->last_caller = sec;            callee->fun->last_caller = sec;
# Line 2238  mark_functions_via_relocs (asection *sec Line 2820  mark_functions_via_relocs (asection *sec
2820                callee->fun->is_func = TRUE;                callee->fun->is_func = TRUE;
2821              }              }
2822            else if (callee->fun->start == NULL)            else if (callee->fun->start == NULL)
2823              callee->fun->start = caller;              {
2824                  struct function_info *caller_start = caller;
2825                  while (caller_start->start)
2826                    caller_start = caller_start->start;
2827    
2828                  if (caller_start != callee->fun)
2829                    callee->fun->start = caller_start;
2830                }
2831            else            else
2832              {              {
2833                struct function_info *callee_start;                struct function_info *callee_start;
# Line 2265  mark_functions_via_relocs (asection *sec Line 2854  mark_functions_via_relocs (asection *sec
2854     These sections are pasted together to form a single function.  */     These sections are pasted together to form a single function.  */
2855    
2856  static bfd_boolean  static bfd_boolean
2857  pasted_function (asection *sec, struct bfd_link_info *info)  pasted_function (asection *sec)
2858  {  {
2859    struct bfd_link_order *l;    struct bfd_link_order *l;
2860    struct _spu_elf_section_data *sec_data;    struct _spu_elf_section_data *sec_data;
# Line 2300  pasted_function (asection *sec, struct b Line 2889  pasted_function (asection *sec, struct b
2889                callee->fun = fun;                callee->fun = fun;
2890                callee->is_tail = TRUE;                callee->is_tail = TRUE;
2891                callee->is_pasted = TRUE;                callee->is_pasted = TRUE;
2892                callee->count = 0;                callee->broken_cycle = FALSE;
2893                  callee->priority = 0;
2894                  callee->count = 1;
2895                if (!insert_callee (fun_start, callee))                if (!insert_callee (fun_start, callee))
2896                  free (callee);                  free (callee);
2897                return TRUE;                return TRUE;
# Line 2314  pasted_function (asection *sec, struct b Line 2905  pasted_function (asection *sec, struct b
2905          fun_start = &sinfo->fun[sinfo->num_fun - 1];          fun_start = &sinfo->fun[sinfo->num_fun - 1];
2906      }      }
2907    
2908    info->callbacks->einfo (_("%A link_order not found\n"), sec);    /* Don't return an error if we did not find a function preceding this
2909    return FALSE;       section.  The section may have incorrect flags.  */
2910      return TRUE;
2911  }  }
2912    
2913  /* Map address ranges in code sections to functions.  */  /* Map address ranges in code sections to functions.  */
# Line 2339  discover_functions (struct bfd_link_info Line 2931  discover_functions (struct bfd_link_info
2931    sec_arr = bfd_zmalloc (bfd_idx * sizeof (*sec_arr));    sec_arr = bfd_zmalloc (bfd_idx * sizeof (*sec_arr));
2932    if (sec_arr == NULL)    if (sec_arr == NULL)
2933      return FALSE;      return FALSE;
   
2934        
2935    for (ibfd = info->input_bfds, bfd_idx = 0;    for (ibfd = info->input_bfds, bfd_idx = 0;
2936         ibfd != NULL;         ibfd != NULL;
# Line 2394  discover_functions (struct bfd_link_info Line 2985  discover_functions (struct bfd_link_info
2985        sec_arr[bfd_idx] = psecs;        sec_arr[bfd_idx] = psecs;
2986        for (psy = psyms, p = psecs, sy = syms; sy < syms + symcount; ++p, ++sy)        for (psy = psyms, p = psecs, sy = syms; sy < syms + symcount; ++p, ++sy)
2987          if (ELF_ST_TYPE (sy->st_info) == STT_NOTYPE          if (ELF_ST_TYPE (sy->st_info) == STT_NOTYPE
2988              || ELF_ST_TYPE (sy->st_info) == STT_FUNC              || ELF_ST_TYPE (sy->st_info) == STT_FUNC)
             || ELF_ST_TYPE (sy->st_info) == STT_SECTION)  
2989            {            {
2990              asection *s;              asection *s;
2991    
# Line 2525  discover_functions (struct bfd_link_info Line 3115  discover_functions (struct bfd_link_info
3115    
3116                  sec_data = spu_elf_section_data (sec);                  sec_data = spu_elf_section_data (sec);
3117                  sinfo = sec_data->u.i.stack_info;                  sinfo = sec_data->u.i.stack_info;
3118                  if (sinfo != NULL)                  if (sinfo != NULL && sinfo->num_fun != 0)
3119                    {                    {
3120                      int fun_idx;                      int fun_idx;
3121                      bfd_vma hi = sec->size;                      bfd_vma hi = sec->size;
# Line 2535  discover_functions (struct bfd_link_info Line 3125  discover_functions (struct bfd_link_info
3125                          sinfo->fun[fun_idx].hi = hi;                          sinfo->fun[fun_idx].hi = hi;
3126                          hi = sinfo->fun[fun_idx].lo;                          hi = sinfo->fun[fun_idx].lo;
3127                        }                        }
3128    
3129                        sinfo->fun[0].lo = 0;
3130                    }                    }
3131                  /* No symbols in this section.  Must be .init or .fini                  /* No symbols in this section.  Must be .init or .fini
3132                     or something similar.  */                     or something similar.  */
3133                  else if (!pasted_function (sec, info))                  else if (!pasted_function (sec))
3134                    return FALSE;                    return FALSE;
3135                }                }
3136          }          }
# Line 2667  remove_cycles (struct function_info *fun Line 3259  remove_cycles (struct function_info *fun
3259    callp = &fun->call_list;    callp = &fun->call_list;
3260    while ((call = *callp) != NULL)    while ((call = *callp) != NULL)
3261      {      {
3262          call->max_depth = depth + !call->is_pasted;
3263        if (!call->fun->visit2)        if (!call->fun->visit2)
3264          {          {
           call->max_depth = depth + !call->is_pasted;  
3265            if (!remove_cycles (call->fun, info, &call->max_depth))            if (!remove_cycles (call->fun, info, &call->max_depth))
3266              return FALSE;              return FALSE;
3267            if (max_depth < call->max_depth)            if (max_depth < call->max_depth)
# Line 2677  remove_cycles (struct function_info *fun Line 3269  remove_cycles (struct function_info *fun
3269          }          }
3270        else if (call->fun->marking)        else if (call->fun->marking)
3271          {          {
3272            if (!spu_hash_table (info)->params->auto_overlay)            struct spu_link_hash_table *htab = spu_hash_table (info);
3273    
3274              if (!htab->params->auto_overlay
3275                  && htab->params->stack_analysis)
3276              {              {
3277                const char *f1 = func_name (fun);                const char *f1 = func_name (fun);
3278                const char *f2 = func_name (call->fun);                const char *f2 = func_name (call->fun);
# Line 2686  remove_cycles (struct function_info *fun Line 3281  remove_cycles (struct function_info *fun
3281                                         "from %s to %s\n"),                                         "from %s to %s\n"),
3282                                       f1, f2);                                       f1, f2);
3283              }              }
3284            *callp = call->next;  
3285            free (call);            call->broken_cycle = TRUE;
           continue;  
3286          }          }
3287        callp = &call->next;        callp = &call->next;
3288      }      }
# Line 2754  build_call_tree (struct bfd_link_info *i Line 3348  build_call_tree (struct bfd_link_info *i
3348    return for_each_node (mark_detached_root, info, &depth, FALSE);    return for_each_node (mark_detached_root, info, &depth, FALSE);
3349  }  }
3350    
3351  /* qsort predicate to sort calls by max_depth then count.  */  /* qsort predicate to sort calls by priority, max_depth then count.  */
3352    
3353  static int  static int
3354  sort_calls (const void *a, const void *b)  sort_calls (const void *a, const void *b)
# Line 2763  sort_calls (const void *a, const void *b Line 3357  sort_calls (const void *a, const void *b
3357    struct call_info *const *c2 = b;    struct call_info *const *c2 = b;
3358    int delta;    int delta;
3359    
3360      delta = (*c2)->priority - (*c1)->priority;
3361      if (delta != 0)
3362        return delta;
3363    
3364    delta = (*c2)->max_depth - (*c1)->max_depth;    delta = (*c2)->max_depth - (*c1)->max_depth;
3365    if (delta != 0)    if (delta != 0)
3366      return delta;      return delta;
# Line 2799  mark_overlay_section (struct function_in Line 3397  mark_overlay_section (struct function_in
3397    struct call_info *call;    struct call_info *call;
3398    unsigned int count;    unsigned int count;
3399    struct _mos_param *mos_param = param;    struct _mos_param *mos_param = param;
3400      struct spu_link_hash_table *htab = spu_hash_table (info);
3401    
3402    if (fun->visit4)    if (fun->visit4)
3403      return TRUE;      return TRUE;
3404    
3405    fun->visit4 = TRUE;    fun->visit4 = TRUE;
3406    if (!fun->sec->linker_mark)    if (!fun->sec->linker_mark
3407          && (htab->params->ovly_flavour != ovly_soft_icache
3408              || htab->params->non_ia_text
3409              || strncmp (fun->sec->name, ".text.ia.", 9) == 0
3410              || strcmp (fun->sec->name, ".init") == 0
3411              || strcmp (fun->sec->name, ".fini") == 0))
3412      {      {
3413        unsigned int size;        unsigned int size;
3414    
# Line 2816  mark_overlay_section (struct function_in Line 3420  mark_overlay_section (struct function_in
3420           this flag to differentiate the two overlay section types.  */           this flag to differentiate the two overlay section types.  */
3421        fun->sec->flags |= SEC_CODE;        fun->sec->flags |= SEC_CODE;
3422    
3423        if (spu_hash_table (info)->params->auto_overlay & OVERLAY_RODATA)        size = fun->sec->size;
3424          if (htab->params->auto_overlay & OVERLAY_RODATA)
3425          {          {
3426            char *name = NULL;            char *name = NULL;
3427    
# Line 2867  mark_overlay_section (struct function_in Line 3472  mark_overlay_section (struct function_in
3472                fun->rodata = rodata;                fun->rodata = rodata;
3473                if (fun->rodata)                if (fun->rodata)
3474                  {                  {
3475                    fun->rodata->linker_mark = 1;                    size += fun->rodata->size;
3476                    fun->rodata->gc_mark = 1;                    if (htab->params->line_size != 0
3477                    fun->rodata->flags &= ~SEC_CODE;                        && size > htab->params->line_size)
3478                        {
3479                          size -= fun->rodata->size;
3480                          fun->rodata = NULL;
3481                        }
3482                      else
3483                        {
3484                          fun->rodata->linker_mark = 1;
3485                          fun->rodata->gc_mark = 1;
3486                          fun->rodata->flags &= ~SEC_CODE;
3487                        }
3488                  }                  }
3489                free (name);                free (name);
3490              }              }
3491          }          }
       size = fun->sec->size;  
       if (fun->rodata)  
         size += fun->rodata->size;  
3492        if (mos_param->max_overlay_size < size)        if (mos_param->max_overlay_size < size)
3493          mos_param->max_overlay_size = size;          mos_param->max_overlay_size = size;
3494      }      }
# Line 2913  mark_overlay_section (struct function_in Line 3525  mark_overlay_section (struct function_in
3525            BFD_ASSERT (!fun->sec->segment_mark);            BFD_ASSERT (!fun->sec->segment_mark);
3526            fun->sec->segment_mark = 1;            fun->sec->segment_mark = 1;
3527          }          }
3528        if (!mark_overlay_section (call->fun, info, param))        if (!call->broken_cycle
3529              && !mark_overlay_section (call->fun, info, param))
3530          return FALSE;          return FALSE;
3531      }      }
3532    
3533    /* Don't put entry code into an overlay.  The overlay manager needs    /* Don't put entry code into an overlay.  The overlay manager needs
3534       a stack!  */       a stack!  Also, don't mark .ovl.init as an overlay.  */
3535    if (fun->lo + fun->sec->output_offset + fun->sec->output_section->vma    if (fun->lo + fun->sec->output_offset + fun->sec->output_section->vma
3536        == info->output_bfd->start_address)        == info->output_bfd->start_address
3537          || strncmp (fun->sec->output_section->name, ".ovl.init", 9) == 0)
3538      {      {
3539        fun->sec->linker_mark = 0;        fun->sec->linker_mark = 0;
3540        if (fun->rodata != NULL)        if (fun->rodata != NULL)
# Line 2972  unmark_overlay_section (struct function_ Line 3586  unmark_overlay_section (struct function_
3586      }      }
3587    
3588    for (call = fun->call_list; call != NULL; call = call->next)    for (call = fun->call_list; call != NULL; call = call->next)
3589      if (!unmark_overlay_section (call->fun, info, param))      if (!call->broken_cycle
3590            && !unmark_overlay_section (call->fun, info, param))
3591        return FALSE;        return FALSE;
3592    
3593    if (RECURSE_UNMARK)    if (RECURSE_UNMARK)
# Line 3008  collect_lib_sections (struct function_in Line 3623  collect_lib_sections (struct function_in
3623    size = fun->sec->size;    size = fun->sec->size;
3624    if (fun->rodata)    if (fun->rodata)
3625      size += fun->rodata->size;      size += fun->rodata->size;
3626    
3627    if (size <= lib_param->lib_size)    if (size <= lib_param->lib_size)
3628      {      {
3629        *lib_param->lib_sections++ = fun->sec;        *lib_param->lib_sections++ = fun->sec;
# Line 3022  collect_lib_sections (struct function_in Line 3638  collect_lib_sections (struct function_in
3638      }      }
3639    
3640    for (call = fun->call_list; call != NULL; call = call->next)    for (call = fun->call_list; call != NULL; call = call->next)
3641      collect_lib_sections (call->fun, info, param);      if (!call->broken_cycle)
3642          collect_lib_sections (call->fun, info, param);
3643    
3644    return TRUE;    return TRUE;
3645  }  }
# Line 3136  auto_ovl_lib_functions (struct bfd_link_ Line 3753  auto_ovl_lib_functions (struct bfd_link_
3753                      if (p->fun == call->fun)                      if (p->fun == call->fun)
3754                        break;                        break;
3755                    if (!p)                    if (!p)
3756                      stub_size += ovl_stub_size (htab->params->ovly_flavour);                      stub_size += ovl_stub_size (htab->params);
3757                  }                  }
3758          }          }
3759        if (tmp + stub_size < lib_size)        if (tmp + stub_size < lib_size)
# Line 3154  auto_ovl_lib_functions (struct bfd_link_ Line 3771  auto_ovl_lib_functions (struct bfd_link_
3771            while ((p = *pp) != NULL)            while ((p = *pp) != NULL)
3772              if (!p->fun->sec->linker_mark)              if (!p->fun->sec->linker_mark)
3773                {                {
3774                  lib_size += ovl_stub_size (htab->params->ovly_flavour);                  lib_size += ovl_stub_size (htab->params);
3775                  *pp = p->next;                  *pp = p->next;
3776                  free (p);                  free (p);
3777                }                }
# Line 3216  collect_overlays (struct function_info * Line 3833  collect_overlays (struct function_info *
3833    
3834    fun->visit7 = TRUE;    fun->visit7 = TRUE;
3835    for (call = fun->call_list; call != NULL; call = call->next)    for (call = fun->call_list; call != NULL; call = call->next)
3836      if (!call->is_pasted)      if (!call->is_pasted && !call->broken_cycle)
3837        {        {
3838          if (!collect_overlays (call->fun, info, ovly_sections))          if (!collect_overlays (call->fun, info, ovly_sections))
3839            return FALSE;            return FALSE;
# Line 3262  collect_overlays (struct function_info * Line 3879  collect_overlays (struct function_info *
3879      }      }
3880    
3881    for (call = fun->call_list; call != NULL; call = call->next)    for (call = fun->call_list; call != NULL; call = call->next)
3882      if (!collect_overlays (call->fun, info, ovly_sections))      if (!call->broken_cycle
3883            && !collect_overlays (call->fun, info, ovly_sections))
3884        return FALSE;        return FALSE;
3885    
3886    if (added_fun)    if (added_fun)
# Line 3313  sum_stack (struct function_info *fun, Line 3931  sum_stack (struct function_info *fun,
3931    max = NULL;    max = NULL;
3932    for (call = fun->call_list; call; call = call->next)    for (call = fun->call_list; call; call = call->next)
3933      {      {
3934          if (call->broken_cycle)
3935            continue;
3936        if (!call->is_pasted)        if (!call->is_pasted)
3937          has_call = TRUE;          has_call = TRUE;
3938        if (!sum_stack (call->fun, info, sum_stack_param))        if (!sum_stack (call->fun, info, sum_stack_param))
# Line 3345  sum_stack (struct function_info *fun, Line 3965  sum_stack (struct function_info *fun,
3965      return TRUE;      return TRUE;
3966    
3967    f1 = func_name (fun);    f1 = func_name (fun);
3968    if (!fun->non_root)    if (htab->params->stack_analysis)
3969      info->callbacks->info (_("  %s: 0x%v\n"), f1, (bfd_vma) cum_stack);      {
3970    info->callbacks->minfo (_("%s: 0x%v 0x%v\n"),        if (!fun->non_root)
3971                            f1, (bfd_vma) stack, (bfd_vma) cum_stack);          info->callbacks->info (_("  %s: 0x%v\n"), f1, (bfd_vma) cum_stack);
3972          info->callbacks->minfo (_("%s: 0x%v 0x%v\n"),
3973    if (has_call)                                f1, (bfd_vma) stack, (bfd_vma) cum_stack);
3974      {  
3975        info->callbacks->minfo (_("  calls:\n"));        if (has_call)
3976        for (call = fun->call_list; call; call = call->next)          {
3977          if (!call->is_pasted)            info->callbacks->minfo (_("  calls:\n"));
3978            {            for (call = fun->call_list; call; call = call->next)
3979              const char *f2 = func_name (call->fun);              if (!call->is_pasted && !call->broken_cycle)
3980              const char *ann1 = call->fun == max ? "*" : " ";                {
3981              const char *ann2 = call->is_tail ? "t" : " ";                  const char *f2 = func_name (call->fun);
3982                    const char *ann1 = call->fun == max ? "*" : " ";
3983                    const char *ann2 = call->is_tail ? "t" : " ";
3984    
3985              info->callbacks->minfo (_("   %s%s %s\n"), ann1, ann2, f2);                  info->callbacks->minfo (_("   %s%s %s\n"), ann1, ann2, f2);
3986            }                }
3987            }
3988      }      }
3989    
3990    if (sum_stack_param->emit_stack_syms)    if (sum_stack_param->emit_stack_syms)
# Line 3430  sort_bfds (const void *a, const void *b) Line 4053  sort_bfds (const void *a, const void *b)
4053    return strcmp ((*abfd1)->filename, (*abfd2)->filename);    return strcmp ((*abfd1)->filename, (*abfd2)->filename);
4054  }  }
4055    
4056  /* Handle --auto-overlay.  */  static unsigned int
4057    print_one_overlay_section (FILE *script,
4058                               unsigned int base,
4059                               unsigned int count,
4060                               unsigned int ovlynum,
4061                               unsigned int *ovly_map,
4062                               asection **ovly_sections,
4063                               struct bfd_link_info *info)
4064    {
4065      unsigned int j;
4066              
4067      for (j = base; j < count && ovly_map[j] == ovlynum; j++)
4068        {
4069          asection *sec = ovly_sections[2 * j];
4070    
4071  static void spu_elf_auto_overlay (struct bfd_link_info *)        if (fprintf (script, "   %s%c%s (%s)\n",
4072       ATTRIBUTE_NORETURN;                     (sec->owner->my_archive != NULL
4073                        ? sec->owner->my_archive->filename : ""),
4074                       info->path_separator,
4075                       sec->owner->filename,
4076                       sec->name) <= 0)
4077            return -1;
4078          if (sec->segment_mark)
4079            {
4080              struct call_info *call = find_pasted_call (sec);
4081              while (call != NULL)
4082                {
4083                  struct function_info *call_fun = call->fun;
4084                  sec = call_fun->sec;
4085                  if (fprintf (script, "   %s%c%s (%s)\n",
4086                               (sec->owner->my_archive != NULL
4087                                ? sec->owner->my_archive->filename : ""),
4088                               info->path_separator,
4089                               sec->owner->filename,
4090                               sec->name) <= 0)
4091                    return -1;
4092                  for (call = call_fun->call_list; call; call = call->next)
4093                    if (call->is_pasted)
4094                      break;
4095                }
4096            }
4097        }
4098    
4099      for (j = base; j < count && ovly_map[j] == ovlynum; j++)
4100        {
4101          asection *sec = ovly_sections[2 * j + 1];
4102          if (sec != NULL
4103              && fprintf (script, "   %s%c%s (%s)\n",
4104                          (sec->owner->my_archive != NULL
4105                           ? sec->owner->my_archive->filename : ""),
4106                          info->path_separator,
4107                          sec->owner->filename,
4108                          sec->name) <= 0)
4109            return -1;
4110    
4111          sec = ovly_sections[2 * j];
4112          if (sec->segment_mark)
4113            {
4114              struct call_info *call = find_pasted_call (sec);
4115              while (call != NULL)
4116                {
4117                  struct function_info *call_fun = call->fun;
4118                  sec = call_fun->rodata;
4119                  if (sec != NULL
4120                      && fprintf (script, "   %s%c%s (%s)\n",
4121                                  (sec->owner->my_archive != NULL
4122                                   ? sec->owner->my_archive->filename : ""),
4123                                  info->path_separator,
4124                                  sec->owner->filename,
4125                                  sec->name) <= 0)
4126                    return -1;
4127                  for (call = call_fun->call_list; call; call = call->next)
4128                    if (call->is_pasted)
4129                      break;
4130                }
4131            }
4132        }
4133    
4134      return j;
4135    }
4136    
4137    /* Handle --auto-overlay.  */
4138    
4139  static void  static void
4140  spu_elf_auto_overlay (struct bfd_link_info *info)  spu_elf_auto_overlay (struct bfd_link_info *info)
# Line 3449  spu_elf_auto_overlay (struct bfd_link_in Line 4150  spu_elf_auto_overlay (struct bfd_link_in
4150    unsigned int *ovly_map;    unsigned int *ovly_map;
4151    FILE *script;    FILE *script;
4152    unsigned int total_overlay_size, overlay_size;    unsigned int total_overlay_size, overlay_size;
4153      const char *ovly_mgr_entry;
4154    struct elf_link_hash_entry *h;    struct elf_link_hash_entry *h;
4155    struct _mos_param mos_param;    struct _mos_param mos_param;
4156    struct _uos_param uos_param;    struct _uos_param uos_param;
# Line 3475  spu_elf_auto_overlay (struct bfd_link_in Line 4177  spu_elf_auto_overlay (struct bfd_link_in
4177    if (!build_call_tree (info))    if (!build_call_tree (info))
4178      goto err_exit;      goto err_exit;
4179    
4180      htab = spu_hash_table (info);
4181      if (htab->reserved == 0)
4182        {
4183          struct _sum_stack_param sum_stack_param;
4184    
4185          sum_stack_param.emit_stack_syms = 0;
4186          sum_stack_param.overall_stack = 0;
4187          if (!for_each_node (sum_stack, info, &sum_stack_param, TRUE))
4188            goto err_exit;
4189          htab->reserved = sum_stack_param.overall_stack + htab->extra_stack_space;
4190        }
4191    
4192      /* No need for overlays if everything already fits.  */
4193      if (fixed_size + htab->reserved <= htab->local_store
4194          && htab->params->ovly_flavour != ovly_soft_icache)
4195        {
4196          htab->params->auto_overlay = 0;
4197          return;
4198        }
4199    
4200    uos_param.exclude_input_section = 0;    uos_param.exclude_input_section = 0;
4201    uos_param.exclude_output_section    uos_param.exclude_output_section
4202      = bfd_get_section_by_name (info->output_bfd, ".interrupt");      = bfd_get_section_by_name (info->output_bfd, ".interrupt");
4203    
4204    htab = spu_hash_table (info);    ovly_mgr_entry = "__ovly_load";
4205    h = elf_link_hash_lookup (&htab->elf, "__ovly_load",    if (htab->params->ovly_flavour == ovly_soft_icache)
4206        ovly_mgr_entry = "__icache_br_handler";
4207      h = elf_link_hash_lookup (&htab->elf, ovly_mgr_entry,
4208                              FALSE, FALSE, FALSE);                              FALSE, FALSE, FALSE);
4209    if (h != NULL    if (h != NULL
4210        && (h->root.type == bfd_link_hash_defined        && (h->root.type == bfd_link_hash_defined
# Line 3539  spu_elf_auto_overlay (struct bfd_link_in Line 4263  spu_elf_auto_overlay (struct bfd_link_in
4263              fixed_size -= sec->size;              fixed_size -= sec->size;
4264              total_overlay_size += sec->size;              total_overlay_size += sec->size;
4265            }            }
4266            else if ((sec->flags & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD)
4267                     && sec->output_section->owner == info->output_bfd
4268                     && strncmp (sec->output_section->name, ".ovl.init", 9) == 0)
4269              fixed_size -= sec->size;
4270        if (count != old_count)        if (count != old_count)
4271          bfd_arr[bfd_count++] = ibfd;          bfd_arr[bfd_count++] = ibfd;
4272      }      }
# Line 3575  spu_elf_auto_overlay (struct bfd_link_in Line 4303  spu_elf_auto_overlay (struct bfd_link_in
4303      }      }
4304    free (bfd_arr);    free (bfd_arr);
4305    
   if (htab->reserved == 0)  
     {  
       struct _sum_stack_param sum_stack_param;  
   
       sum_stack_param.emit_stack_syms = 0;  
       sum_stack_param.overall_stack = 0;  
       if (!for_each_node (sum_stack, info, &sum_stack_param, TRUE))  
         goto err_exit;  
       htab->reserved = sum_stack_param.overall_stack + htab->extra_stack_space;  
     }  
4306    fixed_size += htab->reserved;    fixed_size += htab->reserved;
4307    fixed_size += htab->non_ovly_stub * ovl_stub_size (htab->params->ovly_flavour);    fixed_size += htab->non_ovly_stub * ovl_stub_size (htab->params);
4308    if (fixed_size + mos_param.max_overlay_size <= htab->local_store)    if (fixed_size + mos_param.max_overlay_size <= htab->local_store)
4309      {      {
4310        /* Guess number of overlays.  Assuming overlay buffer is on        if (htab->params->ovly_flavour == ovly_soft_icache)
4311           average only half full should be conservative.  */          {
4312        ovlynum = total_overlay_size * 2 / (htab->local_store - fixed_size);            /* Stubs in the non-icache area are bigger.  */
4313        /* Space for _ovly_table[], _ovly_buf_table[] and toe.  */            fixed_size += htab->non_ovly_stub * 16;
4314        fixed_size += ovlynum * 16 + 16 + 4 + 16;            /* Space for icache manager tables.
4315                 a) Tag array, one quadword per cache line.
4316                 - word 0: ia address of present line, init to zero.  */
4317              fixed_size += 16 << htab->num_lines_log2;
4318              /* b) Rewrite "to" list, one quadword per cache line.  */
4319              fixed_size += 16 << htab->num_lines_log2;
4320              /* c) Rewrite "from" list, one byte per outgoing branch (rounded up
4321                    to a power-of-two number of full quadwords) per cache line.  */
4322              fixed_size += 16 << (htab->fromelem_size_log2
4323                                   + htab->num_lines_log2);
4324              /* d) Pointer to __ea backing store (toe), 1 quadword.  */
4325              fixed_size += 16;
4326            }
4327          else
4328            {
4329              /* Guess number of overlays.  Assuming overlay buffer is on
4330                 average only half full should be conservative.  */
4331              ovlynum = (total_overlay_size * 2 * htab->params->num_lines
4332                         / (htab->local_store - fixed_size));
4333              /* Space for _ovly_table[], _ovly_buf_table[] and toe.  */
4334              fixed_size += ovlynum * 16 + 16 + 4 + 16;
4335            }
4336      }      }
4337    
4338    if (fixed_size + mos_param.max_overlay_size > htab->local_store)    if (fixed_size + mos_param.max_overlay_size > htab->local_store)
# Line 3631  spu_elf_auto_overlay (struct bfd_link_in Line 4370  spu_elf_auto_overlay (struct bfd_link_in
4370      goto err_exit;      goto err_exit;
4371    
4372    memset (&dummy_caller, 0, sizeof (dummy_caller));    memset (&dummy_caller, 0, sizeof (dummy_caller));
4373    overlay_size = (htab->local_store - fixed_size) / htab->params->num_regions;    overlay_size = (htab->local_store - fixed_size) / htab->params->num_lines;
4374      if (htab->params->line_size != 0)
4375        overlay_size = htab->params->line_size;
4376    base = 0;    base = 0;
4377    ovlynum = 0;    ovlynum = 0;
4378    while (base < count)    while (base < count)
4379      {      {
4380        unsigned int size = 0;        unsigned int size = 0, rosize = 0, roalign = 0;
4381    
4382        for (i = base; i < count; i++)        for (i = base; i < count; i++)
4383          {          {
4384            asection *sec;            asection *sec, *rosec;
4385            unsigned int tmp;            unsigned int tmp, rotmp;
4386            unsigned int num_stubs;            unsigned int num_stubs;
4387            struct call_info *call, *pasty;            struct call_info *call, *pasty;
4388            struct _spu_elf_section_data *sec_data;            struct _spu_elf_section_data *sec_data;
# Line 3651  spu_elf_auto_overlay (struct bfd_link_in Line 4392  spu_elf_auto_overlay (struct bfd_link_in
4392            /* See whether we can add this section to the current            /* See whether we can add this section to the current
4393               overlay without overflowing our overlay buffer.  */               overlay without overflowing our overlay buffer.  */
4394            sec = ovly_sections[2 * i];            sec = ovly_sections[2 * i];
4395            tmp = size + sec->size;            tmp = align_power (size, sec->alignment_power) + sec->size;
4396            if (ovly_sections[2 * i + 1])            rotmp = rosize;
4397              tmp += ovly_sections[2 * i + 1]->size;            rosec = ovly_sections[2 * i + 1];
4398            if (tmp > overlay_size)            if (rosec != NULL)
4399                {
4400                  rotmp = align_power (rotmp, rosec->alignment_power) + rosec->size;
4401                  if (roalign < rosec->alignment_power)
4402                    roalign = rosec->alignment_power;
4403                }
4404              if (align_power (tmp, roalign) + rotmp > overlay_size)
4405              break;              break;
4406            if (sec->segment_mark)            if (sec->segment_mark)
4407              {              {
# Line 3664  spu_elf_auto_overlay (struct bfd_link_in Line 4411  spu_elf_auto_overlay (struct bfd_link_in
4411                while (pasty != NULL)                while (pasty != NULL)
4412                  {                  {
4413                    struct function_info *call_fun = pasty->fun;                    struct function_info *call_fun = pasty->fun;
4414                    tmp += call_fun->sec->size;                    tmp = (align_power (tmp, call_fun->sec->alignment_power)
4415                             + call_fun->sec->size);
4416                    if (call_fun->rodata)                    if (call_fun->rodata)
4417                      tmp += call_fun->rodata->size;                      {
4418                          rotmp = (align_power (rotmp,
4419                                                call_fun->rodata->alignment_power)
4420                                   + call_fun->rodata->size);
4421                          if (roalign < rosec->alignment_power)
4422                            roalign = rosec->alignment_power;
4423                        }
4424                    for (pasty = call_fun->call_list; pasty; pasty = pasty->next)                    for (pasty = call_fun->call_list; pasty; pasty = pasty->next)
4425                      if (pasty->is_pasted)                      if (pasty->is_pasted)
4426                        break;                        break;
4427                  }                  }
4428              }              }
4429            if (tmp > overlay_size)            if (align_power (tmp, roalign) + rotmp > overlay_size)
4430              break;              break;
4431    
4432            /* If we add this section, we might need new overlay call            /* If we add this section, we might need new overlay call
# Line 3711  spu_elf_auto_overlay (struct bfd_link_in Line 4465  spu_elf_auto_overlay (struct bfd_link_in
4465            for (call = dummy_caller.call_list; call; call = call->next)            for (call = dummy_caller.call_list; call; call = call->next)
4466              {              {
4467                unsigned int k;                unsigned int k;
4468                  unsigned int stub_delta = 1;
4469    
4470                  if (htab->params->ovly_flavour == ovly_soft_icache)
4471                    stub_delta = call->count;
4472                  num_stubs += stub_delta;
4473    
               ++num_stubs;  
4474                /* If the call is within this overlay, we won't need a                /* If the call is within this overlay, we won't need a
4475                   stub.  */                   stub.  */
4476                for (k = base; k < i + 1; k++)                for (k = base; k < i + 1; k++)
4477                  if (call->fun->sec == ovly_sections[2 * k])                  if (call->fun->sec == ovly_sections[2 * k])
4478                    {                    {
4479                      --num_stubs;                      num_stubs -= stub_delta;
4480                      break;                      break;
4481                    }                    }
4482              }              }
4483            if (tmp + num_stubs * ovl_stub_size (htab->params->ovly_flavour)            if (htab->params->ovly_flavour == ovly_soft_icache
4484                > overlay_size)                && num_stubs > htab->params->max_branch)
4485                break;
4486              if (align_power (tmp, roalign) + rotmp
4487                  + num_stubs * ovl_stub_size (htab->params) > overlay_size)
4488              break;              break;
             
4489            size = tmp;            size = tmp;
4490              rosize = rotmp;
4491          }          }
4492    
4493        if (i == base)        if (i == base)
# Line 3756  spu_elf_auto_overlay (struct bfd_link_in Line 4517  spu_elf_auto_overlay (struct bfd_link_in
4517    if (fprintf (script, "SECTIONS\n{\n") <= 0)    if (fprintf (script, "SECTIONS\n{\n") <= 0)
4518      goto file_err;      goto file_err;
4519    
4520    for (region = 1; region <= htab->params->num_regions; region++)    if (htab->params->ovly_flavour == ovly_soft_icache)
4521      {      {
4522        ovlynum = region;        if (fprintf (script,
4523                       " .data.icache ALIGN (16) : { *(.ovtab) *(.data.icache) }\n"
4524                       " . = ALIGN (%u);\n"
4525                       " .ovl.init : { *(.ovl.init) }\n"
4526                       " . = ABSOLUTE (ADDR (.ovl.init));\n",
4527                       htab->params->line_size) <= 0)
4528            goto file_err;
4529    
4530        base = 0;        base = 0;
4531        while (base < count && ovly_map[base] < ovlynum)        ovlynum = 1;
4532          base++;        while (base < count)
4533            {
4534              unsigned int indx = ovlynum - 1;
4535              unsigned int vma, lma;
4536    
4537        if (base == count)            vma = (indx & (htab->params->num_lines - 1)) << htab->line_size_log2;
4538          break;            lma = indx << htab->line_size_log2;
4539    
4540              if (fprintf (script, " .ovly%u ABSOLUTE (ADDR (.ovl.init)) + %u "
4541                           ": AT (ALIGN (LOADADDR (.ovl.init) + SIZEOF (.ovl.init), 16) + %u) {\n",
4542                           ovlynum, vma, lma) <= 0)
4543                goto file_err;
4544    
4545              base = print_one_overlay_section (script, base, count, ovlynum,
4546                                                ovly_map, ovly_sections, info);
4547              if (base == (unsigned) -1)
4548                goto file_err;
4549    
4550        if (fprintf (script, " OVERLAY :\n {\n") <= 0)            if (fprintf (script, "  }\n") <= 0)
4551                goto file_err;
4552    
4553              ovlynum++;
4554            }
4555    
4556          if (fprintf (script, " . = ABSOLUTE (ADDR (.ovl.init)) + %u;\n",
4557                       1 << (htab->num_lines_log2 + htab->line_size_log2)) <= 0)
4558            goto file_err;
4559        }
4560      else
4561        {
4562          if (fprintf (script,
4563                       " . = ALIGN (16);\n"
4564                       " .ovl.init : { *(.ovl.init) }\n"
4565                       " . = ABSOLUTE (ADDR (.ovl.init));\n") <= 0)
4566          goto file_err;          goto file_err;
4567    
4568        while (base < count)        for (region = 1; region <= htab->params->num_lines; region++)
4569          {          {
4570            unsigned int j;            ovlynum = region;
4571                        base = 0;
4572            if (fprintf (script, "  .ovly%u {\n", ovlynum) <= 0)            while (base < count && ovly_map[base] < ovlynum)
4573              goto file_err;              base++;
4574    
4575            for (j = base; j < count && ovly_map[j] == ovlynum; j++)            if (base == count)
4576              {              break;
               asection *sec = ovly_sections[2 * j];  
4577    
4578                if (fprintf (script, "   %s%c%s (%s)\n",            if (region == 1)
4579                             (sec->owner->my_archive != NULL              {
4580                              ? sec->owner->my_archive->filename : ""),                /* We need to set lma since we are overlaying .ovl.init.  */
4581                             info->path_separator,                if (fprintf (script,
4582                             sec->owner->filename,                             " OVERLAY : AT (ALIGN (LOADADDR (.ovl.init) + SIZEOF (.ovl.init), 16))\n {\n") <= 0)
4583                             sec->name) <= 0)                  goto file_err;
4584                }
4585              else
4586                {
4587                  if (fprintf (script, " OVERLAY :\n {\n") <= 0)
4588                  goto file_err;                  goto file_err;
               if (sec->segment_mark)  
                 {  
                   struct call_info *call = find_pasted_call (sec);  
                   while (call != NULL)  
                     {  
                       struct function_info *call_fun = call->fun;  
                       sec = call_fun->sec;  
                       if (fprintf (script, "   %s%c%s (%s)\n",  
                                    (sec->owner->my_archive != NULL  
                                     ? sec->owner->my_archive->filename : ""),  
                                    info->path_separator,  
                                    sec->owner->filename,  
                                    sec->name) <= 0)  
                         goto file_err;  
                       for (call = call_fun->call_list; call; call = call->next)  
                         if (call->is_pasted)  
                           break;  
                     }  
                 }  
4589              }              }
4590    
4591            for (j = base; j < count && ovly_map[j] == ovlynum; j++)            while (base < count)
4592              {              {
4593                asection *sec = ovly_sections[2 * j + 1];                if (fprintf (script, "  .ovly%u {\n", ovlynum) <= 0)
               if (sec != NULL  
                   && fprintf (script, "   %s%c%s (%s)\n",  
                               (sec->owner->my_archive != NULL  
                                ? sec->owner->my_archive->filename : ""),  
                               info->path_separator,  
                               sec->owner->filename,  
                               sec->name) <= 0)  
4594                  goto file_err;                  goto file_err;
4595    
4596                sec = ovly_sections[2 * j];                base = print_one_overlay_section (script, base, count, ovlynum,
4597                if (sec->segment_mark)                                                  ovly_map, ovly_sections, info);
4598                  {                if (base == (unsigned) -1)
4599                    struct call_info *call = find_pasted_call (sec);                  goto file_err;
4600                    while (call != NULL)  
4601                      {                if (fprintf (script, "  }\n") <= 0)
4602                        struct function_info *call_fun = call->fun;                  goto file_err;
4603                        sec = call_fun->rodata;  
4604                        if (sec != NULL                ovlynum += htab->params->num_lines;
4605                            && fprintf (script, "   %s%c%s (%s)\n",                while (base < count && ovly_map[base] < ovlynum)
4606                                        (sec->owner->my_archive != NULL                  base++;
                                        ? sec->owner->my_archive->filename : ""),  
                                       info->path_separator,  
                                       sec->owner->filename,  
                                       sec->name) <= 0)  
                         goto file_err;  
                       for (call = call_fun->call_list; call; call = call->next)  
                         if (call->is_pasted)  
                           break;  
                     }  
                 }  
4607              }              }
4608    
4609            if (fprintf (script, "  }\n") <= 0)            if (fprintf (script, " }\n") <= 0)
4610              goto file_err;              goto file_err;
   
           base = j;  
           ovlynum += htab->params->num_regions;  
           while (base < count && ovly_map[base] < ovlynum)  
             base++;  
4611          }          }
4612    
       if (fprintf (script, " }\n") <= 0)  
         goto file_err;  
4613      }      }
4614    
4615    free (ovly_map);    free (ovly_map);
# Line 3891  spu_elf_stack_analysis (struct bfd_link_ Line 4647  spu_elf_stack_analysis (struct bfd_link_
4647      return FALSE;      return FALSE;
4648    
4649    htab = spu_hash_table (info);    htab = spu_hash_table (info);
4650    info->callbacks->info (_("Stack size for call graph root nodes.\n"));    if (htab->params->stack_analysis)
4651    info->callbacks->minfo (_("\nStack size for functions.  "      {
4652                              "Annotations: '*' max stack, 't' tail call\n"));        info->callbacks->info (_("Stack size for call graph root nodes.\n"));
4653          info->callbacks->minfo (_("\nStack size for functions.  "
4654                                    "Annotations: '*' max stack, 't' tail call\n"));
4655        }
4656    
4657    sum_stack_param.emit_stack_syms = htab->params->emit_stack_syms;    sum_stack_param.emit_stack_syms = htab->params->emit_stack_syms;
4658    sum_stack_param.overall_stack = 0;    sum_stack_param.overall_stack = 0;
4659    if (!for_each_node (sum_stack, info, &sum_stack_param, TRUE))    if (!for_each_node (sum_stack, info, &sum_stack_param, TRUE))
4660      return FALSE;      return FALSE;
4661    
4662    info->callbacks->info (_("Maximum stack required is 0x%v\n"),    if (htab->params->stack_analysis)
4663                           (bfd_vma) sum_stack_param.overall_stack);      info->callbacks->info (_("Maximum stack required is 0x%v\n"),
4664                               (bfd_vma) sum_stack_param.overall_stack);
4665    return TRUE;    return TRUE;
4666  }  }
4667    
# Line 3915  spu_elf_final_link (bfd *output_bfd, str Line 4675  spu_elf_final_link (bfd *output_bfd, str
4675    if (htab->params->auto_overlay)    if (htab->params->auto_overlay)
4676      spu_elf_auto_overlay (info);      spu_elf_auto_overlay (info);
4677    
4678    if (htab->params->stack_analysis    if ((htab->params->stack_analysis
4679           || (htab->params->ovly_flavour == ovly_soft_icache
4680               && htab->params->lrlive_analysis))
4681        && !spu_elf_stack_analysis (info))        && !spu_elf_stack_analysis (info))
4682      info->callbacks->einfo ("%X%P: stack analysis error: %E\n");      info->callbacks->einfo ("%X%P: stack/lrlive analysis error: %E\n");
4683    
4684      if (!spu_elf_build_stubs (info))
4685        info->callbacks->einfo ("%F%P: can not build overlay stubs: %E\n");
4686    
4687    return bfd_elf_final_link (output_bfd, info);    return bfd_elf_final_link (output_bfd, info);
4688  }  }
# Line 3974  spu_elf_relocate_section (bfd *output_bf Line 4739  spu_elf_relocate_section (bfd *output_bf
4739    bfd_boolean emit_these_relocs = FALSE;    bfd_boolean emit_these_relocs = FALSE;
4740    bfd_boolean is_ea_sym;    bfd_boolean is_ea_sym;
4741    bfd_boolean stubs;    bfd_boolean stubs;
4742      unsigned int iovl = 0;
4743    
4744    htab = spu_hash_table (info);    htab = spu_hash_table (info);
4745    stubs = (htab->stub_sec != NULL    stubs = (htab->stub_sec != NULL
4746             && maybe_needs_stubs (input_section));             && maybe_needs_stubs (input_section));
4747      iovl = overlay_index (input_section);
4748    ea = bfd_get_section_by_name (output_bfd, "._ea");    ea = bfd_get_section_by_name (output_bfd, "._ea");
4749    symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;    symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
4750    sym_hashes = (struct elf_link_hash_entry **) (elf_sym_hashes (input_bfd));    sym_hashes = (struct elf_link_hash_entry **) (elf_sym_hashes (input_bfd));
# Line 4079  spu_elf_relocate_section (bfd *output_bf Line 4846  spu_elf_relocate_section (bfd *output_bf
4846        if (info->relocatable)        if (info->relocatable)
4847          continue;          continue;
4848    
4849          /* Change "a rt,ra,rb" to "ai rt,ra,0". */
4850          if (r_type == R_SPU_ADD_PIC && h != NULL
4851              && (h->def_regular || ELF_COMMON_DEF_P (h)))
4852            {
4853              bfd_byte *loc = contents + rel->r_offset;
4854              loc[0] = 0x1c;
4855              loc[1] = 0x00;
4856              loc[2] &= 0x3f;
4857            }
4858    
4859        is_ea_sym = (ea != NULL        is_ea_sym = (ea != NULL
4860                     && sec != NULL                     && sec != NULL
4861                     && sec->output_section == ea);                     && sec->output_section == ea);
4862    
4863        if (r_type == R_SPU_PPU32 || r_type == R_SPU_PPU64)        /* If this symbol is in an overlay area, we may need to relocate
4864             to the overlay stub.  */
4865          addend = rel->r_addend;
4866          if (stubs
4867              && !is_ea_sym
4868              && (stub_type = needs_ovl_stub (h, sym, sec, input_section, rel,
4869                                              contents, info)) != no_stub)
4870            {
4871              unsigned int ovl = 0;
4872              struct got_entry *g, **head;
4873    
4874              if (stub_type != nonovl_stub)
4875                ovl = iovl;
4876    
4877              if (h != NULL)
4878                head = &h->got.glist;
4879              else
4880                head = elf_local_got_ents (input_bfd) + r_symndx;
4881    
4882              for (g = *head; g != NULL; g = g->next)
4883                if (htab->params->ovly_flavour == ovly_soft_icache
4884                    ? (g->ovl == ovl
4885                       && g->br_addr == (rel->r_offset
4886                                         + input_section->output_offset
4887                                         + input_section->output_section->vma))
4888                    : g->addend == addend && (g->ovl == ovl || g->ovl == 0))
4889                  break;
4890              if (g == NULL)
4891                abort ();
4892    
4893              relocation = g->stub_addr;
4894              addend = 0;
4895            }
4896          else
4897            {
4898              /* For soft icache, encode the overlay index into addresses.  */
4899              if (htab->params->ovly_flavour == ovly_soft_icache
4900                  && (r_type == R_SPU_ADDR16_HI
4901                      || r_type == R_SPU_ADDR32 || r_type == R_SPU_REL32)
4902                  && !is_ea_sym)
4903                {
4904                  unsigned int ovl = overlay_index (sec);
4905                  if (ovl != 0)
4906                    {
4907                      unsigned int set_id = ((ovl - 1) >> htab->num_lines_log2) + 1;
4908                      relocation += set_id << 18;
4909                    }
4910                }
4911            }
4912    
4913          if (unresolved_reloc)
4914            ;
4915          else if (r_type == R_SPU_PPU32 || r_type == R_SPU_PPU64)
4916          {          {
4917            if (is_ea_sym)            if (is_ea_sym)
4918              {              {
# Line 4101  spu_elf_relocate_section (bfd *output_bf Line 4930  spu_elf_relocate_section (bfd *output_bf
4930            emit_these_relocs = TRUE;            emit_these_relocs = TRUE;
4931            continue;            continue;
4932          }          }
4933          else if (is_ea_sym)
       if (is_ea_sym)  
4934          unresolved_reloc = TRUE;          unresolved_reloc = TRUE;
4935    
4936        if (unresolved_reloc)        if (unresolved_reloc)
# Line 4117  spu_elf_relocate_section (bfd *output_bf Line 4945  spu_elf_relocate_section (bfd *output_bf
4945            ret = FALSE;            ret = FALSE;
4946          }          }
4947    
       /* If this symbol is in an overlay area, we may need to relocate  
          to the overlay stub.  */  
       addend = rel->r_addend;  
       if (stubs  
           && (stub_type = needs_ovl_stub (h, sym, sec, input_section, rel,  
                                           contents, info)) != no_stub)  
         {  
           unsigned int ovl = 0;  
           struct got_entry *g, **head;  
   
           if (stub_type != nonovl_stub)  
             ovl = (spu_elf_section_data (input_section->output_section)  
                    ->u.o.ovl_index);  
   
           if (h != NULL)  
             head = &h->got.glist;  
           else  
             head = elf_local_got_ents (input_bfd) + r_symndx;  
   
           for (g = *head; g != NULL; g = g->next)  
             if (g->addend == addend && (g->ovl == ovl || g->ovl == 0))  
               break;  
           if (g == NULL)  
             abort ();  
   
           relocation = g->stub_addr;  
           addend = 0;  
         }  
   
4948        r = _bfd_final_link_relocate (howto,        r = _bfd_final_link_relocate (howto,
4949                                      input_bfd,                                      input_bfd,
4950                                      input_section,                                      input_section,
# Line 4228  spu_elf_relocate_section (bfd *output_bf Line 5027  spu_elf_relocate_section (bfd *output_bf
5027    
5028  /* Adjust _SPUEAR_ syms to point at their overlay stubs.  */  /* Adjust _SPUEAR_ syms to point at their overlay stubs.  */
5029    
5030  static bfd_boolean  static int
5031  spu_elf_output_symbol_hook (struct bfd_link_info *info,  spu_elf_output_symbol_hook (struct bfd_link_info *info,
5032                              const char *sym_name ATTRIBUTE_UNUSED,                              const char *sym_name ATTRIBUTE_UNUSED,
5033                              Elf_Internal_Sym *sym,                              Elf_Internal_Sym *sym,
# Line 4248  spu_elf_output_symbol_hook (struct bfd_l Line 5047  spu_elf_output_symbol_hook (struct bfd_l
5047        struct got_entry *g;        struct got_entry *g;
5048    
5049        for (g = h->got.glist; g != NULL; g = g->next)        for (g = h->got.glist; g != NULL; g = g->next)
5050          if (g->addend == 0 && g->ovl == 0)          if (htab->params->ovly_flavour == ovly_soft_icache
5051                ? g->br_addr == g->stub_addr
5052                : g->addend == 0 && g->ovl == 0)
5053            {            {
5054              sym->st_shndx = (_bfd_elf_section_from_bfd_section              sym->st_shndx = (_bfd_elf_section_from_bfd_section
5055                               (htab->stub_sec[0]->output_section->owner,                               (htab->stub_sec[0]->output_section->owner,
# Line 4258  spu_elf_output_symbol_hook (struct bfd_l Line 5059  spu_elf_output_symbol_hook (struct bfd_l
5059            }            }
5060      }      }
5061    
5062    return TRUE;    return 1;
5063  }  }
5064    
5065  static int spu_plugin = 0;  static int spu_plugin = 0;
# Line 4315  static bfd_boolean Line 5116  static bfd_boolean
5116  spu_elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info)  spu_elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
5117  {  {
5118    asection *toe, *s;    asection *toe, *s;
5119    struct elf_segment_map *m;    struct elf_segment_map *m, *m_overlay;
5120      struct elf_segment_map **p, **p_overlay;
5121    unsigned int i;    unsigned int i;
5122    
5123    if (info == NULL)    if (info == NULL)
# Line 4362  spu_elf_modify_segment_map (bfd *abfd, s Line 5164  spu_elf_modify_segment_map (bfd *abfd, s
5164              break;              break;
5165            }            }
5166    
5167    
5168      /* Some SPU ELF loaders ignore the PF_OVERLAY flag and just load all
5169         PT_LOAD segments.  This can cause the .ovl.init section to be
5170         overwritten with the contents of some overlay segment.  To work
5171         around this issue, we ensure that all PF_OVERLAY segments are
5172         sorted first amongst the program headers; this ensures that even
5173         with a broken loader, the .ovl.init section (which is not marked
5174         as PF_OVERLAY) will be placed into SPU local store on startup.  */
5175    
5176      /* Move all overlay segments onto a separate list.  */
5177      p = &elf_tdata (abfd)->segment_map;
5178      p_overlay = &m_overlay;
5179      while (*p != NULL)
5180        {
5181          if ((*p)->p_type == PT_LOAD && (*p)->count == 1
5182              && spu_elf_section_data ((*p)->sections[0])->u.o.ovl_index != 0)
5183            {
5184              struct elf_segment_map *m = *p;
5185              *p = m->next;
5186              *p_overlay = m;
5187              p_overlay = &m->next;
5188              continue;
5189            }
5190    
5191          p = &((*p)->next);
5192        }
5193    
5194      /* Re-insert overlay segments at the head of the segment map.  */
5195      *p_overlay = elf_tdata (abfd)->segment_map;
5196      elf_tdata (abfd)->segment_map = m_overlay;
5197    
5198    return TRUE;    return TRUE;
5199  }  }
5200    
# Line 4409  spu_elf_modify_program_headers (bfd *abf Line 5242  spu_elf_modify_program_headers (bfd *abf
5242              /* Mark this as an overlay header.  */              /* Mark this as an overlay header.  */
5243              phdr[i].p_flags |= PF_OVERLAY;              phdr[i].p_flags |= PF_OVERLAY;
5244    
5245              if (htab->ovtab != NULL && htab->ovtab->size != 0)              if (htab->ovtab != NULL && htab->ovtab->size != 0
5246                    && htab->params->ovly_flavour != ovly_soft_icache)
5247                {                {
5248                  bfd_byte *p = htab->ovtab->contents;                  bfd_byte *p = htab->ovtab->contents;
5249                  unsigned int off = o * 16 + 8;                  unsigned int off = o * 16 + 8;
# Line 4418  spu_elf_modify_program_headers (bfd *abf Line 5252  spu_elf_modify_program_headers (bfd *abf
5252                  bfd_put_32 (htab->ovtab->owner, phdr[i].p_offset, p + off);                  bfd_put_32 (htab->ovtab->owner, phdr[i].p_offset, p + off);
5253                }                }
5254            }            }
5255          /* Soft-icache has its file offset put in .ovl.init.  */
5256          if (htab->init != NULL && htab->init->size != 0)
5257            {
5258              bfd_vma val = elf_section_data (htab->ovl_sec[0])->this_hdr.sh_offset;
5259    
5260              bfd_put_32 (htab->init->owner, val, htab->init->contents + 4);
5261            }
5262      }      }
5263    
5264    /* Round up p_filesz and p_memsz of PT_LOAD segments to multiples    /* Round up p_filesz and p_memsz of PT_LOAD segments to multiples
# Line 4474  spu_elf_modify_program_headers (bfd *abf Line 5315  spu_elf_modify_program_headers (bfd *abf
5315  #define elf_backend_can_gc_sections     1  #define elf_backend_can_gc_sections     1
5316    
5317  #define bfd_elf32_bfd_reloc_type_lookup         spu_elf_reloc_type_lookup  #define bfd_elf32_bfd_reloc_type_lookup         spu_elf_reloc_type_lookup
5318  #define bfd_elf32_bfd_reloc_name_lookup spu_elf_reloc_name_lookup  #define bfd_elf32_bfd_reloc_name_lookup         spu_elf_reloc_name_lookup
5319  #define elf_info_to_howto                       spu_elf_info_to_howto  #define elf_info_to_howto                       spu_elf_info_to_howto
5320  #define elf_backend_count_relocs                spu_elf_count_relocs  #define elf_backend_count_relocs                spu_elf_count_relocs
5321  #define elf_backend_relocate_section            spu_elf_relocate_section  #define elf_backend_relocate_section            spu_elf_relocate_section

Legend:
Removed from v.20  
changed lines
  Added in v.21

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26