* elf32-spu.c (spu_elf_create_sections): Remove output_bfd parameter.
	(spu_elf_find_overlays, spu_elf_size_stubs): Likewise
	(process_stubs, discover_functions, build_call_tree): Likewise.
	(spu_elf_stack_analysis): Likewise.
	(spu_elf_check_vma): Likewise.  Move.
	(struct call_info): Make "is_tail" a bitfield.
	(insert_callee): Clear fun->start and set fun->is_func if we find
	a non-tail call.
	* elf32-spu.h (spu_elf_create_sections): Update prototype.
	(spu_elf_find_overlays, spu_elf_size_stubs, spu_elf_check_vma): Ditto.
ld/
	* emultempl/spuelf.em: Update calls to elf32-spu.c funcs.
This commit is contained in:
Alan Modra
2008-03-20 05:35:10 +00:00
parent eb42429a93
commit c65be8d78a
5 changed files with 82 additions and 67 deletions

@ -1,3 +1,16 @@
2008-03-20 Alan Modra <amodra@bigpond.net.au>
* elf32-spu.c (spu_elf_create_sections): Remove output_bfd parameter.
(spu_elf_find_overlays, spu_elf_size_stubs): Likewise
(process_stubs, discover_functions, build_call_tree): Likewise.
(spu_elf_stack_analysis): Likewise.
(spu_elf_check_vma): Likewise. Move.
(struct call_info): Make "is_tail" a bitfield.
(insert_callee): Clear fun->start and set fun->is_func if we find
a non-tail call.
* elf32-spu.h (spu_elf_create_sections): Update prototype.
(spu_elf_find_overlays, spu_elf_size_stubs, spu_elf_check_vma): Ditto.
2008-03-17 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* aclocal.m4: Regenerate.

@ -419,8 +419,7 @@ get_sym_h (struct elf_link_hash_entry **hp,
that the linker maps the sections to the right place in the output. */
bfd_boolean
spu_elf_create_sections (bfd *output_bfd,
struct bfd_link_info *info,
spu_elf_create_sections (struct bfd_link_info *info,
int stack_analysis,
int emit_stack_syms)
{
@ -451,7 +450,7 @@ spu_elf_create_sections (bfd *output_bfd,
|| !bfd_set_section_alignment (ibfd, s, 4))
return FALSE;
name_len = strlen (bfd_get_filename (output_bfd)) + 1;
name_len = strlen (bfd_get_filename (info->output_bfd)) + 1;
size = 12 + ((sizeof (SPU_PLUGIN_NAME) + 3) & -4);
size += (name_len + 3) & -4;
@ -467,7 +466,7 @@ spu_elf_create_sections (bfd *output_bfd,
bfd_put_32 (ibfd, 1, data + 8);
memcpy (data + 12, SPU_PLUGIN_NAME, sizeof (SPU_PLUGIN_NAME));
memcpy (data + 12 + ((sizeof (SPU_PLUGIN_NAME) + 3) & -4),
bfd_get_filename (output_bfd), name_len);
bfd_get_filename (info->output_bfd), name_len);
s->contents = data;
}
@ -492,7 +491,7 @@ sort_sections (const void *a, const void *b)
/* Identify overlays in the output bfd, and number them. */
bfd_boolean
spu_elf_find_overlays (bfd *output_bfd, struct bfd_link_info *info)
spu_elf_find_overlays (struct bfd_link_info *info)
{
struct spu_link_hash_table *htab = spu_hash_table (info);
asection **alloc_sec;
@ -500,15 +499,16 @@ spu_elf_find_overlays (bfd *output_bfd, struct bfd_link_info *info)
asection *s;
bfd_vma ovl_end;
if (output_bfd->section_count < 2)
if (info->output_bfd->section_count < 2)
return FALSE;
alloc_sec = bfd_malloc (output_bfd->section_count * sizeof (*alloc_sec));
alloc_sec
= bfd_malloc (info->output_bfd->section_count * sizeof (*alloc_sec));
if (alloc_sec == NULL)
return FALSE;
/* Pick out all the alloced sections. */
for (n = 0, s = output_bfd->sections; s != NULL; s = s->next)
for (n = 0, s = info->output_bfd->sections; s != NULL; s = s->next)
if ((s->flags & SEC_ALLOC) != 0
&& (s->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != SEC_THREAD_LOCAL
&& s->size != 0)
@ -1043,9 +1043,7 @@ build_spuear_stubs (struct elf_link_hash_entry *h, void *inf)
/* Size or build stubs. */
static bfd_boolean
process_stubs (bfd *output_bfd,
struct bfd_link_info *info,
bfd_boolean build)
process_stubs (struct bfd_link_info *info, bfd_boolean build)
{
struct spu_link_hash_table *htab = spu_hash_table (info);
bfd *ibfd;
@ -1081,7 +1079,7 @@ process_stubs (bfd *output_bfd,
|| isec->reloc_count == 0)
continue;
if (!maybe_needs_stubs (isec, output_bfd))
if (!maybe_needs_stubs (isec, info->output_bfd))
continue;
/* Get the relocs. */
@ -1180,8 +1178,7 @@ process_stubs (bfd *output_bfd,
/* Allocate space for overlay call and return stubs. */
int
spu_elf_size_stubs (bfd *output_bfd,
struct bfd_link_info *info,
spu_elf_size_stubs (struct bfd_link_info *info,
void (*place_spu_section) (asection *, asection *,
const char *),
int non_overlay_stubs)
@ -1194,7 +1191,7 @@ spu_elf_size_stubs (bfd *output_bfd,
asection *stub;
htab->non_overlay_stubs = non_overlay_stubs;
if (!process_stubs (output_bfd, info, FALSE))
if (!process_stubs (info, FALSE))
return 0;
elf_link_hash_traverse (&htab->elf, allocate_spuear_stubs, htab);
@ -1392,9 +1389,8 @@ spu_elf_build_stubs (struct bfd_link_info *info, int emit_syms)
h = elf_link_hash_lookup (&htab->elf, "__ovly_return", FALSE, FALSE, FALSE);
htab->ovly_return = h;
/* Write out all the stubs. */
obfd = htab->ovtab->output_section->owner;
process_stubs (obfd, info, TRUE);
/* Fill in all the stubs. */
process_stubs (info, TRUE);
elf_link_hash_traverse (&htab->elf, build_spuear_stubs, htab);
if (htab->stub_err)
@ -1426,6 +1422,7 @@ spu_elf_build_stubs (struct bfd_link_info *info, int emit_syms)
p = htab->ovtab->contents;
/* set low bit of .size to mark non-overlay area as present. */
p[7] = 1;
obfd = htab->ovtab->output_section->owner;
for (s = obfd->sections; s != NULL; s = s->next)
{
unsigned int ovl_index = spu_elf_section_data (s)->u.o.ovl_index;
@ -1476,6 +1473,28 @@ spu_elf_build_stubs (struct bfd_link_info *info, int emit_syms)
return TRUE;
}
/* Check that all loadable section VMAs lie in the range
LO .. HI inclusive. */
asection *
spu_elf_check_vma (struct bfd_link_info *info, bfd_vma lo, bfd_vma hi)
{
struct elf_segment_map *m;
unsigned int i;
bfd *abfd = info->output_bfd;
for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
if (m->p_type == PT_LOAD)
for (i = 0; i < m->count; i++)
if (m->sections[i]->size != 0
&& (m->sections[i]->vma < lo
|| m->sections[i]->vma > hi
|| m->sections[i]->vma + m->sections[i]->size - 1 > hi))
return m->sections[i];
return NULL;
}
/* OFFSET in SEC (presumably) is the beginning of a function prologue.
Search for stack adjusting insns, and return the sp delta. */
@ -1608,7 +1627,7 @@ struct call_info
{
struct function_info *fun;
struct call_info *next;
int is_tail;
unsigned int is_tail : 1;
};
struct function_info
@ -1910,8 +1929,12 @@ insert_callee (struct function_info *caller, struct call_info *callee)
{
/* Tail calls use less stack than normal calls. Retain entry
for normal call over one for tail call. */
if (p->is_tail > callee->is_tail)
p->is_tail = callee->is_tail;
p->is_tail &= callee->is_tail;
if (!p->is_tail)
{
p->fun->start = NULL;
p->fun->is_func = TRUE;
}
return FALSE;
}
callee->next = caller->call_list;
@ -2137,7 +2160,7 @@ interesting_section (asection *s, bfd *obfd)
/* Map address ranges in code sections to functions. */
static bfd_boolean
discover_functions (bfd *output_bfd, struct bfd_link_info *info)
discover_functions (struct bfd_link_info *info)
{
bfd *ibfd;
int bfd_idx;
@ -2203,7 +2226,7 @@ discover_functions (bfd *output_bfd, struct bfd_link_info *info)
asection *s;
*p = s = bfd_section_from_elf_index (ibfd, sy->st_shndx);
if (s != NULL && interesting_section (s, output_bfd))
if (s != NULL && interesting_section (s, info->output_bfd))
*psy++ = sy;
}
symcount = psy - psyms;
@ -2245,7 +2268,7 @@ discover_functions (bfd *output_bfd, struct bfd_link_info *info)
}
for (sec = ibfd->sections; sec != NULL && !gaps; sec = sec->next)
if (interesting_section (sec, output_bfd))
if (interesting_section (sec, info->output_bfd))
gaps |= check_function_ranges (sec, info);
}
@ -2263,7 +2286,7 @@ discover_functions (bfd *output_bfd, struct bfd_link_info *info)
continue;
for (sec = ibfd->sections; sec != NULL; sec = sec->next)
if (interesting_section (sec, output_bfd)
if (interesting_section (sec, info->output_bfd)
&& sec->reloc_count != 0)
{
if (!mark_functions_via_relocs (sec, info, FALSE))
@ -2290,7 +2313,7 @@ discover_functions (bfd *output_bfd, struct bfd_link_info *info)
gaps = FALSE;
for (sec = ibfd->sections; sec != NULL && !gaps; sec = sec->next)
if (interesting_section (sec, output_bfd))
if (interesting_section (sec, info->output_bfd))
gaps |= check_function_ranges (sec, info);
if (!gaps)
continue;
@ -2316,7 +2339,7 @@ discover_functions (bfd *output_bfd, struct bfd_link_info *info)
the range of such functions to the beginning of the
next symbol of interest. */
for (sec = ibfd->sections; sec != NULL; sec = sec->next)
if (interesting_section (sec, output_bfd))
if (interesting_section (sec, info->output_bfd))
{
struct _spu_elf_section_data *sec_data;
struct spu_elf_stack_info *sinfo;
@ -2409,7 +2432,7 @@ call_graph_traverse (struct function_info *fun, struct bfd_link_info *info)
/* Populate call_list for each function. */
static bfd_boolean
build_call_tree (bfd *output_bfd, struct bfd_link_info *info)
build_call_tree (struct bfd_link_info *info)
{
bfd *ibfd;
@ -2423,7 +2446,7 @@ build_call_tree (bfd *output_bfd, struct bfd_link_info *info)
for (sec = ibfd->sections; sec != NULL; sec = sec->next)
{
if (!interesting_section (sec, output_bfd)
if (!interesting_section (sec, info->output_bfd)
|| sec->reloc_count == 0)
continue;
@ -2614,17 +2637,15 @@ sum_stack (struct function_info *fun,
/* Provide an estimate of total stack required. */
static bfd_boolean
spu_elf_stack_analysis (bfd *output_bfd,
struct bfd_link_info *info,
int emit_stack_syms)
spu_elf_stack_analysis (struct bfd_link_info *info, int emit_stack_syms)
{
bfd *ibfd;
bfd_vma max_stack = 0;
if (!discover_functions (output_bfd, info))
if (!discover_functions (info))
return FALSE;
if (!build_call_tree (output_bfd, info))
if (!build_call_tree (info))
return FALSE;
info->callbacks->info (_("Stack size for call graph root nodes.\n"));
@ -2679,7 +2700,7 @@ spu_elf_final_link (bfd *output_bfd, struct bfd_link_info *info)
struct spu_link_hash_table *htab = spu_hash_table (info);
if (htab->stack_analysis
&& !spu_elf_stack_analysis (output_bfd, info, htab->emit_stack_syms))
&& !spu_elf_stack_analysis (info, htab->emit_stack_syms))
info->callbacks->einfo ("%X%P: stack analysis error: %E\n");
return bfd_elf_final_link (output_bfd, info);
@ -3053,27 +3074,6 @@ spu_elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
return TRUE;
}
/* Check that all loadable section VMAs lie in the range
LO .. HI inclusive. */
asection *
spu_elf_check_vma (bfd *abfd, bfd_vma lo, bfd_vma hi)
{
struct elf_segment_map *m;
unsigned int i;
for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
if (m->p_type == PT_LOAD)
for (i = 0; i < m->count; i++)
if (m->sections[i]->size != 0
&& (m->sections[i]->vma < lo
|| m->sections[i]->vma > hi
|| m->sections[i]->vma + m->sections[i]->size - 1 > hi))
return m->sections[i];
return NULL;
}
/* Tweak the section type of .note.spu_name. */
static bfd_boolean

@ -1,6 +1,6 @@
/* SPU specific support for 32-bit ELF.
Copyright 2006, 2007 Free Software Foundation, Inc.
Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@ -54,11 +54,10 @@ struct _ovl_stream
extern void spu_elf_plugin (int);
extern bfd_boolean spu_elf_open_builtin_lib (bfd **,
const struct _ovl_stream *);
extern bfd_boolean spu_elf_create_sections (bfd *,
struct bfd_link_info *, int, int);
extern bfd_boolean spu_elf_find_overlays (bfd *, struct bfd_link_info *);
extern int spu_elf_size_stubs (bfd *, struct bfd_link_info *,
extern bfd_boolean spu_elf_create_sections (struct bfd_link_info *, int, int);
extern bfd_boolean spu_elf_find_overlays (struct bfd_link_info *);
extern int spu_elf_size_stubs (struct bfd_link_info *,
void (*) (asection *, asection *, const char *),
int);
extern bfd_boolean spu_elf_build_stubs (struct bfd_link_info *, int);
extern asection *spu_elf_check_vma (bfd *, bfd_vma, bfd_vma);
extern asection *spu_elf_check_vma (struct bfd_link_info *, bfd_vma, bfd_vma);

@ -1,3 +1,7 @@
2008-03-20 Alan Modra <amodra@bigpond.net.au>
* emultempl/spuelf.em: Update calls to elf32-spu.c funcs.
2008-03-17 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* aclocal.m4: Regenerate.

@ -75,7 +75,7 @@ spu_after_open (void)
if (is_spu_target ()
&& !link_info.relocatable
&& link_info.input_bfds != NULL
&& !spu_elf_create_sections (link_info.output_bfd, &link_info,
&& !spu_elf_create_sections (&link_info,
stack_analysis, emit_stack_syms))
einfo ("%X%P: can not create note section: %E\n");
@ -198,11 +198,11 @@ spu_before_allocation (void)
one_lang_size_sections_pass (NULL, TRUE);
/* Find overlays by inspecting section vmas. */
if (spu_elf_find_overlays (link_info.output_bfd, &link_info))
if (spu_elf_find_overlays (&link_info))
{
int ret;
ret = spu_elf_size_stubs (link_info.output_bfd, &link_info,
ret = spu_elf_size_stubs (&link_info,
spu_place_special_section,
non_overlay_stubs);
if (ret == 0)
@ -235,8 +235,7 @@ gld${EMULATION_NAME}_finish (void)
{
asection *s;
s = spu_elf_check_vma (link_info.output_bfd,
local_store_lo, local_store_hi);
s = spu_elf_check_vma (&link_info, local_store_lo, local_store_hi);
if (s != NULL)
einfo ("%X%P: %A exceeds local store range\n", s);
}