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]

PATCH: PR ld/2513: binutils incorrectly merges TLS relocations of different types


A GD->IE transition may use either of R_386_TLS_TPOFF and
R_386_TLS_TPOFF32. But if we have both R_386_TLS_IE and R_386_TLS_GD,
we can't share the same R_386_TLS_TPOFF since they require different
offsets. This patch handles this case. I will check it in after I
verify it with gcc and glibc.


H.J.
----
2006-04-08  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/2513
	* elf32-i386.c (GOT_TLS_MASK): New macro for tls_type.
	(GOT_TLS_IE_IE): Likewise.
	(GOT_TLS_IE_GD): Likewise.
	(GOT_TLS_IE_MASK): Likewise.
	(elf_i386_check_relocs): For global symbols, set GOT_TLS_IE_GD
	and GOT_TLS_IE_IE for R_386_TLS_GD and R_386_TLS_IE
	respectively.
	(allocate_dynrelocs): If both GOT_TLS_IE_IE and GOT_TLS_IE_GD
	are set, treat tls_type as GOT_TLS_IE_BOTH.
	(elf_i386_relocate_section): Likewise.

--- bfd/elf32-i386.c.tls	2006-03-16 12:37:42.000000000 -0800
+++ bfd/elf32-i386.c	2006-04-08 08:47:16.000000000 -0700
@@ -582,6 +582,10 @@ struct elf_i386_link_hash_entry
 #define GOT_TLS_IE_NEG	6
 #define GOT_TLS_IE_BOTH 7
 #define GOT_TLS_GDESC	8
+#define GOT_TLS_MASK	0x0f
+#define GOT_TLS_IE_IE	0x10
+#define GOT_TLS_IE_GD	0x20
+#define GOT_TLS_IE_MASK	0x30
 #define GOT_TLS_GD_BOTH_P(type)						\
   ((type) == (GOT_TLS_GD | GOT_TLS_GDESC))
 #define GOT_TLS_GD_P(type)						\
@@ -1007,12 +1011,25 @@ elf_i386_check_relocs (bfd *abfd,
 	      case R_386_TLS_IE_32:
 		if (ELF32_R_TYPE (rel->r_info) == r_type)
 		  tls_type = GOT_TLS_IE_NEG;
+		else if (h
+			 && ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD)
+		  /* If this is a GD->IE transition, we may use either
+		     of R_386_TLS_TPOFF and R_386_TLS_TPOFF32.  But if
+		     we may have both R_386_TLS_IE and R_386_TLS_GD,
+		     we can't share the same R_386_TLS_TPOFF since
+		     they require different offsets. So we remember
+		     it comes from R_386_TLS_GD.  */
+		  tls_type = GOT_TLS_IE | GOT_TLS_IE_GD;
 		else
-		  /* If this is a GD->IE transition, we may use either of
-		     R_386_TLS_TPOFF and R_386_TLS_TPOFF32.  */
 		  tls_type = GOT_TLS_IE;
 		break;
 	      case R_386_TLS_IE:
+		if (h)
+		  {
+		    /* We remember it comes from R_386_TLS_IE.  */
+		    tls_type = GOT_TLS_IE_POS | GOT_TLS_IE_IE;
+		    break;
+		  }
 	      case R_386_TLS_GOTIE:
 		tls_type = GOT_TLS_IE_POS; break;
 	      }
@@ -1052,7 +1069,8 @@ elf_i386_check_relocs (bfd *abfd,
 	      tls_type |= old_tls_type;
 	    /* If a TLS symbol is accessed using IE at least once,
 	       there is no point to use dynamic model for it.  */
-	    else if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN
+	    else if (old_tls_type != tls_type
+		     && old_tls_type != GOT_UNKNOWN
 		     && (! GOT_TLS_GD_ANY_P (old_tls_type)
 			 || (tls_type & GOT_TLS_IE) == 0))
 	      {
@@ -1682,6 +1700,14 @@ allocate_dynrelocs (struct elf_link_hash
       asection *s;
       bfd_boolean dyn;
       int tls_type = elf_i386_hash_entry(h)->tls_type;
+      
+      /* If we have both R_386_TLS_IE and R_386_TLS_GD, GOT_TLS_IE_BOTH
+	 should be used.  */
+      if ((tls_type & GOT_TLS_IE_MASK)
+	  == (GOT_TLS_IE_IE | GOT_TLS_IE_GD))
+	tls_type = GOT_TLS_IE_BOTH;
+      else
+	tls_type &= GOT_TLS_MASK;
 
       /* Make sure this symbol is output as a dynamic symbol.
 	 Undefined weak syms won't yet be marked as dynamic.  */
@@ -2685,6 +2711,13 @@ elf_i386_relocate_section (bfd *output_b
 	  else if (h != NULL)
 	    {
 	      tls_type = elf_i386_hash_entry(h)->tls_type;
+	      /* If we have both R_386_TLS_IE and R_386_TLS_GD,
+		 GOT_TLS_IE_BOTH should be used.  */
+	      if ((tls_type & GOT_TLS_IE_MASK)
+		  == (GOT_TLS_IE_IE | GOT_TLS_IE_GD))
+		tls_type = GOT_TLS_IE_BOTH;
+	      else
+		tls_type &= GOT_TLS_MASK;
 	      if (!info->shared && h->dynindx == -1 && (tls_type & GOT_TLS_IE))
 		r_type = R_386_TLS_LE_32;
 	    }


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