This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
powerpc64 toc pointer value
- From: Alan Modra <amodra at gmail dot com>
- To: binutils at sourceware dot org
- Date: Tue, 6 Nov 2012 15:47:20 +1030
- Subject: 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