[committed, PATCH] x86: Don't change r_type when performing TLS transitions

H.J. Lu hjl.tools@gmail.com
Wed Sep 6 11:55:00 GMT 2017


Don't change r_type when performing TLS transitions to avoid getting
the relocation type with ELF32_R_TYPE again.

	* elf32-i386.c (elf_i386_relocate_section): Don't change r_type
	when calling elf_i386_tls_transition.  Don't use ELF32_R_TYPE
	to get the relocation type again.
	* elf64-x86-64.c (elf_x86_64_relocate_section): Don't change
	r_type when calling elf_x86_64_tls_transition.  Don't use
	ELF32_R_TYPE to get the relocation type again.
---
 bfd/ChangeLog      |  9 +++++++++
 bfd/elf32-i386.c   | 29 +++++++++++++++--------------
 bfd/elf64-x86-64.c | 23 ++++++++++++-----------
 3 files changed, 36 insertions(+), 25 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 7e98b61c03..f323dfaa64 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,12 @@
+2017-09-06  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* elf32-i386.c (elf_i386_relocate_section): Don't change r_type
+	when calling elf_i386_tls_transition.  Don't use ELF32_R_TYPE
+	to get the relocation type again.
+	* elf64-x86-64.c (elf_x86_64_relocate_section): Don't change
+	r_type when calling elf_x86_64_tls_transition.  Don't use
+	ELF32_R_TYPE to get the relocation type again.
+
 2017-09-05  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* elf64-x86-64.c (elf_x86_64_convert_load_reloc): Properly set
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index ce9cf3a205..78a5dc4c68 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -2182,7 +2182,7 @@ elf_i386_relocate_section (bfd *output_bfd,
   relend = relocs + input_section->reloc_count;
   for (; rel < relend; wrel++, rel++)
     {
-      unsigned int r_type;
+      unsigned int r_type, r_type_tls;
       reloc_howto_type *howto;
       unsigned long r_symndx;
       struct elf_link_hash_entry *h;
@@ -3029,17 +3029,18 @@ disallow_got32:
 	  if (tls_type == GOT_TLS_IE)
 	    tls_type = GOT_TLS_IE_NEG;
 
+	   r_type_tls = r_type;
 	  if (! elf_i386_tls_transition (info, input_bfd,
 					 input_section, contents,
 					 symtab_hdr, sym_hashes,
-					 &r_type, tls_type, rel,
+					 &r_type_tls, tls_type, rel,
 					 relend, h, r_symndx, TRUE))
 	    return FALSE;
 
-	  if (r_type == R_386_TLS_LE_32)
+	  if (r_type_tls == R_386_TLS_LE_32)
 	    {
 	      BFD_ASSERT (! unresolved_reloc);
-	      if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD)
+	      if (r_type == R_386_TLS_GD)
 		{
 		  unsigned int type;
 		  bfd_vma roff;
@@ -3082,7 +3083,7 @@ disallow_got32:
 		  wrel++;
 		  continue;
 		}
-	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC)
+	      else if (r_type == R_386_TLS_GOTDESC)
 		{
 		  /* GDesc -> LE transition.
 		     It's originally something like:
@@ -3107,7 +3108,7 @@ disallow_got32:
 			      contents + roff);
 		  continue;
 		}
-	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL)
+	      else if (r_type == R_386_TLS_DESC_CALL)
 		{
 		  /* GDesc -> LE transition.
 		     It's originally:
@@ -3122,7 +3123,7 @@ disallow_got32:
 		  bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
 		  continue;
 		}
-	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_IE)
+	      else if (r_type == R_386_TLS_IE)
 		{
 		  unsigned int val;
 
@@ -3216,7 +3217,7 @@ disallow_got32:
 		    }
 		  else
 		    BFD_FAIL ();
-		  if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTIE)
+		  if (r_type == R_386_TLS_GOTIE)
 		    bfd_put_32 (output_bfd, -elf_i386_tpoff (info, relocation),
 				contents + rel->r_offset);
 		  else
@@ -3359,13 +3360,13 @@ disallow_got32:
 	  if (off >= (bfd_vma) -2
 	      && ! GOT_TLS_GDESC_P (tls_type))
 	    abort ();
-	  if (r_type == R_386_TLS_GOTDESC
-	      || r_type == R_386_TLS_DESC_CALL)
+	  if (r_type_tls == R_386_TLS_GOTDESC
+	      || r_type_tls == R_386_TLS_DESC_CALL)
 	    {
 	      relocation = htab->sgotplt_jump_table_size + offplt;
 	      unresolved_reloc = FALSE;
 	    }
-	  else if (r_type == ELF32_R_TYPE (rel->r_info))
+	  else if (r_type_tls == r_type)
 	    {
 	      bfd_vma g_o_t = htab->elf.sgotplt->output_section->vma
 			      + htab->elf.sgotplt->output_offset;
@@ -3378,7 +3379,7 @@ disallow_got32:
 		relocation += g_o_t;
 	      unresolved_reloc = FALSE;
 	    }
-	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD)
+	  else if (r_type == R_386_TLS_GD)
 	    {
 	      unsigned int val, type;
 	      bfd_vma roff;
@@ -3434,7 +3435,7 @@ disallow_got32:
 	      wrel++;
 	      continue;
 	    }
-	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC)
+	  else if (r_type == R_386_TLS_GOTDESC)
 	    {
 	      /* GDesc -> IE transition.
 		 It's originally something like:
@@ -3473,7 +3474,7 @@ disallow_got32:
 			  contents + roff);
 	      continue;
 	    }
-	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL)
+	  else if (r_type == R_386_TLS_DESC_CALL)
 	    {
 	      /* GDesc -> IE transition.
 		 It's originally:
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index bb471911a9..8807447c32 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -2511,7 +2511,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
   relend = relocs + input_section->reloc_count;
   for (; rel < relend; wrel++, rel++)
     {
-      unsigned int r_type;
+      unsigned int r_type, r_type_tls;
       reloc_howto_type *howto;
       unsigned long r_symndx;
       struct elf_link_hash_entry *h;
@@ -3413,20 +3413,21 @@ direct:
 	  else if (h != NULL)
 	    tls_type = elf_x86_hash_entry (h)->tls_type;
 
+	  r_type_tls = r_type;
 	  if (! elf_x86_64_tls_transition (info, input_bfd,
 					   input_section, contents,
 					   symtab_hdr, sym_hashes,
-					   &r_type, tls_type, rel,
+					   &r_type_tls, tls_type, rel,
 					   relend, h, r_symndx, TRUE))
 	    return FALSE;
 
-	  if (r_type == R_X86_64_TPOFF32)
+	  if (r_type_tls == R_X86_64_TPOFF32)
 	    {
 	      bfd_vma roff = rel->r_offset;
 
 	      BFD_ASSERT (! unresolved_reloc);
 
-	      if (ELF32_R_TYPE (rel->r_info) == R_X86_64_TLSGD)
+	      if (r_type == R_X86_64_TLSGD)
 		{
 		  /* GD->LE transition.  For 64bit, change
 			.byte 0x66; leaq foo@tlsgd(%rip), %rdi
@@ -3489,7 +3490,7 @@ direct:
 		  wrel++;
 		  continue;
 		}
-	      else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC)
+	      else if (r_type == R_X86_64_GOTPC32_TLSDESC)
 		{
 		  /* GDesc -> LE transition.
 		     It's originally something like:
@@ -3512,7 +3513,7 @@ direct:
 			      contents + roff);
 		  continue;
 		}
-	      else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL)
+	      else if (r_type == R_X86_64_TLSDESC_CALL)
 		{
 		  /* GDesc -> LE transition.
 		     It's originally:
@@ -3523,7 +3524,7 @@ direct:
 		  bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
 		  continue;
 		}
-	      else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_GOTTPOFF)
+	      else if (r_type == R_X86_64_GOTTPOFF)
 		{
 		  /* IE->LE transition:
 		     For 64bit, originally it can be one of:
@@ -3701,7 +3702,7 @@ direct:
 	  if (off >= (bfd_vma) -2
 	      && ! GOT_TLS_GDESC_P (tls_type))
 	    abort ();
-	  if (r_type == ELF32_R_TYPE (rel->r_info))
+	  if (r_type_tls == r_type)
 	    {
 	      if (r_type == R_X86_64_GOTPC32_TLSDESC
 		  || r_type == R_X86_64_TLSDESC_CALL)
@@ -3717,7 +3718,7 @@ direct:
 	    {
 	      bfd_vma roff = rel->r_offset;
 
-	      if (ELF32_R_TYPE (rel->r_info) == R_X86_64_TLSGD)
+	      if (r_type == R_X86_64_TLSGD)
 		{
 		  /* GD->IE transition.  For 64bit, change
 			.byte 0x66; leaq foo@tlsgd(%rip), %rdi
@@ -3786,7 +3787,7 @@ direct:
 		  wrel++;
 		  continue;
 		}
-	      else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC)
+	      else if (r_type == R_X86_64_GOTPC32_TLSDESC)
 		{
 		  /* GDesc -> IE transition.
 		     It's originally something like:
@@ -3811,7 +3812,7 @@ direct:
 			      contents + roff);
 		  continue;
 		}
-	      else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL)
+	      else if (r_type == R_X86_64_TLSDESC_CALL)
 		{
 		  /* GDesc -> IE transition.
 		     It's originally:
-- 
2.13.5



More information about the Binutils mailing list