This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

powerpc64 toc pointer value


Currently, it is a little difficult for a powerpc64 function to load
its toc pointer, assuming the toc pointer isn't available for some
reason.  One possibility is the following, which works after the .opd
section has been relocated.

	.global foo
	.type foo,@function
	.section .opd,"aw",@progbits
foo:
	.quad .L.foo,.TOC.@tocbase

	.text
.L.foo:
	mflr 0
	bcl 20,31,0f
0:
        mflr 12
	mtlr 0
        addis 12,12,foo-0b@ha
        addi 12,12,foo-0b@l
        ld 2,8(12)

This patch provides another solution by making .TOC., a symbol
mentioned in the ppc64 ABI, a real symbol.  The last three
instructions of the above function can now be replaced with:

	addis 2,12,.TOC.-0b@ha
	addi 2,2,.TOC.-0b@l

bfd/
	* 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.

Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.395
diff -u -p -r1.395 elf64-ppc.c
--- bfd/elf64-ppc.c	6 Nov 2012 03:44:51 -0000	1.395
+++ bfd/elf64-ppc.c	6 Nov 2012 05:16:49 -0000
@@ -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_in
 	}
     }
   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_
 		      }
 		  }
 	    }
+	  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: gas/config/tc-ppc.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ppc.c,v
retrieving revision 1.189
diff -u -p -r1.189 tc-ppc.c
--- gas/config/tc-ppc.c	6 Nov 2012 03:20:31 -0000	1.189
+++ gas/config/tc-ppc.c	6 Nov 2012 05:16:49 -0000
@@ -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 */
 
@@ -6850,7 +6867,17 @@ md_apply_fix (fixS *fixP, valueT *valP, 
      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: gas/config/tc-ppc.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ppc.h,v
retrieving revision 1.46
diff -u -p -r1.46 tc-ppc.h
--- gas/config/tc-ppc.h	1 Aug 2012 13:46:56 -0000	1.46
+++ gas/config/tc-ppc.h	6 Nov 2012 05:16:49 -0000
@@ -235,6 +235,9 @@ extern int ppc_fix_adjustable (struct fi
 #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)

-- 
Alan Modra
Australia Development Lab, IBM


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]