bfd/
authorAlan Modra <amodra@gmail.com>
Tue, 6 Nov 2012 05:18:03 +0000 (05:18 +0000)
committerAlan Modra <amodra@gmail.com>
Tue, 6 Nov 2012 05:18:03 +0000 (05:18 +0000)
* elf64-ppc.c (struct ppc_link_hash_table): Add dot_toc_dot.
(ppc64_elf_size_stubs): Lookup ".TOC.".
(ppc64_elf_relocate_section): Resolve special symbol ".TOC.".
gas/
* config/tc-ppc.c (ppc_elf_adjust_symtab): New function, split out..
(ppc_frob_file_before_adjust): ..from here.
(md_apply_fix): Set BSF_KEEP on .TOC. if not @tocbase.
* config/tc-ppc.h (ppc_elf_adjust_symtab): Declare.
(tc_adjust_symtab): Define.

bfd/ChangeLog
bfd/elf64-ppc.c
gas/ChangeLog
gas/config/tc-ppc.c
gas/config/tc-ppc.h

index cebc007944d8fcd67d592b2801a1b8d6afdd084b..ebec0d78dbf88c17bd91464e868e8b81b6b61a07 100644 (file)
@@ -1,3 +1,9 @@
+2012-11-06  Alan Modra  <amodra@gmail.com>
+
+       * elf64-ppc.c (struct ppc_link_hash_table): Add dot_toc_dot.
+       (ppc64_elf_size_stubs): Lookup ".TOC.".
+       (ppc64_elf_relocate_section): Resolve special symbol ".TOC.".
+
 2012-11-06  Alan Modra  <amodra@gmail.com>
 
        * elf64-ppc.c (maybe_strip_output): Heed SEC_KEEP.
        * reloc.c: Add new ENUM for BFD_RELOC_AVR_8_LO,
        BFD_RELOC_AVR_8_HI, BFD_RELOC_AVR_8_HHI.
        * bfd-in2.h: Regenerate.
-       * libbfd.h: Regenrate.
+       * libbfd.h: Regenerate.
        * elf32-avr.c (elf_avr_howto_table): Add entries for
        R_AVR_8_LO8, R_AVR_8_HI8, R_AVR_8_HHI8.
        (avr_reloc_map): Add RELOC mappings for R_AVR_8_LO8, R_AVR_8_HI8,
index 6bdc701d067aea426476e927fb89320b397d6fe2..94f3c4215127ae424fd27a46654c0547bf061e30 100644 (file)
@@ -3757,6 +3757,9 @@ struct ppc_link_hash_table
   struct ppc_link_hash_entry *tls_get_addr;
   struct ppc_link_hash_entry *tls_get_addr_fd;
 
+  /* The special .TOC. symbol.  */
+  struct ppc_link_hash_entry *dot_toc_dot;
+
   /* The size of reliplt used by got entry relocs.  */
   bfd_size_type got_reli_size;
 
@@ -11364,6 +11367,9 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
        }
     }
   htab->plt_thread_safe = plt_thread_safe;
+  htab->dot_toc_dot = ((struct ppc_link_hash_entry *)
+                      elf_link_hash_lookup (&htab->elf, ".TOC.",
+                                            FALSE, FALSE, TRUE));
   stubs_always_before_branch = group_size < 0;
   if (group_size < 0)
     stub_group_size = -group_size;
@@ -12362,6 +12368,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                      }
                  }
            }
+         if (h_elf == &htab->dot_toc_dot->elf)
+           {
+             relocation = (TOCstart
+                           + htab->stub_group[input_section->id].toc_off);
+             sec = bfd_abs_section_ptr;
+             unresolved_reloc = FALSE;
+           }
        }
       h = (struct ppc_link_hash_entry *) h_elf;
 
index 474b617c2ebd953b159b16ecccb6bf1980decf00..9ad252f6192d72a799709bb983c3bc1137fe3898 100644 (file)
@@ -1,3 +1,11 @@
+2012-11-06  Alan Modra  <amodra@gmail.com>
+
+       * config/tc-ppc.c (ppc_elf_adjust_symtab): New function, split out..
+       (ppc_frob_file_before_adjust): ..from here.
+       (md_apply_fix): Set BSF_KEEP on .TOC. if not @tocbase.
+       * config/tc-ppc.h (ppc_elf_adjust_symtab): Declare.
+       (tc_adjust_symtab): Define.
+
 2012-11-06  Alan Modra  <amodra@gmail.com>
 
        * config/tc-ppc.c (md_apply_fix): Fix xcoff build breakage from
index c72a8632ba16b82ef7210821f502c55650088b2e..1b12f57b8cb70d298792f18474ce94b56d7ec916 100644 (file)
@@ -2323,11 +2323,28 @@ ppc_frob_file_before_adjust (void)
       && toc_reloc_types != has_large_toc_reloc
       && bfd_section_size (stdoutput, toc) > 0x10000)
     as_warn (_("TOC section size exceeds 64k"));
+}
+
+/* .TOC. used in an opd entry as .TOC.@tocbase doesn't need to be
+   emitted.  Other uses of .TOC. will cause the symbol to be marked
+   with BSF_KEEP in md_apply_fix.  */
 
-  /* Don't emit .TOC. symbol.  */
-  symp = symbol_find (".TOC.");
-  if (symp != NULL)
-    symbol_remove (symp, &symbol_rootP, &symbol_lastP);
+void
+ppc_elf_adjust_symtab (void)
+{
+  if (ppc_obj64)
+    {
+      symbolS *symp;
+      symp = symbol_find (".TOC.");
+      if (symp != NULL)
+       {
+         asymbol *bsym = symbol_get_bfdsym (symp);
+         if ((bsym->flags & BSF_KEEP) == 0)
+           symbol_remove (symp, &symbol_rootP, &symbol_lastP);
+         else
+           S_SET_WEAK (symp);
+       }
+    }
 }
 #endif /* OBJ_ELF */
 \f
@@ -6850,7 +6867,17 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
      then the section contents are immaterial, so don't warn if they
      happen to overflow.  Leave such warnings to ld.  */
   if (!fixP->fx_done)
-    fixP->fx_no_overflow = 1;
+    {
+      fixP->fx_no_overflow = 1;
+
+      /* Arrange to emit .TOC. as a normal symbol if used in anything
+        but .TOC.@tocbase.  */
+      if (ppc_obj64
+         && fixP->fx_r_type != BFD_RELOC_PPC64_TOC
+         && fixP->fx_addsy != NULL
+         && strcmp (S_GET_NAME (fixP->fx_addsy), ".TOC.") == 0)
+       symbol_get_bfdsym (fixP->fx_addsy)->flags |= BSF_KEEP;
+    }
 #else
   if (fixP->fx_r_type != BFD_RELOC_PPC_TOC16)
     fixP->fx_addnumber = 0;
index e053c9c8277bd26204265f5139123710283d964a..3dd3f8190b3aa7a7929e72f97b13b77938a5bdb9 100644 (file)
@@ -235,6 +235,9 @@ extern int ppc_fix_adjustable (struct fix *);
 #define tc_frob_file_before_adjust ppc_frob_file_before_adjust
 extern void ppc_frob_file_before_adjust (void);
 
+#define tc_adjust_symtab() ppc_elf_adjust_symtab ()
+extern void ppc_elf_adjust_symtab (void);
+
 #endif /* OBJ_ELF */
 
 #if defined (OBJ_ELF) || defined (OBJ_XCOFF)