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]

internal error in ppc_elf_relocate_section


This fixes a counting mismatch between allocate_dynrelocs and
relocate_section regarding use of the GOT entry for local dynamic TLS
accesses.  If TLS accesses to a given symbol use the local dynamic model
and some other TLS model, and no other symbol used only local dynamic
accesses, then an abort in relocate_section was triggered due to not
allocating space for tlsld_got.

	* elf32-ppc.c (allocate_dynrelocs): Always use tlsld_got for
	TLS_LD even when symbol is used with other TLS reloc types.
	(ppc_elf_relocate_section): Bypass symbol checks when using tlsld_got.
	Leave addend zero on LD DTPMOD dynamic reloc.

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.247
diff -u -p -w -r1.247 elf32-ppc.c
--- bfd/elf32-ppc.c	10 Oct 2008 20:55:35 -0000	1.247
+++ bfd/elf32-ppc.c	20 Nov 2008 06:19:39 -0000
@@ -5024,6 +5024,9 @@ allocate_dynrelocs (struct elf_link_hash
   eh = (struct ppc_elf_link_hash_entry *) h;
   if (eh->elf.got.refcount > 0)
     {
+      bfd_boolean dyn;
+      unsigned int need;
+
       /* Make sure this symbol is output as a dynamic symbol.  */
       if (eh->elf.dynindx == -1
 	  && !eh->elf.forced_local
@@ -5033,21 +5036,19 @@ allocate_dynrelocs (struct elf_link_hash
 	    return FALSE;
 	}
 
-      if (eh->tls_mask == (TLS_TLS | TLS_LD)
-	  && !eh->elf.def_dynamic)
-	{
-	  /* If just an LD reloc, we'll just use htab->tlsld_got.offset.  */
-	  htab->tlsld_got.refcount += 1;
-	  eh->elf.got.offset = (bfd_vma) -1;
-	}
-      else
-	{
-	  bfd_boolean dyn;
-	  unsigned int need = 0;
+      need = 0;
 	  if ((eh->tls_mask & TLS_TLS) != 0)
 	    {
 	      if ((eh->tls_mask & TLS_LD) != 0)
+	    {
+	      if (!eh->elf.def_dynamic)
+		/* We'll just use htab->tlsld_got.offset.  This should
+		   always be the case.  It's a little odd if we have
+		   a local dynamic reloc against a non-local symbol.  */
+		htab->tlsld_got.refcount += 1;
+	      else
 		need += 8;
+	    }
 	      if ((eh->tls_mask & TLS_GD) != 0)
 		need += 8;
 	      if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
@@ -5057,6 +5058,10 @@ allocate_dynrelocs (struct elf_link_hash
 	    }
 	  else
 	    need += 4;
+      if (need == 0)
+	eh->elf.got.offset = (bfd_vma) -1;
+      else
+	{
 	  eh->elf.got.offset = allocate_got (htab, need);
 	  dyn = htab->elf.dynamic_sections_created;
 	  if ((info->shared
@@ -5066,7 +5071,8 @@ allocate_dynrelocs (struct elf_link_hash
 	    {
 	      /* All the entries we allocated need relocs.
 		 Except LD only needs one.  */
-	      if ((eh->tls_mask & TLS_LD) != 0)
+	      if ((eh->tls_mask & TLS_LD) != 0
+		  && eh->elf.def_dynamic)
 		need -= 4;
 	      htab->relgot->size += need * (sizeof (Elf32_External_Rela) / 4);
 	    }
@@ -5302,20 +5308,13 @@ ppc_elf_size_dynamic_sections (bfd *outp
       for (; local_got < end_local_got; ++local_got, ++lgot_masks)
 	if (*local_got > 0)
 	  {
-	    if (*lgot_masks == (TLS_TLS | TLS_LD))
-	      {
-		/* If just an LD reloc, we'll just use
-		   htab->tlsld_got.offset.  */
-		htab->tlsld_got.refcount += 1;
-		*local_got = (bfd_vma) -1;
-	      }
-	    else
-	      {
 		unsigned int need = 0;
 		if ((*lgot_masks & TLS_TLS) != 0)
 		  {
 		    if ((*lgot_masks & TLS_GD) != 0)
 		      need += 8;
+		if ((*lgot_masks & TLS_LD) != 0)
+		  htab->tlsld_got.refcount += 1;
 		    if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0)
 		      need += 4;
 		    if ((*lgot_masks & TLS_DTPREL) != 0)
@@ -5323,6 +5322,10 @@ ppc_elf_size_dynamic_sections (bfd *outp
 		  }
 		else
 		  need += 4;
+	    if (need == 0)
+	      *local_got = (bfd_vma) -1;
+	    else
+	      {
 		*local_got = allocate_got (htab, need);
 		if (info->shared)
 		  htab->relgot->size += (need
@@ -6587,7 +6590,8 @@ ppc_elf_relocate_section (bfd *output_bf
 
 		    /* Generate relocs for the dynamic linker.  */
 		    if ((info->shared || indx != 0)
-			&& (h == NULL
+			&& (offp == &htab->tlsld_got.offset
+			    || h == NULL
 			    || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
 			    || h->root.type != bfd_link_hash_undefweak))
 		      {
@@ -6618,7 +6622,7 @@ ppc_elf_relocate_section (bfd *output_bf
 			  outrel.r_info = ELF32_R_INFO (indx, R_PPC_RELATIVE);
 			else
 			  outrel.r_info = ELF32_R_INFO (indx, R_PPC_GLOB_DAT);
-			if (indx == 0)
+			if (indx == 0 && tls_ty != (TLS_TLS | TLS_LD))
 			  {
 			    outrel.r_addend += relocation;
 			    if (tls_ty & (TLS_GD | TLS_DTPREL | TLS_TPREL))

-- 
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]