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] gold: x86-64: Fix TLSDESC relaxation for x32


X32 TLSDESC sequences can be:

40 8d 05 00 00 00 00	rex lea	foo@TLSDESC(%rip), %reg
...
67 ff 10		call	*foo@TLSCALL(%eax)

or the same sequence as LP64:

48 8d 05 00 00 00 00	lea	foo@TLSDESC(%rip), %reg
...
ff 10			call	*foo@TLSCALL(%rax)

We need to support both sequences for x32.  For both GDesc -> IE/LE
transitions,

67 ff 10		call	*foo@TLSCALL(%eax)

should relaxed to

0f 1f 00		nopl	(%rax)

For GDesc -> LE transition,

40 8d 05 00 00 00 00	rex lea	foo@TLSDESC(%rip), %reg

should relaxed to

40 c7 c0 fc ff ff ff	rex movl $foo@tpoff, %reg

For GDesc -> IE transition,

40 8d 05 00 00 00 00	rex lea	foo@TLSDESC(%rip), %reg

should relaxed to

40 8b 05 00 00 00 00	rex movl foo@gottpoff(%rip), %eax

Tested with GCC 10 20200121 on Linux/x32.  OK for master?

Thanks.

H.J.
--
	PR gold/25426
	* x86_64.cc (Target_x86_64<size>::Relocate::tls_desc_gd_to_ie):
	For x32, relax "rex leal foo@tlsdesc(%rip), %reg" to
	"rex movl foo@gottpoff(%rip), %eax" and relax ""call *(%eax)"
	to "nopl (%rax)".
	(Target_x86_64<size>::Relocate::tls_desc_gd_to_le): For x32,
	relax "rex leal foo@tlsdesc(%rip), %reg" to
	"rex movl foo@tpoff, %eax" and relax "call *foo@tlscall(%eax)"
	to "nopl (%rax)".
	* testsuite/Makefile.am (tls_test_gnu2.o): Depend on
	gcctestdir/as.
	(tls_test_file2_gnu2.o): Likewise.
	(tls_test_c_gnu2.o): Likewise.
	* testsuite/Makefile.in: Regenerated.
---
 gold/testsuite/Makefile.am |  6 +--
 gold/testsuite/Makefile.in |  6 +--
 gold/x86_64.cc             | 78 ++++++++++++++++++++++++++++++--------
 3 files changed, 68 insertions(+), 22 deletions(-)

diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index ed1ea1755ac..397bf694000 100644
--- a/gold/testsuite/Makefile.am
+++ b/gold/testsuite/Makefile.am
@@ -1032,11 +1032,11 @@ if TLS_GNU2_DIALECT
 
 check_PROGRAMS += tls_shared_gnu2_gd_to_ie_test
 
-tls_test_gnu2.o: tls_test.cc
+tls_test_gnu2.o: tls_test.cc gcctestdir/as
 	$(CXXCOMPILE) -c -fpic -mtls-dialect=gnu2 -o $@ $<
-tls_test_file2_gnu2.o: tls_test_file2.cc
+tls_test_file2_gnu2.o: tls_test_file2.cc gcctestdir/as
 	$(CXXCOMPILE) -c -fpic -mtls-dialect=gnu2 -o $@ $<
-tls_test_c_gnu2.o: tls_test_c.c
+tls_test_c_gnu2.o: tls_test_c.c gcctestdir/as
 	$(COMPILE) -c -fpic -mtls-dialect=gnu2 $(TLS_TEST_C_CFLAGS) -o $@ $<
 tls_test_gnu2_shared2.so: tls_test_file2_gnu2.o gcctestdir/ld
 	$(CXXLINK) -shared tls_test_file2_gnu2.o
diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in
index 9533b0e20b2..d02311564e7 100644
--- a/gold/testsuite/Makefile.in
+++ b/gold/testsuite/Makefile.in
@@ -8213,11 +8213,11 @@ uninstall-am:
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@		tls_test_c_pic.o gcctestdir/ld
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@	$(CXXLINK) $(THREADFLAGS) -pie tls_test_main_pie.o tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o $(THREADLIBS)
 
-@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_test_gnu2.o: tls_test.cc
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_test_gnu2.o: tls_test.cc gcctestdir/as
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@	$(CXXCOMPILE) -c -fpic -mtls-dialect=gnu2 -o $@ $<
-@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_test_file2_gnu2.o: tls_test_file2.cc
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_test_file2_gnu2.o: tls_test_file2.cc gcctestdir/as
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@	$(CXXCOMPILE) -c -fpic -mtls-dialect=gnu2 -o $@ $<
-@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_test_c_gnu2.o: tls_test_c.c
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_test_c_gnu2.o: tls_test_c.c gcctestdir/as
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@	$(COMPILE) -c -fpic -mtls-dialect=gnu2 $(TLS_TEST_C_CFLAGS) -o $@ $<
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_test_gnu2_shared2.so: tls_test_file2_gnu2.o gcctestdir/ld
 @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@	$(CXXLINK) -shared tls_test_file2_gnu2.o
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index a65e2c55e9e..ee6c0c08572 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -5474,26 +5474,49 @@ Target_x86_64<size>::Relocate::tls_desc_gd_to_ie(
 {
   if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC)
     {
-      // leaq foo@tlsdesc(%rip), %rax
-      // ==> movq foo@gottpoff(%rip), %rax
+      // LP64: leaq foo@tlsdesc(%rip), %rax
+      //       ==> movq foo@gottpoff(%rip), %rax
+      // X32:  rex leal foo@tlsdesc(%rip), %eax
+      //       ==> rex movl foo@gottpoff(%rip), %eax
       tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3);
       tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4);
       tls::check_tls(relinfo, relnum, rela.get_r_offset(),
-		     view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05);
+		     ((view[-3] == 0x48
+		       || (size == 32 && view[-3] == 0x40))
+		      && view[-2] == 0x8d
+		      && view[-1] == 0x05));
       view[-2] = 0x8b;
       const elfcpp::Elf_Xword addend = rela.get_r_addend();
       Relocate_functions<size, false>::pcrela32(view, value, addend, address);
     }
   else
     {
-      // call *foo@tlscall(%rax)
-      // ==> nop; nop
+      // LP64: call *foo@tlscall(%rax)
+      //       ==> xchg %ax, %ax
+      // X32:  call *foo@tlscall(%eax)
+      //       ==> nopl (%rax)
       gold_assert(r_type == elfcpp::R_X86_64_TLSDESC_CALL);
       tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 2);
+      int prefix = 0;
+      if (size == 32 && view[0] == 0x67)
+	{
+	  tls::check_range(relinfo, relnum, rela.get_r_offset(),
+			   view_size, 3);
+	  prefix = 1;
+	}
       tls::check_tls(relinfo, relnum, rela.get_r_offset(),
-		     view[0] == 0xff && view[1] == 0x10);
-      view[0] = 0x66;
-      view[1] = 0x90;
+		     view[prefix] == 0xff && view[prefix + 1] == 0x10);
+      if (prefix)
+	{
+	  view[0] = 0x0f;
+	  view[1] = 0x1f;
+	  view[2] = 0x00;
+	}
+      else
+	{
+	  view[0] = 0x66;
+	  view[1] = 0x90;
+	}
     }
 }
 
@@ -5513,12 +5536,17 @@ Target_x86_64<size>::Relocate::tls_desc_gd_to_le(
 {
   if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC)
     {
-      // leaq foo@tlsdesc(%rip), %rax
-      // ==> movq foo@tpoff, %rax
+      // LP64: leaq foo@tlsdesc(%rip), %rax
+      //       ==> movq foo@tpoff, %rax
+      // X32:  rex leal foo@tlsdesc(%rip), %eax
+      //       ==> rex movl foo@tpoff, %eax
       tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3);
       tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4);
       tls::check_tls(relinfo, relnum, rela.get_r_offset(),
-		     view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05);
+		     ((view[-3] == 0x48
+		       || (size == 32 && view[-3] == 0x40))
+		      && view[-2] == 0x8d
+		      && view[-1] == 0x05));
       view[-2] = 0xc7;
       view[-1] = 0xc0;
       value -= tls_segment->memsz();
@@ -5526,14 +5554,32 @@ Target_x86_64<size>::Relocate::tls_desc_gd_to_le(
     }
   else
     {
-      // call *foo@tlscall(%rax)
-      // ==> nop; nop
+      // LP64: call *foo@tlscall(%rax)
+      //       ==> xchg %ax, %ax
+      // X32:  call *foo@tlscall(%eax)
+      //       ==> nopl (%rax)
       gold_assert(r_type == elfcpp::R_X86_64_TLSDESC_CALL);
       tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 2);
+      int prefix = 0;
+      if (size == 32 && view[0] == 0x67)
+	{
+	  tls::check_range(relinfo, relnum, rela.get_r_offset(),
+			   view_size, 3);
+	  prefix = 1;
+	}
       tls::check_tls(relinfo, relnum, rela.get_r_offset(),
-		     view[0] == 0xff && view[1] == 0x10);
-      view[0] = 0x66;
-      view[1] = 0x90;
+		     view[prefix] == 0xff && view[prefix + 1] == 0x10);
+      if (prefix)
+	{
+	  view[0] = 0x0f;
+	  view[1] = 0x1f;
+	  view[2] = 0x00;
+	}
+      else
+	{
+	  view[0] = 0x66;
+	  view[1] = 0x90;
+	}
     }
 }
 
-- 
2.24.1


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