This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: PR 11217, PowerPC64 automatic multiple TOC and __thread problems
- From: Alan Modra <amodra at gmail dot com>
- To: binutils at sourceware dot org
- Date: Wed, 27 Jan 2010 23:13:39 +1030
- Subject: Re: PR 11217, PowerPC64 automatic multiple TOC and __thread problems
- References: <20100125065049.GO8112@bubble.grove.modra.org>
On Mon, Jan 25, 2010 at 05:20:49PM +1030, Alan Modra wrote:
> gcc for all TLS models besides local exec uses @got relocs, and these
> generate GOT entries that are placed in the first TOC group. The net
> result is that functions using a TOC group other than the first can't
> access their GOT entries. ld ought to generate multiple GOT entries,
> one in each group
PowerPC64 ld does in fact do this (well more than one in each group).
The problem was that the GOT entry offset calculation assumed the
first TOC group. This patch (the relocate_section hunk) fixes that.
While I was looking at this, I noticed that it was possible for ld to
attempt a multi-toc partition with .toc in a given input file in one
TOC group with .got for the same file in another. That of course
doesn't work.
PR ld/11217
* elf64-ppc.c (struct ppc_link_hash_table): Add toc_bfd, toc_first_sec.
(ppc64_elf_setup_section_lists): Init them.
(ppc64_elf_next_toc_section): Don't partition multi-toc between .got
and .toc on the same input file.
(ppc64_elf_relocate_section): Correct GOT entry offset.
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.308
diff -u -p -r1.308 elf64-ppc.c
--- bfd/elf64-ppc.c 25 Jan 2010 06:47:15 -0000 1.308
+++ bfd/elf64-ppc.c 27 Jan 2010 12:12:00 -0000
@@ -3732,6 +3732,8 @@ struct ppc_link_hash_table
/* Temp used when calculating TOC pointers. */
bfd_vma toc_curr;
+ bfd *toc_bfd;
+ asection *toc_first_sec;
/* Highest input section id. */
int top_id;
@@ -9612,6 +9614,8 @@ ppc64_elf_setup_section_lists (bfd *outp
htab->stub_group[id].toc_off = TOC_BASE_OFF;
elf_gp (output_bfd) = htab->toc_curr = ppc64_elf_toc (output_bfd);
+ htab->toc_bfd = NULL;
+ htab->toc_first_sec = NULL;
/* We can't use output_bfd->section_count here to find the top output
section index as some sections may have been removed, and
@@ -9646,11 +9650,21 @@ ppc64_elf_next_toc_section (struct bfd_l
if (!htab->no_multi_toc)
{
- bfd_vma addr = isec->output_offset + isec->output_section->vma;
- bfd_vma off = addr - htab->toc_curr;
+ bfd_vma addr, off;
+ if (htab->toc_bfd != isec->owner)
+ {
+ htab->toc_bfd = isec->owner;
+ htab->toc_first_sec = isec;
+ }
+ addr = isec->output_offset + isec->output_section->vma;
+ off = addr - htab->toc_curr;
if (off + isec->size > 0x10000)
- htab->toc_curr = addr;
+ {
+ addr = (htab->toc_first_sec->output_offset
+ + htab->toc_first_sec->output_section->vma);
+ htab->toc_curr = addr;
+ }
elf_gp (isec->owner) = (htab->toc_curr
- elf_gp (isec->output_section->owner)
@@ -11745,10 +11759,8 @@ ppc64_elf_relocate_section (bfd *output_
if (off >= (bfd_vma) -2)
abort ();
- relocation = got->output_offset + off;
-
- /* TOC base (r2) is TOC start plus 0x8000. */
- addend = -TOC_BASE_OFF;
+ relocation = got->output_section->vma + got->output_offset + off;
+ addend = -(TOCstart + htab->stub_group[input_section->id].toc_off);
}
break;
--
Alan Modra
Australia Development Lab, IBM