PowerPC64 debian bug 886264, out-of-line save/restore functions
authorAlan Modra <amodra@gmail.com>
Wed, 14 Mar 2018 11:39:33 +0000 (22:09 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 14 Mar 2018 11:50:11 +0000 (22:20 +1030)
This calculation in relocate_section

      if (stub_entry->stub_type == ppc_stub_save_res)
relocation += (stub_sec->output_offset
       + stub_sec->output_section->vma
       + stub_sec->size - htab->sfpr->size
       - htab->sfpr->output_offset
       - htab->sfpr->output_section->vma);

to adjust from the original out-of-line save/restore function address
in sfpr to a copy at the end of stub_sec goes wrong when stub_sec is
padded, because the copy is no longer at the end of stub_sec.  The
solution is to pad before copying sfpr, so the copy is always at the
end of stub_sec.

* elf64-ppc.c (sfpr_define): Adjust for stub_sec size having
sfpr size added before defining alias symbols.
(ppc64_elf_build_stubs): Add stub section padding before
copying sfpr contents and defining save/restore alias symbols.

bfd/ChangeLog
bfd/elf64-ppc.c

index ad971fc20780024b8178c28d8069db3420e125f1..fac9b6204af782802d789ddad39127be2a77824f 100644 (file)
@@ -1,3 +1,10 @@
+2018-03-14  Alan Modra  <amodra@gmail.com>
+
+       * elf64-ppc.c (sfpr_define): Adjust for stub_sec size having
+       sfpr size added before defining alias symbols.
+       (ppc64_elf_build_stubs): Add stub section padding before
+       copying sfpr contents and defining save/restore alias symbols.
+
 2018-03-14  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/20882
index 44237bca6637452a012dad49adb444ca73bb86fe..889bdb0defb716691f5e69e5d3638741b7a703ee 100644 (file)
@@ -6660,7 +6660,7 @@ sfpr_define (struct bfd_link_info *info,
                {
                  s->root.type = bfd_link_hash_defined;
                  s->root.u.def.section = stub_sec;
-                 s->root.u.def.value = (stub_sec->size
+                 s->root.u.def.value = (stub_sec->size - htab->sfpr->size
                                         + h->elf.root.u.def.value);
                  s->ref_regular = 1;
                  s->def_regular = 1;
@@ -13247,20 +13247,7 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
 
   for (group = htab->group; group != NULL; group = group->next)
     if (group->needs_save_res)
-      {
-       stub_sec = group->stub_sec;
-       memcpy (stub_sec->contents + stub_sec->size, htab->sfpr->contents,
-               htab->sfpr->size);
-       if (htab->params->emit_stub_syms)
-         {
-           unsigned int i;
-
-           for (i = 0; i < ARRAY_SIZE (save_res_funcs); i++)
-             if (!sfpr_define (info, &save_res_funcs[i], stub_sec))
-               return FALSE;
-         }
-       stub_sec->size += htab->sfpr->size;
-      }
+      group->stub_sec->size += htab->sfpr->size;
 
   if (htab->relbrlt != NULL)
     htab->relbrlt->reloc_count = 0;
@@ -13273,6 +13260,22 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
          stub_sec->size = (stub_sec->size + (1 << align) - 1) & -(1 << align);
        }
 
+  for (group = htab->group; group != NULL; group = group->next)
+    if (group->needs_save_res)
+      {
+       stub_sec = group->stub_sec;
+       memcpy (stub_sec->contents + stub_sec->size - htab->sfpr->size,
+               htab->sfpr->contents, htab->sfpr->size);
+       if (htab->params->emit_stub_syms)
+         {
+           unsigned int i;
+
+           for (i = 0; i < ARRAY_SIZE (save_res_funcs); i++)
+             if (!sfpr_define (info, &save_res_funcs[i], stub_sec))
+               return FALSE;
+         }
+      }
+
   for (group = htab->group; group != NULL; group = group->next)
     if ((stub_sec = group->stub_sec) != NULL)
       {