OSDN Git Service

* elf64-ppc.c (ppc64_elf_next_input_section): Use elf_gp value
authoramodra <amodra>
Tue, 1 Feb 2011 07:38:24 +0000 (07:38 +0000)
committeramodra <amodra>
Tue, 1 Feb 2011 07:38:24 +0000 (07:38 +0000)
for toc pointer on any section having makes_toc_func_call set.
(check_pasted_section): Ensure pasted .init/.fini fragments use
the same toc if any has makes_toc_func_call set.

bfd/ChangeLog
bfd/elf64-ppc.c

index c643fb7..35d534f 100644 (file)
@@ -1,3 +1,10 @@
+2011-02-01  Alan Modra  <amodra@gmail.com>
+
+       * elf64-ppc.c (ppc64_elf_next_input_section): Use elf_gp value
+       for toc pointer on any section having makes_toc_func_call set.
+       (check_pasted_section): Ensure pasted .init/.fini fragments use
+       the same toc if any has makes_toc_func_call set.
+
 2011-01-28  Joseph Myers  <joseph@codesourcery.com>
 
        * elf32-ppc.c (ppc_elf_link_hash_newfunc): Initialize has_sda_refs
index 5c35dc1..d020928 100644 (file)
@@ -10580,14 +10580,28 @@ ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec)
          if (elf_gp (isec->owner) != 0)
            htab->toc_curr = elf_gp (isec->owner);
        }
-      else if (!isec->call_check_done
-              && toc_adjusting_stub_needed (info, isec) < 0)
-       return FALSE;
+      else
+       {
+         if (!isec->call_check_done
+             && toc_adjusting_stub_needed (info, isec) < 0)
+           return FALSE;
+         /* If we make a local call from this section, ie. a branch
+            without a following nop, then we have no place to put a
+            toc restoring insn.  We must use the same toc group as
+            the callee.
+            Testing makes_toc_func_call actually tests for *any*
+            calls to functions that need a good toc pointer.  A more
+            precise test would be better, as this one will set
+            incorrect values for pasted .init/.fini fragments.
+            (Fixed later in check_pasted_section.)  */
+         if (isec->makes_toc_func_call
+             && elf_gp (isec->owner) != 0)
+           htab->toc_curr = elf_gp (isec->owner);
+       }
     }
 
   /* Functions that don't use the TOC can belong in any TOC group.
-     Use the last TOC base.  This happens to make _init and _fini
-     pasting work, because the fragments generally don't use the TOC.  */
+     Use the last TOC base.  */
   htab->stub_group[isec->id].toc_off = htab->toc_curr;
   return TRUE;
 }
@@ -10614,6 +10628,15 @@ check_pasted_section (struct bfd_link_info *info, const char *name)
            else if (toc_off != htab->stub_group[i->id].toc_off)
              return FALSE;
          }
+
+      if (toc_off == 0)
+       for (i = o->map_head.s; i != NULL; i = i->map_head.s)
+         if (i->makes_toc_func_call)
+           {
+             toc_off = htab->stub_group[i->id].toc_off;
+             break;
+           }
+
       /* Make sure the whole pasted function uses the same toc offset.  */
       if (toc_off != 0)
        for (i = o->map_head.s; i != NULL; i = i->map_head.s)