PPC64: Allow .TOC. in linker script to override backend calculated value
authorAlan Modra <amodra@gmail.com>
Tue, 18 Aug 2015 07:13:18 +0000 (16:43 +0930)
committerAlan Modra <amodra@gmail.com>
Tue, 18 Aug 2015 07:13:18 +0000 (16:43 +0930)
bfd/
* elf64-ppc.c (ppc64_elf_func_desc_adjust): Don't redefine .TOC.
if already defined, and set linker_def.
(ppc64_elf_set_toc): Use .TOC. value if defined other than by
the backend.
ld/
* ldexp.c (exp_fold_tree_1): Clear linker_def on symbol assignment.

bfd/ChangeLog
bfd/elf64-ppc.c
ld/ChangeLog
ld/ldexp.c

index 09f765039be11901968e7ea24c92edaa5a0eba09..fb48800e23707ad22778967450e6c20774983fef 100644 (file)
@@ -1,3 +1,10 @@
+2015-08-18  Alan Modra  <amodra@gmail.com>
+
+       * elf64-ppc.c (ppc64_elf_func_desc_adjust): Don't redefine .TOC.
+       if already defined, and set linker_def.
+       (ppc64_elf_set_toc): Use .TOC. value if defined other than by
+       the backend.
+
 2015-08-14  Alan Modra  <amodra@gmail.com>
 
        PR ld/18759
index e153ee484b6544fdf79c5ad9c774db3cd9f77cab..4db534491f9cf882b99ba079b04eefaa7dea65c4 100644 (file)
@@ -6945,11 +6945,16 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
       _bfd_elf_link_hash_hide_symbol (info, htab->elf.hgot, TRUE);
       /* Make .TOC. defined so as to prevent it being made dynamic.
         The wrong value here is fixed later in ppc64_elf_set_toc.  */
+      if (!htab->elf.hgot->def_regular
+         || htab->elf.hgot->root.type != bfd_link_hash_defined)
+       {
+         htab->elf.hgot->root.type = bfd_link_hash_defined;
+         htab->elf.hgot->root.u.def.value = 0;
+         htab->elf.hgot->root.u.def.section = bfd_abs_section_ptr;
+         htab->elf.hgot->def_regular = 1;
+         htab->elf.hgot->root.linker_def = 1;
+       }
       htab->elf.hgot->type = STT_OBJECT;
-      htab->elf.hgot->root.type = bfd_link_hash_defined;
-      htab->elf.hgot->root.u.def.value = 0;
-      htab->elf.hgot->root.u.def.section = bfd_abs_section_ptr;
-      htab->elf.hgot->def_regular = 1;
       htab->elf.hgot->other = ((htab->elf.hgot->other & ~ELF_ST_VISIBILITY (-1))
                               | STV_HIDDEN);
     }
@@ -12539,6 +12544,34 @@ ppc64_elf_set_toc (struct bfd_link_info *info, bfd *obfd)
   asection *s;
   bfd_vma TOCstart, adjust;
 
+  if (info != NULL)
+    {
+      struct elf_link_hash_entry *h;
+      struct elf_link_hash_table *htab = elf_hash_table (info);
+
+      if (is_elf_hash_table (htab)
+         && htab->hgot != NULL)
+       h = htab->hgot;
+      else
+       {
+         h = elf_link_hash_lookup (htab, ".TOC.", FALSE, FALSE, TRUE);
+         if (is_elf_hash_table (htab))
+           htab->hgot = h;
+       }
+      if (h != NULL
+         && h->root.type == bfd_link_hash_defined
+         && !h->root.linker_def
+         && (!is_elf_hash_table (htab)
+             || h->def_regular))
+       {
+         TOCstart = (h->root.u.def.value - TOC_BASE_OFF
+                     + h->root.u.def.section->output_offset
+                     + h->root.u.def.section->output_section->vma);
+         _bfd_set_gp_value (obfd, TOCstart);
+         return TOCstart;
+       }
+    }
+
   /* The TOC consists of sections .got, .toc, .tocbss, .plt in that
      order.  The TOC starts where the first of these sections starts.  */
   s = bfd_get_section_by_name (obfd, ".got");
index 5f1094a37c4958b9d687366015e08e3306365929..62ad6f3f58a9945de6a78c7d6a4caf63737a4210 100644 (file)
@@ -1,3 +1,7 @@
+2015-08-18  Alan Modra  <amodra@gmail.com>
+
+       * ldexp.c (exp_fold_tree_1): Clear linker_def on symbol assignment.
+
 2015-08-06  Alan Modra  <amodra@gmail.com>
 
        * ldexp.c (align_dot_val): Delete.
index 1d4da9aadb4780f6e0077f1cc448117a0c281e4e..1140881015dd15e5fda34b702d9ffb3f351c4513 100644 (file)
@@ -1144,6 +1144,7 @@ exp_fold_tree_1 (etree_type *tree)
              h->type = bfd_link_hash_defined;
              h->u.def.value = expld.result.value;
              h->u.def.section = expld.result.section;
+             h->linker_def = 0;
              if (tree->type.node_class == etree_provide)
                tree->type.node_class = etree_provided;