This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc 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/4918: ___tls_get_addr call requires @PLT for global-dynamic even without -fpic


On Mon, Aug 13, 2007 at 10:26:57AM -0700, H.J. Lu wrote:
> Is there a particular reason for x86 and x86-64 global-dynamic TLS
> model to require @PLT when calling __tls_get_addr when PIC isn't
> required? See
> 
> http://sources.redhat.com/bugzilla/show_bug.cgi?id=4918
> 
> Right now, gcc doesn't generate PLT when calling __tls_get_addr
> without -fpic. Assert in x86/x86-64 linkers fail because of it.
> The only thing I can think of is it is used to make sure that it is
> a call instruction.  I may have missed something. If not, I'd like to
> change it to check for R_X86_64_32/R_X86_64_PLT32 and call
> __tls_get_addr explicitly.
> 

This is the patch. I will check it in shortly.


H.J.
----
bfd/

2007-08-14  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/4918
	* elf32-i386.c (elf_i386_relocate_section): Allow R_386_PC32
	on ___tls_get_addr for GD->LE/LD->LE transitions when not
	building shared library.

	* elf64-x86-64.c (elf64_x86_64_relocate_section): Allow
	R_X86_64_PC32 on __tls_get_addr for GD->LE/LD->LE transitions
	when not building shared library.

ld/testsuite/

2007-08-14  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/4918
	* ld-i386/i386.exp (i386tests): Add tlsgd1 and tlsld1 tests.
	* ld-x86-64/x86-64.exp (x86_64tests): Likewise.

	* ld-i386/tlsgd1.dd: New file.
	* ld-i386/tlsgd1.s: Likewise.
	* ld-i386/tlsld1.dd: Likewise.
	* ld-i386/tlsld1.s: Likewise.
	* ld-x86-64/tlsgd1.dd: Likewise.
	* ld-x86-64/tlsgd1.s: Likewise.
	* ld-x86-64/tlsld1.dd: Likewise.
	* ld-x86-64/tlsld1.s: Likewise.

--- binutils/bfd/elf32-i386.c.tls	2007-08-14 12:10:15.000000000 -0700
+++ binutils/bfd/elf32-i386.c	2007-08-14 12:18:53.000000000 -0700
@@ -2672,6 +2672,8 @@ elf_i386_relocate_section (bfd *output_b
 		{
 		  unsigned int val, type;
 		  bfd_vma roff;
+		  unsigned long tls_r_symndx;
+		  struct elf_link_hash_entry *tls_h;
 
 		  /* GD->LE transition.  */
 		  BFD_ASSERT (rel->r_offset >= 2);
@@ -2682,7 +2684,16 @@ elf_i386_relocate_section (bfd *output_b
 					 contents + rel->r_offset + 4)
 			      == 0xe8);
 		  BFD_ASSERT (rel + 1 < relend);
-		  BFD_ASSERT (ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
+		  tls_r_symndx = ELF32_R_SYM (rel[1].r_info);
+		  BFD_ASSERT (tls_r_symndx >= symtab_hdr->sh_info);
+		  tls_h = sym_hashes[tls_r_symndx - symtab_hdr->sh_info];
+		  BFD_ASSERT (tls_h != NULL
+			      && tls_h->root.root.string != NULL
+			      && strcmp (tls_h->root.root.string,
+					 "___tls_get_addr") == 0);
+		  BFD_ASSERT ((! info->shared
+			       && ELF32_R_TYPE (rel[1].r_info) == R_386_PC32)
+			      || ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
 		  roff = rel->r_offset + 5;
 		  val = bfd_get_8 (input_bfd,
 				   contents + rel->r_offset - 1);
@@ -2727,7 +2738,7 @@ elf_i386_relocate_section (bfd *output_b
 		    }
 		  bfd_put_32 (output_bfd, tpoff (info, relocation),
 			      contents + roff);
-		  /* Skip R_386_PLT32.  */
+		  /* Skip R_386_PC32/R_386_PLT32.  */
 		  rel++;
 		  continue;
 		}
@@ -3211,6 +3222,8 @@ elf_i386_relocate_section (bfd *output_b
 	  if (! info->shared)
 	    {
 	      unsigned int val;
+	      unsigned long tls_r_symndx;
+	      struct elf_link_hash_entry *tls_h;
 
 	      /* LD->LE transition:
 		 Ensure it is:
@@ -3226,10 +3239,18 @@ elf_i386_relocate_section (bfd *output_b
 	      BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4)
 			  == 0xe8);
 	      BFD_ASSERT (rel + 1 < relend);
-	      BFD_ASSERT (ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
+	      tls_r_symndx = ELF32_R_SYM (rel[1].r_info);
+	      BFD_ASSERT (tls_r_symndx >= symtab_hdr->sh_info);
+	      tls_h = sym_hashes[tls_r_symndx - symtab_hdr->sh_info];
+	      BFD_ASSERT (tls_h != NULL
+			  && tls_h->root.root.string != NULL
+			  && strcmp (tls_h->root.root.string,
+				     "___tls_get_addr") == 0);
+	      BFD_ASSERT (ELF32_R_TYPE (rel[1].r_info) == R_386_PC32
+			  || ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
 	      memcpy (contents + rel->r_offset - 2,
 		      "\x65\xa1\0\0\0\0\x90\x8d\x74\x26", 11);
-	      /* Skip R_386_PLT32.  */
+	      /* Skip R_386_PC32/R_386_PLT32.  */
 	      rel++;
 	      continue;
 	    }
--- binutils/bfd/elf64-x86-64.c.tls	2007-08-14 12:10:15.000000000 -0700
+++ binutils/bfd/elf64-x86-64.c	2007-08-14 12:10:15.000000000 -0700
@@ -2547,10 +2547,12 @@ elf64_x86_64_relocate_section (bfd *outp
 		  unsigned int i;
 		  static unsigned char tlsgd[8]
 		    = { 0x66, 0x48, 0x8d, 0x3d, 0x66, 0x66, 0x48, 0xe8 };
+		  unsigned long tls_r_symndx;
+		  struct elf_link_hash_entry *tls_h;
 
 		  /* GD->LE transition.
 		     .byte 0x66; leaq foo@tlsgd(%rip), %rdi
-		     .word 0x6666; rex64; call __tls_get_addr@plt
+		     .word 0x6666; rex64; call __tls_get_addr
 		     Change it into:
 		     movq %fs:0, %rax
 		     leaq foo@tpoff(%rax), %rax */
@@ -2565,13 +2567,22 @@ elf64_x86_64_relocate_section (bfd *outp
 					   contents + rel->r_offset + 4 + i)
 				== tlsgd[i+4]);
 		  BFD_ASSERT (rel + 1 < relend);
-		  BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
+		  tls_r_symndx = ELF64_R_SYM (rel[1].r_info);
+		  BFD_ASSERT (tls_r_symndx >= symtab_hdr->sh_info);
+		  tls_h = sym_hashes[tls_r_symndx - symtab_hdr->sh_info];
+		  BFD_ASSERT (tls_h != NULL
+			      && tls_h->root.root.string != NULL
+			      && strcmp (tls_h->root.root.string,
+					 "__tls_get_addr") == 0);
+		  BFD_ASSERT ((! info->shared
+			       && ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PC32)
+			      || ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
 		  memcpy (contents + rel->r_offset - 4,
 			  "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0",
 			  16);
 		  bfd_put_32 (output_bfd, tpoff (info, relocation),
 			      contents + rel->r_offset + 8);
-		  /* Skip R_X86_64_PLT32.  */
+		  /* Skip R_X86_64_PC32/R_X86_64_PLT32.  */
 		  rel++;
 		  continue;
 		}
@@ -2939,9 +2950,12 @@ elf64_x86_64_relocate_section (bfd *outp
 	case R_X86_64_TLSLD:
 	  if (! info->shared)
 	    {
+	      unsigned long tls_r_symndx;
+	      struct elf_link_hash_entry *tls_h;
+
 	      /* LD->LE transition:
 		 Ensure it is:
-		 leaq foo@tlsld(%rip), %rdi; call __tls_get_addr@plt.
+		 leaq foo@tlsld(%rip), %rdi; call __tls_get_addr.
 		 We change it into:
 		 .word 0x6666; .byte 0x66; movl %fs:0, %rax.  */
 	      BFD_ASSERT (rel->r_offset >= 3);
@@ -2955,10 +2969,18 @@ elf64_x86_64_relocate_section (bfd *outp
 	      BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4)
 			  == 0xe8);
 	      BFD_ASSERT (rel + 1 < relend);
-	      BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
+	      tls_r_symndx = ELF64_R_SYM (rel[1].r_info);
+	      BFD_ASSERT (tls_r_symndx >= symtab_hdr->sh_info);
+	      tls_h = sym_hashes[tls_r_symndx - symtab_hdr->sh_info];
+	      BFD_ASSERT (tls_h != NULL
+			  && tls_h->root.root.string != NULL
+			  && strcmp (tls_h->root.root.string,
+				     "__tls_get_addr") == 0);
+	      BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PC32
+			  || ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
 	      memcpy (contents + rel->r_offset - 3,
 		      "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12);
-	      /* Skip R_X86_64_PLT32.  */
+	      /* Skip R_X86_64_PC32/R_X86_64_PLT32.  */
 	      rel++;
 	      continue;
 	    }
--- binutils/ld/testsuite/ld-i386/i386.exp.tls	2007-07-24 15:04:02.000000000 -0700
+++ binutils/ld/testsuite/ld-i386/i386.exp	2007-08-14 12:10:15.000000000 -0700
@@ -109,6 +109,12 @@ set i386tests {
      {emit-relocs.s} {{readelf --relocs emit-relocs.d}} "emit-relocs.so"}
     {"-z combreloc relocation sections" "-shared -melf_i386 -z combreloc"
      "--32" {combreloc.s} {{readelf -r combreloc.d}} "combreloc.so"}
+    {"TLS GD->LE transition" "-melf_i386"
+     "--32" {tlsgd1.s}
+     {{objdump -dwr tlsgd1.dd}} "tlsgd1"}
+    {"TLS LD->LE transition" "-melf_i386"
+     "--32" {tlsld1.s}
+     {{objdump -dwr tlsld1.dd}} "tlsld1"}
 }
 
 run_ld_link_tests $i386tests
--- binutils/ld/testsuite/ld-i386/tlsgd1.dd.tls	2007-08-14 12:10:15.000000000 -0700
+++ binutils/ld/testsuite/ld-i386/tlsgd1.dd	2007-08-14 12:10:15.000000000 -0700
@@ -0,0 +1,14 @@
+#source: tlsgd1.s
+#as: --32
+#ld: -melf_i386 tmpdir/tlsgd1
+#objdump: -drw
+#target: i?86-*-linux*
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+[ 	]*[a-f0-9]+:	65 a1 00 00 00 00    	mov    %gs:0x0,%eax
+[ 	]*[a-f0-9]+:	81 e8 04 00 00 00    	sub    \$0x4,%eax
+#pass
--- binutils/ld/testsuite/ld-i386/tlsgd1.s.tls	2007-08-14 12:10:15.000000000 -0700
+++ binutils/ld/testsuite/ld-i386/tlsgd1.s	2007-08-14 12:10:15.000000000 -0700
@@ -0,0 +1,12 @@
+	.text
+	.globl _start
+_start:
+	leal	foo@TLSGD(,%ebx,1), %eax
+	call	___tls_get_addr
+	.globl foo
+	.section	.tdata,"awT",@progbits
+	.align 4
+	.type	foo, @object
+	.size	foo, 4
+foo:
+	.long	100
--- binutils/ld/testsuite/ld-i386/tlsld1.dd.tls	2007-08-14 12:10:15.000000000 -0700
+++ binutils/ld/testsuite/ld-i386/tlsld1.dd	2007-08-14 12:10:15.000000000 -0700
@@ -0,0 +1,15 @@
+#source: tlsld1.s
+#as: --32
+#ld: -melf_i386 tmpdir/tlsld1
+#objdump: -drw
+#target: i?86-*-linux*
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+[ 	]*[a-f0-9]+:	65 a1 00 00 00 00    	mov    %gs:0x0,%eax
+[ 	]*[a-f0-9]+:	90                   	nop    
+[ 	]*[a-f0-9]+:	8d 74 26 00          	lea    0x0\(%esi\),%esi
+#pass
--- binutils/ld/testsuite/ld-i386/tlsld1.s.tls	2007-08-14 12:10:15.000000000 -0700
+++ binutils/ld/testsuite/ld-i386/tlsld1.s	2007-08-14 12:10:15.000000000 -0700
@@ -0,0 +1,12 @@
+	.text
+	.globl _start
+_start:
+	leal	foo@TLSLDM(%ebx), %eax
+	call	___tls_get_addr
+	.globl foo
+	.section	.tdata,"awT",@progbits
+	.align 4
+	.type	foo, @object
+	.size	foo, 4
+foo:
+	.long	100
--- binutils/ld/testsuite/ld-x86-64/tlsgd1.dd.tls	2007-08-14 12:10:15.000000000 -0700
+++ binutils/ld/testsuite/ld-x86-64/tlsgd1.dd	2007-08-14 12:10:15.000000000 -0700
@@ -0,0 +1,14 @@
+#source: tlsgd1.s
+#as: --64
+#ld: -melf_x86_64 tmpdir/tlsgd1
+#objdump: -drw
+#target: x86_64-*-linux*
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+[ 	]*[a-f0-9]+:	64 48 8b 04 25 00 00 00 00 	mov    %fs:0x0,%rax
+[ 	]*[a-f0-9]+:	48 8d 80 fc ff ff ff 	lea    -0x4\(%rax\),%rax
+#pass
--- binutils/ld/testsuite/ld-x86-64/tlsgd1.s.tls	2007-08-14 12:10:15.000000000 -0700
+++ binutils/ld/testsuite/ld-x86-64/tlsgd1.s	2007-08-14 12:10:15.000000000 -0700
@@ -0,0 +1,15 @@
+	.text
+	.globl _start
+_start:
+	.byte	0x66
+	leaq	foo@TLSGD(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr
+	.globl foo
+	.section	.tdata,"awT",@progbits
+	.align 4
+	.type	foo, @object
+	.size	foo, 4
+foo:
+	.long	100
--- binutils/ld/testsuite/ld-x86-64/tlsld1.dd.tls	2007-08-14 12:10:15.000000000 -0700
+++ binutils/ld/testsuite/ld-x86-64/tlsld1.dd	2007-08-14 12:10:15.000000000 -0700
@@ -0,0 +1,13 @@
+#source: tlsld1.s
+#as: --64
+#ld: -melf_x86_64 tmpdir/tlsld1
+#objdump: -drw
+#target: x86_64-*-linux*
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+[a-f0-9]+ <_start>:
+[ 	]*[a-f0-9]+:	66 66 66 64 48 8b 04 25 00 00 00 00 	mov    %fs:0x0,%rax
+#pass
--- binutils/ld/testsuite/ld-x86-64/tlsld1.s.tls	2007-08-14 12:10:15.000000000 -0700
+++ binutils/ld/testsuite/ld-x86-64/tlsld1.s	2007-08-14 12:10:15.000000000 -0700
@@ -0,0 +1,12 @@
+	.text
+	.globl _start
+_start:
+	leaq    foo@TLSLD(%rip), %rdi
+	call    __tls_get_addr
+	.globl foo
+	.section	.tdata,"awT",@progbits
+	.align 4
+	.type	foo, @object
+	.size	foo, 4
+foo:
+	.long	100
--- binutils/ld/testsuite/ld-x86-64/x86-64.exp.tls	2007-07-24 15:04:03.000000000 -0700
+++ binutils/ld/testsuite/ld-x86-64/x86-64.exp	2007-08-14 12:10:15.000000000 -0700
@@ -66,6 +66,12 @@ set x86_64tests {
     {"TLS in debug sections" "-melf_x86_64"
      "--64" {tlsg.s}
      {{objdump -sj.debug_foobar tlsg.sd}} "tlsg"}
+    {"TLS GD->LE transition" "-melf_x86_64"
+     "--64" {tlsgd1.s}
+     {{objdump -dwr tlsgd1.dd}} "tlsgd1"}
+    {"TLS LD->LE transition" "-melf_x86_64"
+     "--64" {tlsld1.s}
+     {{objdump -dwr tlsld1.dd}} "tlsld1"}
 }
 
 run_ld_link_tests $x86_64tests


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