This is the mail archive of the binutils@sources.redhat.com 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 tls sanity check


Implements a ld sanity check for PowerPC64 Linux, guarding against
"extern int x;" in one file and "__thread int x;" in another.  In the
process of doing this, I uncovered some problems with tls optimization
for the PowerOpen style tls scheme, so the following fixes those too.

bfd/ChangeLog
	* elf64-ppc.c (get_tls_mask): Add toc_symndx param, save toc
	reloc symbol index to it.  Don't allow gd syms in shared libs
	to be optimized.
	(ppc64_elf_tls_optimize): Adjust get_tls_mask call.
	(ppc64_elf_size_stubs): Likewise.
	(ppc64_elf_relocate_section): Check that tls relocs are only used
	with tls syms, and similarly for non-tls.  Correct symbol used
	when optimizing toc tls code.

ld/ChangeLog
	* ld-powerpc/tlsexetoc.d: Correct.
	* ld-powerpc/tlstoc.d: Correct.

Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.131
diff -u -p -r1.131 elf64-ppc.c
--- bfd/elf64-ppc.c	23 Sep 2003 00:40:49 -0000	1.131
+++ bfd/elf64-ppc.c	23 Oct 2003 07:35:05 -0000
@@ -4791,11 +4801,12 @@ get_sym_h (struct elf_link_hash_entry **
    type suitable for optimization, and 1 otherwise.  */
 
 static int
-get_tls_mask (char **tls_maskp, Elf_Internal_Sym **locsymsp,
+get_tls_mask (char **tls_maskp, unsigned long *toc_symndx,
+	      Elf_Internal_Sym **locsymsp,
 	      const Elf_Internal_Rela *rel, bfd *ibfd)
 {
   unsigned long r_symndx;
-  unsigned int next_r;
+  int next_r;
   struct elf_link_hash_entry *h;
   Elf_Internal_Sym *sym;
   asection *sec;
@@ -4824,17 +4835,14 @@ get_tls_mask (char **tls_maskp, Elf_Inte
   next_r = ppc64_elf_section_data (sec)->t_symndx[off / 8 + 1];
   if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd))
     return 0;
-  if (h == NULL
-      || h->root.type == bfd_link_hash_defined
-      || h->root.type == bfd_link_hash_defweak)
-    {
-      if (next_r == (unsigned) -1)
-	return 2;
-      if (next_r == (unsigned) -2
-	  && (h == NULL
-	      || !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)))
-	return 3;
-    }
+  if (toc_symndx != NULL)
+    *toc_symndx = r_symndx;
+  if ((h == NULL
+       || ((h->root.type == bfd_link_hash_defined
+	    || h->root.type == bfd_link_hash_defweak)
+	   && !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)))
+      && (next_r == -1 || next_r == -2))
+    return 1 - next_r;
   return 1;
 }
 
@@ -5318,7 +5326,7 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIB
 			    char *toc_tls;
 			    int retval;
 
-			    retval = get_tls_mask (&toc_tls, &locsyms,
+			    retval = get_tls_mask (&toc_tls, NULL, &locsyms,
 						   rel - 1, ibfd);
 			    if (retval == 0)
 			      goto err_free_rel;
@@ -6902,7 +6910,7 @@ ppc64_elf_size_stubs (bfd *output_bfd,
 		      /* Get tls info.  */
 		      char *tls_mask;
 
-		      if (!get_tls_mask (&tls_mask, &local_syms,
+		      if (!get_tls_mask (&tls_mask, NULL, &local_syms,
 					 irela - 1, input_bfd))
 			goto error_ret_free_internal;
 		      if (*tls_mask != 0)
@@ -7308,8 +7316,9 @@ ppc64_elf_relocate_section (bfd *output_
       struct elf_link_hash_entry *h;
       struct elf_link_hash_entry *fdh;
       const char *sym_name;
-      unsigned long r_symndx;
+      unsigned long r_symndx, toc_symndx;
       char tls_mask, tls_gd, tls_type;
+      char sym_type;
       bfd_vma relocation;
       bfd_boolean unresolved_reloc;
       bfd_boolean warned;
@@ -7343,6 +7352,7 @@ ppc64_elf_relocate_section (bfd *output_
 	  sym = local_syms + r_symndx;
 	  sec = local_sections[r_symndx];
 	  sym_name = bfd_elf_local_sym_name (input_bfd, sym);
+	  sym_type = ELF64_ST_TYPE (sym->st_info);
 	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
 	  if (elf_section_data (sec) != NULL)
 	    {
@@ -7360,6 +7370,7 @@ ppc64_elf_relocate_section (bfd *output_
 				   unresolved_reloc, info,
 				   warned);
 	  sym_name = h->root.root.string;
+	  sym_type = h->type;
 	}
 
       /* TLS optimizations.  Replace instruction sequences and relocs
@@ -7368,6 +7379,7 @@ ppc64_elf_relocate_section (bfd *output_
 	 for the final instruction stream.  */
       tls_mask = 0;
       tls_gd = 0;
+      toc_symndx = 0;
       if (IS_PPC64_TLS_RELOC (r_type))
 	{
 	  if (h != NULL)
@@ -7378,6 +7390,42 @@ ppc64_elf_relocate_section (bfd *output_
 	      lgot_masks = (char *) (local_got_ents + symtab_hdr->sh_info);
 	      tls_mask = lgot_masks[r_symndx];
 	    }
+	  if (tls_mask == 0 && r_type == R_PPC64_TLS)
+	    {
+	      /* Check for toc tls entries.  */
+	      char *toc_tls;
+
+	      if (!get_tls_mask (&toc_tls, &toc_symndx, &local_syms,
+				 rel, input_bfd))
+		return FALSE;
+
+	      if (toc_tls)
+		tls_mask = *toc_tls;
+	    }
+	}
+
+      /* Check that tls relocs are used with tls syms, and non-tls
+	 relocs are used with non-tls syms.  */
+      if (r_symndx != 0
+	  && r_type != R_PPC64_NONE
+	  && (h == NULL
+	      || h->root.type == bfd_link_hash_defined
+	      || h->root.type == bfd_link_hash_defweak)
+	  && IS_PPC64_TLS_RELOC (r_type) != (sym_type == STT_TLS))
+	{
+	  if (r_type == R_PPC64_TLS && tls_mask != 0)
+	    /* R_PPC64_TLS is OK against a symbol in the TOC.  */
+	    ;
+	  else
+	    (*_bfd_error_handler)
+	      (sym_type == STT_TLS
+	       ? _("%s(%s+0x%lx): %s used with TLS symbol %s")
+	       : _("%s(%s+0x%lx): %s used with non-TLS symbol %s"),
+	       bfd_archive_filename (input_bfd),
+	       input_section->name,
+	       (long) rel->r_offset,
+	       ppc64_elf_howto_table[r_type]->name,
+	       sym_name);
 	}
 
       /* Ensure reloc mapping code below stays sane.  */
@@ -7392,6 +7440,7 @@ ppc64_elf_relocate_section (bfd *output_
 	  || (R_PPC64_GOT_TLSLD16_HI & 3) != (R_PPC64_GOT_TPREL16_HI & 3)
 	  || (R_PPC64_GOT_TLSLD16_HA & 3) != (R_PPC64_GOT_TPREL16_HA & 3))
 	abort ();
+
       switch (r_type)
 	{
 	default:
@@ -7406,7 +7455,8 @@ ppc64_elf_relocate_section (bfd *output_
 	    char *toc_tls;
 	    int retval;
 
-	    retval = get_tls_mask (&toc_tls, &local_syms, rel, input_bfd);
+	    retval = get_tls_mask (&toc_tls, &toc_symndx, &local_syms,
+				   rel, input_bfd);
 	    if (retval == 0)
 	      return FALSE;
 
@@ -7451,22 +7501,20 @@ ppc64_elf_relocate_section (bfd *output_
 	      insn |= 0x3c0d0000;	/* addis 0,13,0 */
 	      bfd_put_32 (output_bfd, insn, contents + rel->r_offset - 2);
 	      r_type = R_PPC64_TPREL16_HA;
-	      rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+	      if (toc_symndx != 0)
+		{
+		  rel->r_info = ELF64_R_INFO (toc_symndx, r_type);
+		  /* We changed the symbol.  Start over in order to
+		     get h, sym, sec etc. right.  */
+		  rel--;
+		  continue;
+		}
+	      else
+		rel->r_info = ELF64_R_INFO (r_symndx, r_type);
 	    }
 	  break;
 
 	case R_PPC64_TLS:
-	  if (tls_mask == 0)
-	    {
-	      /* Check for toc tls entries.  */
-	      char *toc_tls;
-
-	      if (!get_tls_mask (&toc_tls, &local_syms, rel, input_bfd))
-		return FALSE;
-
-	      if (toc_tls)
-		tls_mask = *toc_tls;
-	    }
 	  if (tls_mask != 0
 	      && (tls_mask & TLS_TPREL) == 0)
 	    {
@@ -7502,11 +7550,20 @@ ppc64_elf_relocate_section (bfd *output_
 		abort ();
 	      insn |= rtra;
 	      bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
-	      r_type = R_PPC64_TPREL16_LO;
-	      rel->r_info = ELF64_R_INFO (r_symndx, r_type);
 	      /* Was PPC64_TLS which sits on insn boundary, now
 		 PPC64_TPREL16_LO which is at insn+2.  */
 	      rel->r_offset += 2;
+	      r_type = R_PPC64_TPREL16_LO;
+	      if (toc_symndx != 0)
+		{
+		  rel->r_info = ELF64_R_INFO (toc_symndx, r_type);
+		  /* We changed the symbol.  Start over in order to
+		     get h, sym, sec etc. right.  */
+		  rel--;
+		  continue;
+		}
+	      else
+		rel->r_info = ELF64_R_INFO (r_symndx, r_type);
 	    }
 	  break;
 
@@ -7605,6 +7662,8 @@ ppc64_elf_relocate_section (bfd *output_
 			  rel->r_addend = htab->tls_sec->vma + DTP_OFFSET;
 			  rel[1].r_addend = htab->tls_sec->vma + DTP_OFFSET;
 			}
+		      else if (toc_symndx != 0)
+			r_symndx = toc_symndx;
 		      r_type = R_PPC64_TPREL16_HA;
 		      rel->r_info = ELF64_R_INFO (r_symndx, r_type);
 		      rel[1].r_info = ELF64_R_INFO (r_symndx,
@@ -7621,10 +7680,10 @@ ppc64_elf_relocate_section (bfd *output_
 		  bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - 2);
 		  bfd_put_32 (output_bfd, insn2, contents + offset);
 		  bfd_put_32 (output_bfd, insn3, contents + offset + 4);
-		  if (tls_gd == 0)
+		  if (tls_gd == 0 || toc_symndx != 0)
 		    {
-		      /* We changed the symbol on an LD reloc.  Start over
-			 in order to get h, sym, sec etc. right.  */
+		      /* We changed the symbol.  Start over in order
+			 to get h, sym, sec etc. right.  */
 		      rel--;
 		      continue;
 		    }
Index: ld/testsuite/ld-powerpc/tlsexetoc.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-powerpc/tlsexetoc.d,v
retrieving revision 1.4
diff -u -p -r1.4 tlsexetoc.d
--- ld/testsuite/ld-powerpc/tlsexetoc.d	16 Jun 2003 10:51:07 -0000	1.4
+++ ld/testsuite/ld-powerpc/tlsexetoc.d	23 Oct 2003 07:35:34 -0000
@@ -18,15 +18,15 @@ Disassembly of section \.text:
 .*	4e 80 04 20 	bctr
 
 .* <_start>:
-.*	e8 62 80 08 	ld	r3,-32760\(r2\)
-.*	60 00 00 00 	nop
-.*	7c 63 6a 14 	add	r3,r3,r13
+.*	38 62 80 08 	addi	r3,r2,-32760
+.*	4b ff ff e1 	bl	.*
+.*	e8 41 00 28 	ld	r2,40\(r1\)
 .*	38 62 80 18 	addi	r3,r2,-32744
 .*	4b ff ff d5 	bl	.*
 .*	e8 41 00 28 	ld	r2,40\(r1\)
 .*	3c 6d 00 00 	addis	r3,r13,0
 .*	60 00 00 00 	nop
-.*	38 63 91 90 	addi	r3,r3,-28272
+.*	38 63 90 38 	addi	r3,r3,-28616
 .*	3c 6d 00 00 	addis	r3,r13,0
 .*	60 00 00 00 	nop
 .*	38 63 10 00 	addi	r3,r3,4096
@@ -36,7 +36,7 @@ Disassembly of section \.text:
 .*	e9 22 80 48 	ld	r9,-32696\(r2\)
 .*	7d 49 18 2a 	ldx	r10,r9,r3
 .*	3d 2d 00 00 	addis	r9,r13,0
-.*	a1 49 91 d8 	lhz	r10,-28200\(r9\)
+.*	a1 49 90 58 	lhz	r10,-28584\(r9\)
 .*	89 4d 90 60 	lbz	r10,-28576\(r13\)
 .*	3d 2d 00 00 	addis	r9,r13,0
 .*	99 49 90 68 	stb	r10,-28568\(r9\)
Index: ld/testsuite/ld-powerpc/tlstoc.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-powerpc/tlstoc.d,v
retrieving revision 1.2
diff -u -p -r1.2 tlstoc.d
--- ld/testsuite/ld-powerpc/tlstoc.d	16 Jun 2003 10:51:07 -0000	1.2
+++ ld/testsuite/ld-powerpc/tlstoc.d	23 Oct 2003 07:35:34 -0000
@@ -15,13 +15,13 @@ Disassembly of section \.text:
 .* <_start>:
 .*	3c 6d 00 00 	addis	r3,r13,0
 .*	60 00 00 00 	nop
-.*	38 63 90 58 	addi	r3,r3,-28584
+.*	38 63 90 40 	addi	r3,r3,-28608
 .*	3c 6d 00 00 	addis	r3,r13,0
 .*	60 00 00 00 	nop
 .*	38 63 10 00 	addi	r3,r3,4096
 .*	3c 6d 00 00 	addis	r3,r13,0
 .*	60 00 00 00 	nop
-.*	38 63 90 58 	addi	r3,r3,-28584
+.*	38 63 90 48 	addi	r3,r3,-28600
 .*	3c 6d 00 00 	addis	r3,r13,0
 .*	60 00 00 00 	nop
 .*	38 63 10 00 	addi	r3,r3,4096
@@ -31,7 +31,7 @@ Disassembly of section \.text:
 .*	e9 22 80 40 	ld	r9,-32704\(r2\)
 .*	7d 49 18 2a 	ldx	r10,r9,r3
 .*	3d 2d 00 00 	addis	r9,r13,0
-.*	a1 49 90 a0 	lhz	r10,-28512\(r9\)
+.*	a1 49 90 68 	lhz	r10,-28568\(r9\)
 .*	89 4d 90 70 	lbz	r10,-28560\(r13\)
 .*	3d 2d 00 00 	addis	r9,r13,0
 .*	99 49 90 78 	stb	r10,-28552\(r9\)

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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