* elf32-spu.c (mark_functions_via_relocs): Don't assume that
authorAlan Modra <amodra@gmail.com>
Thu, 28 Feb 2008 09:30:27 +0000 (09:30 +0000)
committerAlan Modra <amodra@gmail.com>
Thu, 28 Feb 2008 09:30:27 +0000 (09:30 +0000)
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
bfd/elf32-spu.c

index 1646c19..15b939d 100644 (file)
@@ -1,3 +1,12 @@
+2008-02-28  Alan Modra  <amodra@bigpond.net.au>
+
+       * 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  <clm@codesourcery.com>
 
        * 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  <amodra@bigpond.net.au>
 
index 826512f..3557c6b 100644 (file)
@@ -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;
                        }