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]

Re: PR 11217, PowerPC64 automatic multiple TOC and __thread problems


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


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