aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2020-05-01 10:11:06 -0700
committerH.J. Lu <hjl.tools@gmail.com>2020-05-01 10:11:23 -0700
commitccf20d460f73c48f3334e1401558df342c77ac8a (patch)
tree80cf7c6bb978934ed96849825b7c0e8e6bd14721 /gold
parent6d520e36de0229eefe2f1671438cc8333a90b5e6 (diff)
downloadgdb-ccf20d460f73c48f3334e1401558df342c77ac8a.zip
gdb-ccf20d460f73c48f3334e1401558df342c77ac8a.tar.gz
gdb-ccf20d460f73c48f3334e1401558df342c77ac8a.tar.bz2
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 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.
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog17
-rw-r--r--gold/testsuite/Makefile.am6
-rw-r--r--gold/testsuite/Makefile.in6
-rw-r--r--gold/x86_64.cc76
4 files changed, 82 insertions, 23 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 0b7cb07..23fb070 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,5 +1,22 @@
2020-05-01 H.J. Lu <hongjiu.lu@intel.com>
+ 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.
+
+2020-05-01 H.J. Lu <hongjiu.lu@intel.com>
+
PR gold/25473
* x86_64.cc (Target_x86_64<size>::Relocate::tls_desc_gd_to_ie):
Properly check r8 - r15 in "lea foo@TLSDESC(%rip), %reg".
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index 6187554..ceba002 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 8d2f142..5fed355 100644
--- a/gold/testsuite/Makefile.in
+++ b/gold/testsuite/Makefile.in
@@ -8275,11 +8275,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 d4f1d6b..1d9d920 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -5472,12 +5472,15 @@ 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] & 0xfb) == 0x48
+ (((view[-3] & 0xfb) == 0x48
+ || (size == 32 && (view[-3] & 0xfb) == 0x40))
&& view[-2] == 0x8d
&& (view[-1] & 0xc7) == 0x05));
view[-2] = 0x8b;
@@ -5486,14 +5489,32 @@ Target_x86_64<size>::Relocate::tls_desc_gd_to_ie(
}
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,15 +5534,18 @@ 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] & 0xfb) == 0x48
+ (((view[-3] & 0xfb) == 0x48
+ || (size == 32 && (view[-3] & 0xfb) == 0x40))
&& view[-2] == 0x8d
&& (view[-1] & 0xc7) == 0x05));
- view[-3] = 0x48 | ((view[-3] >> 2) & 1);
+ view[-3] = (view[-3] & 0x48) | ((view[-3] >> 2) & 1);
view[-2] = 0xc7;
view[-1] = 0xc0 | ((view[-1] >> 3) & 7);
value -= tls_segment->memsz();
@@ -5529,14 +5553,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;
+ }
}
}