unsigned int overlay_fixed;
/* Local store --auto-overlay should reserve for stack and heap. */
unsigned int reserved;
+ /* If reserved is not specified, stack analysis will calculate a value
+ for the stack. This parameter adjusts that value to allow for
+ negative sp access (the ABI says 2000 bytes below sp are valid,
+ and the overlay manager uses some of this area). */
+ int extra_stack_space;
/* Count of overlay stubs needed in non-overlay area. */
unsigned int non_ovly_stub;
section needs a stub. */
if (spu_elf_section_data (sym_sec->output_section)->u.o.ovl_index
!= spu_elf_section_data (input_section->output_section)->u.o.ovl_index)
- return ovl_stub;
+ ret = ovl_stub;
/* If this insn isn't a branch then we are possibly taking the
address of a function and passing it out somehow. */
if (OVL_STUB_SIZE == 16)
val -= 12;
if (((dest | to | from) & 3) != 0
- || val + 0x20000 >= 0x40000)
+ || val + 0x40000 >= 0x80000)
{
htab->stub_err = 1;
return FALSE;
&& (spu_elf_section_data (sym_sec->output_section)->u.o.ovl_index != 0
|| htab->non_overlay_stubs))
{
- count_stub (htab, NULL, NULL, nonovl_stub, h, NULL);
+ return count_stub (htab, NULL, NULL, nonovl_stub, h, NULL);
}
return TRUE;
&& (spu_elf_section_data (sym_sec->output_section)->u.o.ovl_index != 0
|| htab->non_overlay_stubs))
{
- build_stub (htab, NULL, NULL, nonovl_stub, h, NULL,
- h->root.u.def.value, sym_sec);
+ return build_stub (htab, NULL, NULL, nonovl_stub, h, NULL,
+ h->root.u.def.value, sym_sec);
}
return TRUE;
/* Fill in all the stubs. */
process_stubs (info, TRUE);
+ if (!htab->stub_err)
+ elf_link_hash_traverse (&htab->elf, build_spuear_stubs, info);
- elf_link_hash_traverse (&htab->elf, build_spuear_stubs, info);
if (htab->stub_err)
- return FALSE;
+ {
+ (*_bfd_error_handler) (_("overlay stub relocation overflow"));
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
for (i = 0; i <= htab->num_overlays; i++)
{
htab->stub_sec[i]->rawsize = 0;
}
- if (htab->stub_err)
- {
- (*_bfd_error_handler) (_("overlay stub relocation overflow"));
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
-
htab->ovtab->contents = bfd_zalloc (htab->ovtab->owner, htab->ovtab->size);
if (htab->ovtab->contents == NULL)
return FALSE;
unsigned int hi,
unsigned int overlay_fixed,
unsigned int reserved,
+ int extra_stack_space,
void (*spu_elf_load_ovl_mgr) (void),
FILE *(*spu_elf_open_overlay_script) (void),
void (*spu_elf_relink) (void))
htab->local_store = hi + 1 - lo;
htab->overlay_fixed = overlay_fixed;
htab->reserved = reserved;
+ htab->extra_stack_space = extra_stack_space;
htab->spu_elf_load_ovl_mgr = spu_elf_load_ovl_mgr;
htab->spu_elf_open_overlay_script = spu_elf_open_overlay_script;
htab->spu_elf_relink = spu_elf_relink;
return TRUE;
}
+/* If non-zero then unmark functions called from those within sections
+ that we need to unmark. Unfortunately this isn't reliable since the
+ call graph cannot know the destination of function pointer calls. */
+#define RECURSE_UNMARK 0
+
struct _uos_param {
asection *exclude_input_section;
asection *exclude_output_section;
|| fun->sec->output_section == uos_param->exclude_output_section)
excluded = 1;
- uos_param->clearing += excluded;
+ if (RECURSE_UNMARK)
+ uos_param->clearing += excluded;
- if (uos_param->clearing)
+ if (RECURSE_UNMARK ? uos_param->clearing : excluded)
{
fun->sec->linker_mark = 0;
if (fun->rodata)
if (!unmark_overlay_section (call->fun, info, param))
return FALSE;
- uos_param->clearing -= excluded;
+ if (RECURSE_UNMARK)
+ uos_param->clearing -= excluded;
return TRUE;
}
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->reserved = sum_stack_param.overall_stack + htab->extra_stack_space;
}
fixed_size += htab->reserved;
fixed_size += htab->non_ovly_stub * OVL_STUB_SIZE;
}
else
{
- RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
- r_symndx, symtab_hdr, sym_hashes,
- h, sec, relocation,
- unresolved_reloc, warned);
+ if (sym_hashes == NULL)
+ return FALSE;
+
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ relocation = 0;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ sec = h->root.u.def.section;
+ if (sec == NULL
+ || sec->output_section == NULL)
+ /* Set a flag that will be cleared later if we find a
+ relocation value for this symbol. output_section
+ is typically NULL for symbols satisfied by a shared
+ library. */
+ unresolved_reloc = TRUE;
+ else
+ relocation = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else if (h->root.type == bfd_link_hash_undefweak)
+ ;
+ else if (info->unresolved_syms_in_objects == RM_IGNORE
+ && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
+ ;
+ else if (!info->relocatable
+ && !(r_type == R_SPU_PPU32 || r_type == R_SPU_PPU64))
+ {
+ bfd_boolean err;
+ err = (info->unresolved_syms_in_objects == RM_GENERATE_ERROR
+ || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT);
+ if (!info->callbacks->undefined_symbol (info,
+ h->root.root.string,
+ input_bfd,
+ input_section,
+ rel->r_offset, err))
+ return FALSE;
+ warned = TRUE;
+ }
sym_name = h->root.root.string;
}