[PATCH] x86: Add tls check in gas

Cui, Lili lili.cui@intel.com
Tue Aug 27 06:07:10 GMT 2024


Hi,

This patch is to add tls check in gas, and the following two changes are special:
1. Removed BFD_RELOC_386_TLS_LE_32 kmov test, as the linker does not change it.
2. Added -mtls-check=no to gas reloc32/reloc64 test files as there are some illegal instructions. I'm not sure if we should remove them.

Thanks,
Lili.

Assembler shouldn't accept invalid TLS instructions, TLS relocations
can only be used with specific instructions as specified in TLS psABI
and linker issues an error when TLS relocations are used with wrong
instructions. It is inconvenient for gcc to rely on linker to report
errors, adding tls check in the assembler stage so that gcc can know
tls errors earlier.

gas/ChangeLog:

        PR gas/32022
        * config.in: Regenerate.
        * config/tc-i386.c (_BFD_MAKE_TABLE_bfd_reloc_code_real): New.
        (x86_check_tls_relocation): Added a new function to check tls relocation.
        (i386_assemble): Handle x86_check_tls_relocation.
        (OPTION_MTLS_CHECK): Added a new option to contrl tls check.
        (struct option): Ditto.
        (md_parse_option): Ditto.
        (md_show_usage): Ditto.
        * configure: Added a new option to check tls relocation by default.
        * configure.ac: Ditto.
        * doc/c-i386.texi: Ditto.
        * testsuite/gas/i386/i386.exp: Added new tests.
        * testsuite/gas/i386/ilp32/ilp32.exp: Ditto.
        * testsuite/gas/i386/ilp32/reloc64.d: Disable tls check for it.
        * testsuite/gas/i386/inval-tls.l: Added more test cases.
        * testsuite/gas/i386/inval-tls.s: Ditto.
        * testsuite/gas/i386/reloc32.d: Disable tls check for it.
        * testsuite/gas/i386/reloc64.d: Ditto.
        * testsuite/gas/i386/x86-64-inval-tls.l: Added more test cases.
        * testsuite/gas/i386/x86-64-inval-tls.s: Ditto.
        * testsuite/gas/i386/x86-64.exp: Added new tests.
        * testsuite/gas/i386/tls.d: New test.
        * testsuite/gas/i386/tls.s: Ditto.
        * testsuite/gas/i386/x86-64-tls.d: Ditto.
        * testsuite/gas/i386/x86-64-tls.s: Ditto.

ld/ChangeLog:

        PR gas/32022
        * testsuite/ld-i386/tlsgdesc1.d: Disable tls check for it.
        * testsuite/ld-i386/tlsgdesc2.d: Ditto.
        * testsuite/ld-i386/tlsie2.d: Ditto.
        * testsuite/ld-i386/tlsie3.d: Ditto.
        * testsuite/ld-i386/tlsie4.d: Ditto.
        * testsuite/ld-i386/tlsie5.d: Ditto.
        * testsuite/ld-x86-64/tlsdesc3.d: Ditto.
        * testsuite/ld-x86-64/tlsdesc4.d: Ditto.
        * testsuite/ld-x86-64/tlsie2.d: Ditto.
        * testsuite/ld-x86-64/tlsie3.d: Ditto.
        * testsuite/ld-x86-64/tlsie5.d: Ditto.
---
 gas/config.in                             |   3 +
 gas/config/tc-i386.c                      | 154 ++++++++++++++++++++--
 gas/configure                             |  26 +++-
 gas/configure.ac                          |  18 +++
 gas/doc/c-i386.texi                       |  10 ++
 gas/testsuite/gas/i386/i386.exp           |   3 +-
 gas/testsuite/gas/i386/ilp32/ilp32.exp    |   2 +-
 gas/testsuite/gas/i386/ilp32/reloc64.d    |   2 +-
 gas/testsuite/gas/i386/inval-tls.l        |  10 +-
 gas/testsuite/gas/i386/inval-tls.s        |  22 +++-
 gas/testsuite/gas/i386/reloc32.d          |   2 +-
 gas/testsuite/gas/i386/reloc64.d          |   2 +-
 gas/testsuite/gas/i386/tls.d              |  28 ++++
 gas/testsuite/gas/i386/tls.s              |  36 +++++
 gas/testsuite/gas/i386/x86-64-inval-tls.l |  10 +-
 gas/testsuite/gas/i386/x86-64-inval-tls.s |  16 +++
 gas/testsuite/gas/i386/x86-64-tls.d       |  29 ++++
 gas/testsuite/gas/i386/x86-64-tls.s       |  31 +++++
 gas/testsuite/gas/i386/x86-64.exp         |   3 +-
 ld/testsuite/ld-i386/tlsgdesc1.d          |   2 +-
 ld/testsuite/ld-i386/tlsgdesc2.d          |   2 +-
 ld/testsuite/ld-i386/tlsie2.d             |   2 +-
 ld/testsuite/ld-i386/tlsie3.d             |   2 +-
 ld/testsuite/ld-i386/tlsie4.d             |   2 +-
 ld/testsuite/ld-i386/tlsie5.d             |   2 +-
 ld/testsuite/ld-x86-64/tlsdesc3.d         |   2 +-
 ld/testsuite/ld-x86-64/tlsdesc4.d         |   2 +-
 ld/testsuite/ld-x86-64/tlsie2.d           |   2 +-
 ld/testsuite/ld-x86-64/tlsie3.d           |   2 +-
 ld/testsuite/ld-x86-64/tlsie5.d           |   2 +-
 30 files changed, 391 insertions(+), 38 deletions(-)
 create mode 100644 gas/testsuite/gas/i386/tls.d
 create mode 100644 gas/testsuite/gas/i386/tls.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-tls.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-tls.s

diff --git a/gas/config.in b/gas/config.in
index a1f83499332..97d0efc393f 100644
--- a/gas/config.in
+++ b/gas/config.in
@@ -60,6 +60,9 @@
 /* Define default value for RISC-V -mpriv-spec */
 #undef DEFAULT_RISCV_PRIV_SPEC
 
+/* Define to 1 if you want to check tls relocation by default. */
+#undef DEFAULT_TLS_CHECK
+
 /* Define to 1 if you want to generate GNU x86 used ISA and feature properties
    by default. */
 #undef DEFAULT_X86_USED_NOTE
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index ad68ba9322d..e2db1c4c68f 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -38,6 +38,9 @@
 #include "opcodes/i386-mnem.h"
 #include <limits.h>
 
+#define _BFD_MAKE_TABLE_bfd_reloc_code_real
+#include "bfd/libbfd.h"
+
 #ifndef INFER_ADDR_PREFIX
 #define INFER_ADDR_PREFIX 1
 #endif
@@ -717,6 +720,9 @@ lfence_before_ret;
 static int generate_relax_relocations
   = DEFAULT_GENERATE_X86_RELAX_RELOCATIONS;
 
+/* 1 if the assembler should check tls relocation.  */
+static int tls_check = DEFAULT_TLS_CHECK;
+
 static enum check_kind
   {
     check_none = 0,
@@ -6229,6 +6235,108 @@ static INLINE bool may_need_pass2 (const insn_template *t)
 	       && (t->base_opcode | 8) == 0x2c);
 }
 
+static bool x86_check_tls_relocation (unsigned int r_type)
+{
+  switch (r_type)
+    {
+    case BFD_RELOC_386_TLS_GOTDESC:
+      /* Check transition from GDesc access model:
+	 leal x@tlsdesc(%ebx), %eax
+	 call *x@tlsdesc(%eax)
+       */
+      if (i.tm.mnem_off == MN_call)
+	return true;
+      /* fall through */
+    case BFD_RELOC_386_TLS_GD:
+      /*  Check transition from GD access model:
+	  leal foo@tlsgd(,%ebx,1), %eax
+       */
+    case BFD_RELOC_386_TLS_LDM:
+      /*  Check transition from LDM access model:
+	  leal foo@tlsldm(%ebx), %eax
+       */
+      if (i.tm.mnem_off == MN_lea)
+	return true;
+      break;
+    case BFD_RELOC_X86_64_TLSGD:
+      /* Check transition from GD access model:
+	 leaq foo@tlsgd(%rip), %rdi
+      */
+    case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+      /* Check transition from GOTPC32 TLSDESC access model:
+
+	 --- LP64 mode ---
+	 leaq x@tlsdesc(%rip), %rax
+	 call *x@tlsdesc(%rax)
+
+	 --- X32 mode ---
+	 rex leal x@tlsdesc(%rip), %eax
+	 call *x@tlsdesc(%eax)
+       */
+      if (i.tm.mnem_off == MN_call)
+	return true;
+      /* fall through */
+    case BFD_RELOC_X86_64_TLSLD:
+      /* Check transition from LD access model:
+	 leaq foo@tlsld(%rip), %rdi
+       */
+      if (i.tm.mnem_off == MN_lea
+	  && i.base_reg
+	  && i.base_reg->reg_num == RegIP)
+	return true;
+      break;
+    case BFD_RELOC_386_TLS_GOTIE:
+      /* Check transition from GOTIE access model:
+	 subl foo@gotntpoff(%reg1), %reg2
+	 movl foo@gotntpoff(%reg1), %reg2
+	 addl foo@gotntpoff(%reg1), %reg2
+       */
+    case BFD_RELOC_386_TLS_IE_32:
+      /* Check transition from IE_32 access model:
+	 subl foo@gottpoff(%reg1), %reg2
+	 movl foo@gottpoff(%reg1), %reg2
+	 addl foo@gottpoff(%reg1), %reg2
+       */
+      if (i.tm.mnem_off == MN_sub)
+	return true;
+      /* fall through */
+    case BFD_RELOC_386_TLS_IE:
+      /* Check transition from IE access model:
+	 movl foo@indntpoff, %eax
+	 movl foo@indntpoff, %reg
+	 addl foo@indntpoff, %reg
+       */
+      if (i.tm.mnem_off == MN_add || i.tm.mnem_off == MN_mov)
+	return true;
+      break;
+    case BFD_RELOC_X86_64_GOTTPOFF:
+      /* Check transition from GOTTPOFF access model:
+	 mov foo@gottpoff(%rip), %reg
+	 add foo@gottpoff(%rip), %reg.
+       */
+      if ((i.tm.mnem_off == MN_add || i.tm.mnem_off == MN_mov)
+	  && i.base_reg
+	  && i.base_reg->reg_num == RegIP)
+	return true;
+      break;
+    case BFD_RELOC_386_TLS_DESC_CALL:
+      /* Check transition from GDesc access model:
+	 call *x@tlscall(%eax).
+       */
+    case BFD_RELOC_X86_64_TLSDESC_CALL:
+      /* Check transition from GDesc access model:
+	 call *x@tlscall(%rax) <--- LP64 mode.
+	 call *x@tlscall(%eax) <--- X32 mode.
+       */
+      if (i.tm.mnem_off == MN_call)
+	return true;
+      break;
+    default:
+      return true;
+    }
+  return false;
+}
+
 /* This is the guts of the machine-dependent assembler.  LINE points to a
    machine dependent instruction.  This function is supposed to emit
    the frags/bytes it assembles to.  */
@@ -6567,6 +6675,18 @@ i386_assemble (char *line)
 	i.prefix[LOCK_PREFIX] = 0;
     }
 
+  if (tls_check)
+    {
+      for (j = i.imm_operands; j < i.operands; ++j)
+	if (!x86_check_tls_relocation (i.reloc[j]))
+	  {
+	    as_bad (_("`%s' relocation cannot be used with `%s'"),
+		    bfd_reloc_code_real_names[i.reloc[j]],
+		    insn_name (&i.tm));
+	    return;
+	  }
+    }
+
   if ((is_any_vex_encoding (&i.tm) && i.tm.opcode_space != SPACE_EVEXMAP4)
       || i.tm.operand_types[i.imm_operands].bitfield.class >= RegMMX
       || i.tm.operand_types[i.imm_operands + 1].bitfield.class >= RegMMX)
@@ -6577,20 +6697,6 @@ i386_assemble (char *line)
 	  as_bad (_("data size prefix invalid with `%s'"), insn_name (&i.tm));
 	  return;
 	}
-
-      /* Don't allow e.g. KMOV in TLS code sequences.  */
-      for (j = i.imm_operands; j < i.operands; ++j)
-	switch (i.reloc[j])
-	  {
-	  case BFD_RELOC_X86_64_GOTTPOFF:
-	  case BFD_RELOC_386_TLS_GOTIE:
-	  case BFD_RELOC_386_TLS_LE_32:
-	  case BFD_RELOC_X86_64_TLSLD:
-	    as_bad (_("TLS relocation cannot be used with `%s'"), insn_name (&i.tm));
-	    return;
-	  default:
-	    break;
-	  }
     }
 
   /* Check if HLE prefix is OK.  */
@@ -16170,6 +16276,7 @@ const char *md_shortopts = "qnO::";
 #define OPTION_MLFENCE_BEFORE_INDIRECT_BRANCH (OPTION_MD_BASE + 32)
 #define OPTION_MLFENCE_BEFORE_RET (OPTION_MD_BASE + 33)
 #define OPTION_MUSE_UNALIGNED_VECTOR_MOVE (OPTION_MD_BASE + 34)
+#define OPTION_MTLS_CHECK (OPTION_MD_BASE + 35)
 
 struct option md_longopts[] =
 {
@@ -16216,6 +16323,7 @@ struct option md_longopts[] =
   {"mlfence-before-ret", required_argument, NULL, OPTION_MLFENCE_BEFORE_RET},
   {"mamd64", no_argument, NULL, OPTION_MAMD64},
   {"mintel64", no_argument, NULL, OPTION_MINTEL64},
+  {"mtls-check", required_argument, NULL, OPTION_MTLS_CHECK},
   {NULL, no_argument, NULL, 0}
 };
 size_t md_longopts_size = sizeof (md_longopts);
@@ -16772,6 +16880,14 @@ md_parse_option (int c, const char *arg)
 	  optimize_for_space = 0;
 	}
       break;
+    case OPTION_MTLS_CHECK:
+      if (strcasecmp (arg, "yes") == 0)
+	tls_check = 1;
+      else if (strcasecmp (arg, "no") == 0)
+	tls_check = 0;
+      else
+	as_fatal (_("invalid -mtls-check= option: `%s'"), arg);
+      break;
 
     default:
       return 0;
@@ -17014,6 +17130,16 @@ md_show_usage (FILE *stream)
     fprintf (stream, _("(default: no)\n"));
   fprintf (stream, _("\
                           generate relax relocations\n"));
+
+  fprintf (stream, _("\
+  -mtls-check=[no|yes] "));
+  if (DEFAULT_TLS_CHECK)
+    fprintf (stream, _("(default: yes)\n"));
+  else
+    fprintf (stream, _("(default: no)\n"));
+  fprintf (stream, _("\
+		     check tls relocation\n"));
+
   fprintf (stream, _("\
   -malign-branch-boundary=NUM (default: 0)\n\
                           align branches within NUM byte boundary\n"));
diff --git a/gas/configure b/gas/configure
index 6b96d3a4e0c..059be2968af 100755
--- a/gas/configure
+++ b/gas/configure
@@ -818,6 +818,7 @@ enable_checking
 enable_compressed_debug_sections
 enable_default_compressed_debug_sections_algorithm
 enable_x86_relax_relocations
+enable_tls_check
 enable_elf_stt_common
 enable_generate_build_notes
 enable_mips_fix_loongson3_llsc
@@ -1493,6 +1494,7 @@ Optional Features:
                           --enable-compressed-debug-sections.
   --enable-x86-relax-relocations
                           generate x86 relax relocations by default
+  --enable-tls-check      check tls relocation by default
   --enable-elf-stt-common generate ELF common symbols with STT_COMMON type by
                           default
   --enable-generate-build-notes
@@ -10775,7 +10777,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 10778 "configure"
+#line 10780 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10881,7 +10883,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 10884 "configure"
+#line 10886 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11575,6 +11577,17 @@ if test "${enable_x86_relax_relocations+set}" = set; then :
 esac
 fi
 
+# PR gas/32022
+# Decide if check tls relocation.
+ac_default_tls_check=unset
+# Provide a configure time option to override our default.
+# Check whether --enable-tls_check was given.
+if test "${enable_tls_check+set}" = set; then :
+  enableval=$enable_tls_check; case "${enableval}" in
+  no)  ac_default_tls_check=0 ;;
+esac
+fi
+
 # Decide if ELF assembler should generate common symbols with the
 # STT_COMMON type.
 ac_default_elf_stt_common=unset
@@ -12698,6 +12711,15 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+if test ${ac_default_tls_check} = unset; then
+  ac_default_tls_check=1
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_TLS_CHECK $ac_default_tls_check
+_ACEOF
+
+
 if test ${ac_default_elf_stt_common} = unset; then
   ac_default_elf_stt_common=0
 fi
diff --git a/gas/configure.ac b/gas/configure.ac
index 6b978aae3f7..aa8a865ea59 100644
--- a/gas/configure.ac
+++ b/gas/configure.ac
@@ -95,6 +95,17 @@ AC_ARG_ENABLE(x86_relax_relocations,
   no)  ac_default_x86_relax_relocations=0 ;;
 esac])dnl
 
+# PR gas/32022
+# Decide if check tls relocation.
+ac_default_tls_check=unset
+# Provide a configure time option to override our default.
+AC_ARG_ENABLE(tls_check,
+	      AS_HELP_STRING([--enable-tls-check],
+	      [check tls relocation by default]),
+[case "${enableval}" in
+  no)  ac_default_tls_check=0 ;;
+esac])dnl
+
 # Decide if ELF assembler should generate common symbols with the
 # STT_COMMON type.
 ac_default_elf_stt_common=unset
@@ -737,6 +748,13 @@ AC_DEFINE_UNQUOTED(DEFAULT_GENERATE_X86_RELAX_RELOCATIONS,
   $ac_default_x86_relax_relocations,
   [Define to 1 if you want to generate x86 relax relocations by default.])
 
+if test ${ac_default_tls_check} = unset; then
+  ac_default_tls_check=1
+fi
+AC_DEFINE_UNQUOTED(DEFAULT_TLS_CHECK,
+  $ac_default_tls_check,
+  [Define to 1 if you want to check tls relocation by default.])
+
 if test ${ac_default_elf_stt_common} = unset; then
   ac_default_elf_stt_common=0
 fi
diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
index 36ba82506fe..1474c172767 100644
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -463,6 +463,16 @@ R_X86_64_REX_GOTPCRELX, in 64-bit mode.
 relocations.  The default can be controlled by a configure option
 @option{--enable-x86-relax-relocations}.
 
+@cindex @samp{-mtls-check=} option, i386
+@cindex @samp{-mtls-check=} option, x86-64
+@item -mtls-check=@var{no}
+@itemx -mtls-check=@var{yes}
+These options control whether the assembler check tls relocation.
+@option{-mtls-check=@var{yes}} will check tls relocation.
+@option{-mtls-check=@var{no}} will not check tls relocation
+The default can be controlled by a configure option
+@option{--enable-tls-check}.
+
 @cindex @samp{-malign-branch-boundary=} option, i386
 @cindex @samp{-malign-branch-boundary=} option, x86-64
 @item -malign-branch-boundary=@var{NUM}
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 3e707b3d0c6..6a445e3ccd1 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -696,10 +696,11 @@ if [gas_32_check] then {
 	run_dump_test "tlsd"
 	run_dump_test "tlspic"
 	run_dump_test "tlsnopic"
+	run_dump_test "tls"
 	run_list_test "inval-tls"
 	run_dump_test "bss"
 	run_dump_test "reloc32"
-	run_list_test "reloc32" "--defsym _bad_=1"
+	run_list_test "reloc32" "--defsym _bad_=1 -mtls-check=no"
 	run_dump_test "intel-got32"
 	run_dump_test "intel-movs32"
 	run_dump_test "intel-movs16"
diff --git a/gas/testsuite/gas/i386/ilp32/ilp32.exp b/gas/testsuite/gas/i386/ilp32/ilp32.exp
index a3017388934..b32da8725b5 100644
--- a/gas/testsuite/gas/i386/ilp32/ilp32.exp
+++ b/gas/testsuite/gas/i386/ilp32/ilp32.exp
@@ -37,7 +37,7 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_x32_check] &
 	}
     }
 
-    run_list_test "reloc64" "--defsym _bad_=1"
+    run_list_test "reloc64" "--defsym _bad_=1 -mtls-check=no"
     run_list_test "reloc-2"
 
     set ASFLAGS "$old_ASFLAGS"
diff --git a/gas/testsuite/gas/i386/ilp32/reloc64.d b/gas/testsuite/gas/i386/ilp32/reloc64.d
index e2c461f24e8..84b6aaccc01 100644
--- a/gas/testsuite/gas/i386/ilp32/reloc64.d
+++ b/gas/testsuite/gas/i386/ilp32/reloc64.d
@@ -1,4 +1,4 @@
-#as: -mx86-used-note=no --generate-missing-build-notes=no
+#as: -mx86-used-note=no --generate-missing-build-notes=no -mtls-check=no
 #objdump: -Drw
 #name: x86-64 (ILP32) relocs
 
diff --git a/gas/testsuite/gas/i386/inval-tls.l b/gas/testsuite/gas/i386/inval-tls.l
index 59e7c30f46f..89e15eb1db4 100644
--- a/gas/testsuite/gas/i386/inval-tls.l
+++ b/gas/testsuite/gas/i386/inval-tls.l
@@ -1,3 +1,9 @@
 .*: Assembler messages:
-.*:3: Error: .* `kmovd'
-.*:4: Error: .* `kmovd'
+.*:3: Error: `BFD_RELOC_386_TLS_GOTIE' relocation cannot be used with `kmovd'
+.*:6: Error: `BFD_RELOC_386_TLS_GD' relocation cannot be used with `add'
+.*:9: Error: `BFD_RELOC_386_TLS_LDM' relocation cannot be used with `add'
+.*:12: Error: `BFD_RELOC_386_TLS_GOTDESC' relocation cannot be used with `add'
+.*:15: Error: `BFD_RELOC_386_TLS_IE' relocation cannot be used with `sub'
+.*:18: Error: `BFD_RELOC_386_TLS_GOTIE' relocation cannot be used with `lea'
+.*:21: Error: `BFD_RELOC_386_TLS_IE_32' relocation cannot be used with `lea'
+.*:24: Error: `BFD_RELOC_386_TLS_DESC_CALL' relocation cannot be used with `lea'
diff --git a/gas/testsuite/gas/i386/inval-tls.s b/gas/testsuite/gas/i386/inval-tls.s
index 3fe85c31ff3..463d0043337 100644
--- a/gas/testsuite/gas/i386/inval-tls.s
+++ b/gas/testsuite/gas/i386/inval-tls.s
@@ -1,4 +1,24 @@
 	.text
 # All the following should be illegal
 	kmovd	foo@gotntpoff(%eax), %k0
-	kmovd	foo@tpoff(%eax), %k0
+
+	/* Invalid testcase for BFD_RELOC_386_TLS_GD.  */
+	addl foo@tlsgd(,%ebx,1), %eax
+
+	/* Invalid testcase for BFD_RELOC_386_TLS_LDM.  */
+	addl foo@tlsldm(%ebx), %eax
+
+	/* Invalid testcase for BFD_RELOC_386_TLS_GOTDESC.  */
+	addl x@tlsdesc(%ebx), %eax
+
+	/* Invalid testcase for BFD_RELOC_386_TLS_IE.  */
+	subl foo@indntpoff(%ebx), %ecx
+
+	/* Invalid testcase for BFD_RELOC_386_TLS_GOTIE.  */
+	leal foo@gotntpoff(%ebx), %ecx
+
+	/* Invalid testcase for BFD_RELOC_386_TLS_IE_32.  */
+	leal foo@gottpoff(%ebx), %ecx
+
+	/* Invalid testcase for BFD_RELOC_386_TLS_DESC_CALL.  */
+	leal foo@tlscall(%ebx), %ecx
diff --git a/gas/testsuite/gas/i386/reloc32.d b/gas/testsuite/gas/i386/reloc32.d
index 263a742022e..7d1b1ba2ae0 100644
--- a/gas/testsuite/gas/i386/reloc32.d
+++ b/gas/testsuite/gas/i386/reloc32.d
@@ -1,4 +1,4 @@
-#as: -mrelax-relocations=yes
+#as: -mrelax-relocations=yes -mtls-check=no
 #objdump: -Drw
 #name: i386 relocs
 
diff --git a/gas/testsuite/gas/i386/reloc64.d b/gas/testsuite/gas/i386/reloc64.d
index 540a9b77d35..f4e44a627c5 100644
--- a/gas/testsuite/gas/i386/reloc64.d
+++ b/gas/testsuite/gas/i386/reloc64.d
@@ -1,4 +1,4 @@
-#as: -mx86-used-note=no --generate-missing-build-notes=no
+#as: -mx86-used-note=no --generate-missing-build-notes=no -mtls-check=no
 #objdump: -Drw
 #name: x86-64 relocs
 #notarget: *-*-solaris*
diff --git a/gas/testsuite/gas/i386/tls.d b/gas/testsuite/gas/i386/tls.d
new file mode 100644
index 00000000000..de66c375410
--- /dev/null
+++ b/gas/testsuite/gas/i386/tls.d
@@ -0,0 +1,28 @@
+#as:
+#objdump: -dw
+#name: Check tls relocation 32 bit-mode
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+00000000 <_start>:
+\s*[a-f0-9]+:\s*8d 04 1d 00 00 00 00[	 ]+lea    0x0\(,%ebx,1\),%eax
+\s*[a-f0-9]+:\s*8d 83 00 00 00 00[	 ]+lea    0x0\(%ebx\),%eax
+\s*[a-f0-9]+:\s*8d 83 00 00 00 00[	 ]+lea    0x0\(%ebx\),%eax
+\s*[a-f0-9]+:\s*ff 90 00 00 00 00[	 ]+call   \*0x0\(%eax\)
+\s*[a-f0-9]+:\s*a1 00 00 00 00[	 ]+mov    0x0,%eax
+\s*[a-f0-9]+:\s*8b 1d 00 00 00 00[	 ]+mov    0x0,%ebx
+\s*[a-f0-9]+:\s*03 15 00 00 00 00[	 ]+add    0x0,%edx
+\s*[a-f0-9]+:\s*2b 8b 00 00 00 00[	 ]+sub    0x0\(%ebx\),%ecx
+\s*[a-f0-9]+:\s*8b 8b 00 00 00 00[	 ]+mov    0x0\(%ebx\),%ecx
+\s*[a-f0-9]+:\s*03 8b 00 00 00 00[	 ]+add    0x0\(%ebx\),%ecx
+\s*[a-f0-9]+:\s*2b 8b 00 00 00 00[	 ]+sub    0x0\(%ebx\),%ecx
+\s*[a-f0-9]+:\s*8b 8b 00 00 00 00[	 ]+mov    0x0\(%ebx\),%ecx
+\s*[a-f0-9]+:\s*03 8b 00 00 00 00[	 ]+add    0x0\(%ebx\),%ecx
+\s*[a-f0-9]+:\s*8d 8b 00 00 00 00[	 ]+lea    0x0\(%ebx\),%ecx
+\s*[a-f0-9]+:\s*8b 8b 00 00 00 00[	 ]+mov    0x0\(%ebx\),%ecx
+\s*[a-f0-9]+:\s*03 0d 00 00 00 00[	 ]+add    0x0,%ecx
+\s*[a-f0-9]+:\s*ff 10[	 ]+call   \*\(%eax\)
+#pass
diff --git a/gas/testsuite/gas/i386/tls.s b/gas/testsuite/gas/i386/tls.s
new file mode 100644
index 00000000000..46f873ba915
--- /dev/null
+++ b/gas/testsuite/gas/i386/tls.s
@@ -0,0 +1,36 @@
+# Check tls relocation 32-bit mode
+
+	.text
+_start:
+        /* BFD_RELOC_386_TLS_GD.  */
+	leal foo@tlsgd(,%ebx,1), %eax
+
+	/* BFD_RELOC_386_TLS_LDM.  */
+	leal foo@tlsldm(%ebx), %eax
+
+	/* BFD_RELOC_386_TLS_GOTDESC.  */
+	leal x@tlsdesc(%ebx), %eax
+	call *x@tlsdesc(%eax)
+
+	/* BFD_RELOC_386_TLS_IE.  */
+	movl foo@indntpoff, %eax
+	movl foo@indntpoff, %ebx
+	addl foo@indntpoff, %edx
+
+	/* BFD_RELOC_386_TLS_GOTIE.  */
+	subl foo@gotntpoff(%ebx), %ecx
+	movl foo@gotntpoff(%ebx), %ecx
+	addl foo@gotntpoff(%ebx), %ecx
+
+	/* BFD_RELOC_386_TLS_IE_32.  */
+        subl foo@gottpoff(%ebx), %ecx
+	movl foo@gottpoff(%ebx), %ecx
+	addl foo@gottpoff(%ebx), %ecx
+
+	/* BFD_RELOC_386_TLS_LE_32.  */
+        leal foo@tpoff(%ebx), %ecx
+	movl foo@tpoff(%ebx), %ecx
+	addl foo@tpoff, %ecx
+
+	/* BFD_RELOC_386_TLS_DESC_CALL.  */
+	call *foo@tlscall(%eax)
diff --git a/gas/testsuite/gas/i386/x86-64-inval-tls.l b/gas/testsuite/gas/i386/x86-64-inval-tls.l
index 4256e6219a4..1abc24a3c0a 100644
--- a/gas/testsuite/gas/i386/x86-64-inval-tls.l
+++ b/gas/testsuite/gas/i386/x86-64-inval-tls.l
@@ -1,3 +1,9 @@
 .*: Assembler messages:
-.*:3: Error: .* `kmovq'
-.*:4: Error: .* `kmovq'
+.*:3: Error: `BFD_RELOC_X86_64_GOTTPOFF' relocation cannot be used with `kmovq'
+.*:4: Error: `BFD_RELOC_X86_64_TLSLD' relocation cannot be used with `kmovq'
+.*:7: Error: `BFD_RELOC_X86_64_TLSGD' relocation cannot be used with `add'
+.*:10: Error: `BFD_RELOC_X86_64_TLSLD' relocation cannot be used with `add'
+.*:13: Error: `BFD_RELOC_X86_64_GOTPC32_TLSDESC' relocation cannot be used with `add'
+.*:16: Error: `BFD_RELOC_X86_64_GOTTPOFF' relocation cannot be used with `sub'
+.*:17: Error: `BFD_RELOC_X86_64_GOTTPOFF' relocation cannot be used with `xor'
+.*:20: Error: `BFD_RELOC_X86_64_TLSDESC_CALL' relocation cannot be used with `lea'
diff --git a/gas/testsuite/gas/i386/x86-64-inval-tls.s b/gas/testsuite/gas/i386/x86-64-inval-tls.s
index 71e19272ba9..ae969baeef1 100644
--- a/gas/testsuite/gas/i386/x86-64-inval-tls.s
+++ b/gas/testsuite/gas/i386/x86-64-inval-tls.s
@@ -2,3 +2,19 @@
 # All the following should be illegal
 	kmovq	foo@gottpoff(%rip), %k0
 	kmovq	foo@tlsld(%rip), %k0
+
+	/* Invalid testcase for BFD_RELOC_X86_64_TLSGD.  */
+	addq foo@tlsgd(%rip), %rdi
+
+	/* Invalid testcase for BFD_RELOC_X86_64_TLSLD.  */
+	addq foo@tlsld(%rip), %rdi
+
+	/* Invalid testcase for BFD_RELOC_X86_64_GOTPC32_TLSDESC.  */
+	addq x@tlsdesc(%rip), %rax
+
+	/* Invalid testcase for BFD_RELOC_X86_64_GOTTPOFF.  */
+	subq foo@gottpoff(%rip), %r12
+	xorq foo@gottpoff(%rip), %rax
+
+	/* Invalid testcase for BFD_RELOC_X86_64_TLSDESC_CALL.  */
+	leaq foo@tlscall(%rip), %r12
diff --git a/gas/testsuite/gas/i386/x86-64-tls.d b/gas/testsuite/gas/i386/x86-64-tls.d
new file mode 100644
index 00000000000..f0bade1bf2d
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-tls.d
@@ -0,0 +1,29 @@
+#as:
+#objdump: -dw
+#name: Check tls relocation x86-64
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0000000000000000 <_start>:
+\s*[a-f0-9]+:\s*48 8d 3d 00 00 00 00[	 ]+lea    0x0\(%rip\),%rdi.*
+\s*[a-f0-9]+:\s*48 8d 3d 00 00 00 00[	 ]+lea    0x0\(%rip\),%rdi.*
+\s*[a-f0-9]+:\s*48 8d 05 00 00 00 00[	 ]+lea    0x0\(%rip\),%rax.*
+\s*[a-f0-9]+:\s*ff 90 00 00 00 00   [	 ]+call   \*0x0\(%rax\).*
+\s*[a-f0-9]+:\s*40 8d 05 00 00 00 00[	 ]+rex lea 0x0\(%rip\),%eax.*
+\s*[a-f0-9]+:\s*d5 40 8d 05 00 00 00 00[	 ]+lea    0x0\(%rip\),%r16d.*
+\s*[a-f0-9]+:\s*67 ff 90 00 00 00 00[	 ]+call   \*0x0\(%eax\).*
+\s*[a-f0-9]+:\s*4c 03 25 00 00 00 00[	 ]+add    0x0\(%rip\),%r12.*
+\s*[a-f0-9]+:\s*48 8b 05 00 00 00 00[	 ]+mov    0x0\(%rip\),%rax.*
+\s*[a-f0-9]+:\s*d5 48 03 05 00 00 00 00[	 ]+add    0x0\(%rip\),%r16.*
+\s*[a-f0-9]+:\s*d5 48 8b 25 00 00 00 00[	 ]+mov    0x0\(%rip\),%r20.*
+\s*[a-f0-9]+:\s*62 64 bc 18 01 35 00 00 00 00[	 ]+add    %r30,0x0\(%rip\),%r8.*
+\s*[a-f0-9]+:\s*62 f4 dc 10 03 05 00 00 00 00[	 ]+add    0x0\(%rip\),%rax,%r20.*
+\s*[a-f0-9]+:\s*62 e4 fc 0c 03 05 00 00 00 00[	 ]+{nf} add 0x0\(%rip\),%r16.*
+\s*[a-f0-9]+:\s*62 64 bc 1c 01 35 00 00 00 00[	 ]+{nf} add %r30,0x0\(%rip\),%r8.*
+\s*[a-f0-9]+:\s*62 f4 dc 14 03 05 00 00 00 00[	 ]+{nf} add 0x0\(%rip\),%rax,%r20.*
+\s*[a-f0-9]+:\s*ff 90 00 00 00 00[	 ]+call   \*0x0\(%rax\).*
+\s*[a-f0-9]+:\s*67 ff 90 00 00 00 00[	 ]+call   \*0x0\(%eax\).*
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-tls.s b/gas/testsuite/gas/i386/x86-64-tls.s
new file mode 100644
index 00000000000..ae19bbd39d7
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-tls.s
@@ -0,0 +1,31 @@
+# Check tls relocation 64-bit mode
+
+	.text
+_start:
+	/* BFD_RELOC_X86_64_TLSGD.  */
+	leaq foo@tlsgd(%rip), %rdi
+
+	/* BFD_RELOC_X86_64_TLSLD.  */
+	leaq foo@tlsld(%rip), %rdi
+
+	/* BFD_RELOC_X86_64_GOTPC32_TLSDESC.  */
+	leaq     x@tlsdesc(%rip), %rax
+	call     *x@tlsdesc(%rax)
+	rex leal x@tlsdesc(%rip), %eax
+	leal     x@tlsdesc(%rip), %r16d
+	call     *x@tlsdesc(%eax)
+
+	/* BFD_RELOC_X86_64_GOTTPOFF.  */
+	addq     foo@gottpoff(%rip), %r12
+	movq     foo@gottpoff(%rip), %rax
+	addq     foo@gottpoff(%rip), %r16
+	movq     foo@gottpoff(%rip), %r20
+	addq     %r30, foo@gottpoff(%rip), %r8
+	addq     foo@gottpoff(%rip), %rax, %r20
+	{nf} addq foo@gottpoff(%rip), %r16
+	{nf} addq %r30, foo@gottpoff(%rip), %r8
+	{nf} addq foo@gottpoff(%rip), %rax, %r20
+
+	/* BFD_RELOC_X86_64_TLSDESC_CALL.  */
+	call *x@tlsdesc(%rax)
+	call *x@tlsdesc(%eax)
diff --git a/gas/testsuite/gas/i386/x86-64.exp b/gas/testsuite/gas/i386/x86-64.exp
index 57cb4aa165a..4da97297d17 100644
--- a/gas/testsuite/gas/i386/x86-64.exp
+++ b/gas/testsuite/gas/i386/x86-64.exp
@@ -651,7 +651,8 @@ if [is_elf_format] then {
     run_dump_test "x86-64-unwind"
 
     run_dump_test "reloc64"
-    run_list_test "reloc64" "--defsym _bad_=1"
+    run_list_test "reloc64" "--defsym _bad_=1 -mtls-check=no"
+    run_dump_test "x86-64-tls"
     run_list_test "x86-64-inval-tls"
     run_dump_test "mixed-mode-reloc64"
     run_dump_test "rela"
diff --git a/ld/testsuite/ld-i386/tlsgdesc1.d b/ld/testsuite/ld-i386/tlsgdesc1.d
index 2a70e81c444..0c853ab0a67 100644
--- a/ld/testsuite/ld-i386/tlsgdesc1.d
+++ b/ld/testsuite/ld-i386/tlsgdesc1.d
@@ -1,4 +1,4 @@
 #name: TLS GDesc->LE transition check (LEA)
-#as: --32
+#as: --32 -mtls-check=no
 #ld: -melf_i386
 #error: .*: relocation R_386_TLS_GOTDESC against `foo' must be used in LEA only
diff --git a/ld/testsuite/ld-i386/tlsgdesc2.d b/ld/testsuite/ld-i386/tlsgdesc2.d
index 2e6a66d372c..e563abf17c8 100644
--- a/ld/testsuite/ld-i386/tlsgdesc2.d
+++ b/ld/testsuite/ld-i386/tlsgdesc2.d
@@ -1,4 +1,4 @@
 #name: TLS GDesc->LE transition check (indirect CALL)
-#as: --32
+#as: --32 -mtls-check=no
 #ld: -melf_i386
 #error: .*: relocation R_386_TLS_DESC_CALL against `foo' must be used in indirect CALL only
diff --git a/ld/testsuite/ld-i386/tlsie2.d b/ld/testsuite/ld-i386/tlsie2.d
index 9f9e63029d6..4e7dc6ea56e 100644
--- a/ld/testsuite/ld-i386/tlsie2.d
+++ b/ld/testsuite/ld-i386/tlsie2.d
@@ -1,4 +1,4 @@
 #name: TLS IE->LE transition check (R_386_TLS_GOTIE with %eax)
-#as: --32
+#as: --32 -mtls-check=no
 #ld: -melf_i386
 #error: .*: relocation R_386_TLS_GOTIE against `foo' must be used in ADD, SUB or MOV only
diff --git a/ld/testsuite/ld-i386/tlsie3.d b/ld/testsuite/ld-i386/tlsie3.d
index 506f1a02605..6bfc78e0b49 100644
--- a/ld/testsuite/ld-i386/tlsie3.d
+++ b/ld/testsuite/ld-i386/tlsie3.d
@@ -1,4 +1,4 @@
 #name: TLS IE->LE transition check (R_386_TLS_GOTIE)
-#as: --32
+#as: --32 -mtls-check=no
 #ld: -melf_i386
 #error: .*: relocation R_386_TLS_GOTIE against `foo' must be used in ADD, SUB or MOV only
diff --git a/ld/testsuite/ld-i386/tlsie4.d b/ld/testsuite/ld-i386/tlsie4.d
index a516d002660..98293f4b36a 100644
--- a/ld/testsuite/ld-i386/tlsie4.d
+++ b/ld/testsuite/ld-i386/tlsie4.d
@@ -1,4 +1,4 @@
 #name: TLS IE->LE transition check (R_386_TLS_IE with %eax)
-#as: --32
+#as: --32 -mtls-check=no
 #ld: -melf_i386
 #error: .*: relocation R_386_TLS_IE against `foo' must be used in ADD or MOV only
diff --git a/ld/testsuite/ld-i386/tlsie5.d b/ld/testsuite/ld-i386/tlsie5.d
index d3447182e19..4e9c9a8f74a 100644
--- a/ld/testsuite/ld-i386/tlsie5.d
+++ b/ld/testsuite/ld-i386/tlsie5.d
@@ -1,4 +1,4 @@
 #name: TLS IE->LE transition check (R_386_TLS_IE)
-#as: --32
+#as: --32 -mtls-check=no
 #ld: -melf_i386
 #error: .*: relocation R_386_TLS_IE against `foo' must be used in ADD or MOV only
diff --git a/ld/testsuite/ld-x86-64/tlsdesc3.d b/ld/testsuite/ld-x86-64/tlsdesc3.d
index bbf22ebeafe..955884885d7 100644
--- a/ld/testsuite/ld-x86-64/tlsdesc3.d
+++ b/ld/testsuite/ld-x86-64/tlsdesc3.d
@@ -1,4 +1,4 @@
 #name: TLS GDesc->LE transition check (LEA)
-#as: --64
+#as: --64 -mtls-check=no
 #ld: -melf_x86_64
 #error: .*: relocation R_X86_64_GOTPC32_TLSDESC against `foo' must be used in LEA only
diff --git a/ld/testsuite/ld-x86-64/tlsdesc4.d b/ld/testsuite/ld-x86-64/tlsdesc4.d
index b50115c7178..a1e2c3a0828 100644
--- a/ld/testsuite/ld-x86-64/tlsdesc4.d
+++ b/ld/testsuite/ld-x86-64/tlsdesc4.d
@@ -1,4 +1,4 @@
 #name: TLS GDesc->LE transition check (indirect CALL)
-#as: --64
+#as: --64 -mtls-check=no
 #ld: -melf_x86_64
 #error: .*: relocation R_X86_64_TLSDESC_CALL against `foo' must be used in indirect CALL only
diff --git a/ld/testsuite/ld-x86-64/tlsie2.d b/ld/testsuite/ld-x86-64/tlsie2.d
index bf8a8198b5b..2e6d41ccf61 100644
--- a/ld/testsuite/ld-x86-64/tlsie2.d
+++ b/ld/testsuite/ld-x86-64/tlsie2.d
@@ -1,4 +1,4 @@
 #name: TLS IE->LE transition check
-#as: --64
+#as: --64 -mtls-check=no
 #ld: -melf_x86_64
 #error: .*: relocation R_X86_64_GOTTPOFF against `foo' must be used in ADD or MOV only
diff --git a/ld/testsuite/ld-x86-64/tlsie3.d b/ld/testsuite/ld-x86-64/tlsie3.d
index 49d8464fbaf..b59cc6429de 100644
--- a/ld/testsuite/ld-x86-64/tlsie3.d
+++ b/ld/testsuite/ld-x86-64/tlsie3.d
@@ -1,4 +1,4 @@
 #name: TLS IE->LE transition check (%r12)
-#as: --64
+#as: --64 -mtls-check=no
 #ld: -melf_x86_64
 #error: .*: relocation R_X86_64_GOTTPOFF against `foo' must be used in ADD or MOV only
diff --git a/ld/testsuite/ld-x86-64/tlsie5.d b/ld/testsuite/ld-x86-64/tlsie5.d
index 29de1cebf8e..d7ab5ab7b32 100644
--- a/ld/testsuite/ld-x86-64/tlsie5.d
+++ b/ld/testsuite/ld-x86-64/tlsie5.d
@@ -1,4 +1,4 @@
 #name: TLS IE->LE transition check (APX)
-#as: --64
+#as: --64 -mtls-check=no
 #ld: -melf_x86_64
 #error: .*: relocation R_X86_64_CODE_6_GOTTPOFF against `foo' must be used in ADD only
-- 
2.34.1



More information about the Binutils mailing list