From c65be8d78a6822e12d6037afdaddcde688f90f7a Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 20 Mar 2008 05:35:10 +0000 Subject: [PATCH] bfd/ * 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. --- bfd/ChangeLog | 13 +++++ bfd/elf32-spu.c | 112 ++++++++++++++++++++--------------------- bfd/elf32-spu.h | 11 ++-- ld/ChangeLog | 4 ++ ld/emultempl/spuelf.em | 9 ++-- 5 files changed, 82 insertions(+), 67 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 7a2c42c53a..c6157add39 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2008-03-20 Alan Modra + + * 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 * aclocal.m4: Regenerate. diff --git a/bfd/elf32-spu.c b/bfd/elf32-spu.c index fd93565765..db9f205868 100644 --- a/bfd/elf32-spu.c +++ b/bfd/elf32-spu.c @@ -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 diff --git a/bfd/elf32-spu.h b/bfd/elf32-spu.h index 4478e20cc1..b7e50a03b0 100644 --- a/bfd/elf32-spu.h +++ b/bfd/elf32-spu.h @@ -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); diff --git a/ld/ChangeLog b/ld/ChangeLog index f79ac8af87..64eacd5b2b 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,7 @@ +2008-03-20 Alan Modra + + * emultempl/spuelf.em: Update calls to elf32-spu.c funcs. + 2008-03-17 Ralf Wildenhues * aclocal.m4: Regenerate. diff --git a/ld/emultempl/spuelf.em b/ld/emultempl/spuelf.em index fa28212bbd..3a8cf28a31 100644 --- a/ld/emultempl/spuelf.em +++ b/ld/emultempl/spuelf.em @@ -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); } -- 2.34.1