From 911f096e1a0b04d82d059a42e459b15503c285ce Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 28 Feb 2008 09:30:27 +0000 Subject: [PATCH] * elf32-spu.c (mark_functions_via_relocs): Don't assume that the "->start" pointer reaches to function origin, so that we can handle functions split over more than two sections. (build_call_tree): Likewise. (pasted_function): Don't attempt to set fun->start back to the function origin, just go back one section. --- bfd/ChangeLog | 11 ++++++++++- bfd/elf32-spu.c | 38 +++++++++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 1646c19d641..15b939d5863 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2008-02-28 Alan Modra + + * elf32-spu.c (mark_functions_via_relocs): Don't assume that + the "->start" pointer reaches to function origin, so that we + can handle functions split over more than two sections. + (build_call_tree): Likewise. + (pasted_function): Don't attempt to set fun->start back to the + function origin, just go back one section. + 2008-02-27 Catherine Moore * elf.c ( _bfd_elf_print_private_bfd_data): Call @@ -9,7 +18,7 @@ * elfxx-mips.h (_bfd_mips_elf_get_target_dtag): Declare. * elf-bfd.h (elf_backend_get_target_dtag): Add prototype. * elfxx-target.h (elf_backend_get_target_dtag): Add default. - (elf_backend_data): Add elf_backend_get_target_dtag. + (elf_backend_data): Add elf_backend_get_target_dtag. 2008-02-26 Alan Modra diff --git a/bfd/elf32-spu.c b/bfd/elf32-spu.c index 826512f0c63..3557c6bc0fb 100644 --- a/bfd/elf32-spu.c +++ b/bfd/elf32-spu.c @@ -1997,14 +1997,29 @@ mark_functions_via_relocs (asection *sec, destination has been called by some other function then it is a separate function. We also assume that functions are not split across input files. */ - if (callee->fun->start != NULL - || sec->owner != sym_sec->owner) + if (sec->owner != sym_sec->owner) { callee->fun->start = NULL; callee->fun->is_func = TRUE; } - else + else if (callee->fun->start == NULL) callee->fun->start = caller; + else + { + struct function_info *callee_start; + struct function_info *caller_start; + callee_start = callee->fun; + while (callee_start->start) + callee_start = callee_start->start; + caller_start = caller; + while (caller_start->start) + caller_start = caller_start->start; + if (caller_start != callee_start) + { + callee->fun->start = NULL; + callee->fun->is_func = TRUE; + } + } } } @@ -2041,11 +2056,7 @@ pasted_function (asection *sec, struct bfd_link_info *info) if (l->u.indirect.section == sec) { if (fun_start != NULL) - { - if (fun_start->start) - fun_start = fun_start->start; - fun->start = fun_start; - } + fun->start = fun_start; return TRUE; } if (l->type == bfd_indirect_link_order @@ -2382,14 +2393,19 @@ build_call_tree (bfd *output_bfd, struct bfd_link_info *info) int i; for (i = 0; i < sinfo->num_fun; ++i) { - if (sinfo->fun[i].start != NULL) + struct function_info *start = sinfo->fun[i].start; + + if (start != NULL) { - struct call_info *call = sinfo->fun[i].call_list; + struct call_info *call; + while (start->start != NULL) + start = start->start; + call = sinfo->fun[i].call_list; while (call != NULL) { struct call_info *call_next = call->next; - if (!insert_callee (sinfo->fun[i].start, call)) + if (!insert_callee (start, call)) free (call); call = call_next; } -- 2.30.2