]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
x86: Add tls check in gas
authorCui, Lili <lili.cui@intel.com>
Thu, 19 Sep 2024 06:38:16 +0000 (14:38 +0800)
committerH.J. Lu <hjl.tools@gmail.com>
Fri, 20 Sep 2024 21:19:16 +0000 (05:19 +0800)
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 or format. Since 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
        *(enum x86_tls_error_type): New.
        *(struct _i386_insn): Added has_gotrel to indicate whether TLS
relocations need to be checked.
        (x86_check_tls_relocation): Added a new function to check TLS
relocation.
        (x86_report_tls_error): Created a new function to report TLS error.
        (i386_assemble): Handle x86_check_tls_relocation.
        (lex_got): Set i.has_gotrel.
        (OPTION_MTLS_CHECK): Added a new option to contrl TLS check.
        (struct option): Ditto.
        (md_parse_option): Ditto.
        (md_show_usage): Ditto.
        * configure.ac: Added a new option to check TLS relocation by
default.
        * configure: Regenerated.
        * doc/c-i386.texi: Document -mtls-check=.
        * 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/ilp32/x32-tls.d: Ditto.
        * 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/ilp32/x32-inval-tls.l: New test.
        * testsuite/gas/i386/ilp32/x32-inval-tls.s: Ditto.
        * testsuite/gas/i386/ilp32/x86-64-tls.d: Ditto.
        * testsuite/gas/i386/tls.d: Ditto.
        * 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-i386/tlsgdesc3.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.
        * testsuite/ld-x86-64/tlsdesc5.d: Ditto.

36 files changed:
gas/config.in
gas/config/tc-i386.c
gas/configure
gas/configure.ac
gas/doc/c-i386.texi
gas/testsuite/gas/i386/i386.exp
gas/testsuite/gas/i386/ilp32/ilp32.exp
gas/testsuite/gas/i386/ilp32/reloc64.d
gas/testsuite/gas/i386/ilp32/x32-inval-tls.l [new file with mode: 0644]
gas/testsuite/gas/i386/ilp32/x32-inval-tls.s [new file with mode: 0644]
gas/testsuite/gas/i386/ilp32/x32-tls.d
gas/testsuite/gas/i386/ilp32/x86-64-tls.d [new file with mode: 0644]
gas/testsuite/gas/i386/inval-tls.l
gas/testsuite/gas/i386/inval-tls.s
gas/testsuite/gas/i386/reloc32.d
gas/testsuite/gas/i386/reloc64.d
gas/testsuite/gas/i386/tls.d [new file with mode: 0644]
gas/testsuite/gas/i386/tls.s [new file with mode: 0644]
gas/testsuite/gas/i386/x86-64-inval-tls.l
gas/testsuite/gas/i386/x86-64-inval-tls.s
gas/testsuite/gas/i386/x86-64-tls.d [new file with mode: 0644]
gas/testsuite/gas/i386/x86-64-tls.s [new file with mode: 0644]
gas/testsuite/gas/i386/x86-64.exp
ld/testsuite/ld-i386/tlsgdesc1.d
ld/testsuite/ld-i386/tlsgdesc2.d
ld/testsuite/ld-i386/tlsgdesc3.d
ld/testsuite/ld-i386/tlsie2.d
ld/testsuite/ld-i386/tlsie3.d
ld/testsuite/ld-i386/tlsie4.d
ld/testsuite/ld-i386/tlsie5.d
ld/testsuite/ld-x86-64/tlsdesc3.d
ld/testsuite/ld-x86-64/tlsdesc4.d
ld/testsuite/ld-x86-64/tlsdesc5.d
ld/testsuite/ld-x86-64/tlsie2.d
ld/testsuite/ld-x86-64/tlsie3.d
ld/testsuite/ld-x86-64/tlsie5.d

index a1f834993329333380b32e75814bd37edec2ba77..c32b46b93f5296992de9f63d0f93a8da6d85c0f4 100644 (file)
@@ -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 x86 TLS relocation by default. */
+#undef DEFAULT_X86_TLS_CHECK
+
 /* Define to 1 if you want to generate GNU x86 used ISA and feature properties
    by default. */
 #undef DEFAULT_X86_USED_NOTE
index 72de448728a39eea0f6f1f3bf4c184f141418adf..11565ac7cb07ba1ef34013f23d613c9032b85066 100644 (file)
@@ -274,6 +274,30 @@ enum i386_error
     internal_error,
   };
 
+enum x86_tls_error_type
+{
+  x86_tls_error_continue,
+  x86_tls_error_none,
+  x86_tls_error_insn,
+  x86_tls_error_opcode,
+  x86_tls_error_sib,
+  x86_tls_error_no_base_reg,
+  x86_tls_error_require_no_base_index_reg,
+  x86_tls_error_base_reg,
+  x86_tls_error_index_ebx,
+  x86_tls_error_eax,
+  x86_tls_error_RegA,
+  x86_tls_error_ebx,
+  x86_tls_error_rip,
+  x86_tls_error_dest_eax,
+  x86_tls_error_dest_rdi,
+  x86_tls_error_scale_factor,
+  x86_tls_error_base_reg_size,
+  x86_tls_error_dest_32bit_reg_size,
+  x86_tls_error_dest_64bit_reg_size,
+  x86_tls_error_dest_32bit_or_64bit_reg_size
+};
+
 struct _i386_insn
   {
     /* TM holds the template for the insn were currently assembling.  */
@@ -365,6 +389,9 @@ struct _i386_insn
     /* Has GOTPC or TLS relocation.  */
     bool has_gotpc_tls_reloc;
 
+    /* Has relocation entry from the gotrel array.  */
+    bool has_gotrel;
+
     /* RM and SIB are the modrm byte and the sib byte where the
        addressing modes of this insn are encoded.  */
     modrm_byte rm;
@@ -717,6 +744,9 @@ lfence_before_ret;
 static int generate_relax_relocations
   = DEFAULT_GENERATE_X86_RELAX_RELOCATIONS;
 
+/* 1 if the assembler should check tls relocation.  */
+static bool tls_check = DEFAULT_X86_TLS_CHECK;
+
 static enum check_kind
   {
     check_none = 0,
@@ -6358,6 +6388,356 @@ static INLINE bool may_need_pass2 (const insn_template *t)
               && (t->base_opcode | 8) == 0x2c);
 }
 
+static enum x86_tls_error_type
+x86_check_tls_relocation (enum bfd_reloc_code_real r_type)
+{
+  switch (r_type)
+    {
+    case BFD_RELOC_386_TLS_GOTDESC:
+      /* Check GDesc access model:
+
+        leal x@tlsdesc(%ebx), %reg32 --> Memory reg must be %ebx and
+                                         SIB is not supported.
+       */
+      if (i.tm.mnem_off != MN_lea)
+       return x86_tls_error_insn;
+      if (i.index_reg)
+       return x86_tls_error_sib;
+      if (!i.base_reg)
+       return x86_tls_error_no_base_reg;
+      if (i.base_reg->reg_type.bitfield.instance != RegB)
+       return x86_tls_error_ebx;
+      if (!i.op[1].regs->reg_type.bitfield.dword)
+       return x86_tls_error_dest_32bit_reg_size;
+      break;
+
+    case BFD_RELOC_386_TLS_GD:
+      /* Check GD access model:
+
+        leal foo@tlsgd(,%ebx,1), %eax   --> Only this fixed format is supported.
+        leal foo@tlsgd(%reg32), %eax    --> Dest reg must be '%eax'
+                                            Memory reg can't be %eax.
+       */
+      if (i.tm.mnem_off != MN_lea)
+       return x86_tls_error_insn;
+      if (i.op[1].regs->reg_type.bitfield.instance != Accum)
+       return x86_tls_error_dest_eax;
+      if (!i.op[1].regs->reg_type.bitfield.dword)
+       return x86_tls_error_dest_32bit_reg_size;
+      if (i.index_reg)
+       {
+         if (i.base_reg)
+           return x86_tls_error_base_reg;
+         if (i.index_reg->reg_type.bitfield.instance != RegB)
+           return x86_tls_error_index_ebx;
+         if (i.log2_scale_factor)
+           return x86_tls_error_scale_factor;
+       }
+      else
+       {
+         if (!i.base_reg)
+           return x86_tls_error_no_base_reg;
+         if (i.base_reg->reg_type.bitfield.instance == Accum)
+           return x86_tls_error_eax;
+       }
+      break;
+
+    case BFD_RELOC_386_TLS_LDM:
+      /*  Check LDM access model:
+
+         leal foo@tlsldm(%reg32), %eax --> Dest reg must be '%eax'
+                                           Memory reg can't be %eax and SIB
+                                           is not supported.
+       */
+      if (i.tm.mnem_off != MN_lea)
+       return x86_tls_error_insn;
+      if (i.index_reg)
+       return x86_tls_error_sib;
+      if (!i.base_reg)
+       return x86_tls_error_no_base_reg;
+      if (i.base_reg->reg_type.bitfield.instance == Accum)
+       return x86_tls_error_eax;
+      if (i.op[1].regs->reg_type.bitfield.instance != Accum)
+       return x86_tls_error_dest_eax;
+      if (!i.op[1].regs->reg_type.bitfield.dword)
+       return x86_tls_error_dest_32bit_reg_size;
+      break;
+
+    case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+      /* Check GOTPC32 TLSDESC access model:
+
+        --- LP64 mode ---
+        leaq x@tlsdesc(%rip), %reg64 --> Memory reg must be %rip.
+
+        --- X32 mode ---
+        rex/rex2 leal x@tlsdesc(%rip), %reg32 --> Memory reg must be %rip.
+
+        In X32 mode, gas will add rex/rex2 for it later, no need to check
+        here.
+       */
+      if (i.tm.mnem_off != MN_lea)
+       return x86_tls_error_insn;
+      if (!i.base_reg)
+       return x86_tls_error_no_base_reg;
+      if (i.base_reg->reg_num != RegIP
+         || !i.base_reg->reg_type.bitfield.qword)
+       return x86_tls_error_rip;
+      if (x86_elf_abi == X86_64_ABI)
+       {
+         if (!i.op[1].regs->reg_type.bitfield.qword)
+           return x86_tls_error_dest_64bit_reg_size;
+       }
+      else if (!i.op[1].regs->reg_type.bitfield.dword
+              && !i.op[1].regs->reg_type.bitfield.qword)
+       return x86_tls_error_dest_32bit_or_64bit_reg_size;
+         break;
+
+    case BFD_RELOC_X86_64_TLSGD:
+      /* Check GD access model:
+
+        leaq foo@tlsgd(%rip), %rdi --> Only this fixed format is supported.
+       */
+    case BFD_RELOC_X86_64_TLSLD:
+      /* Check LD access model:
+
+        leaq foo@tlsld(%rip), %rdi --> Only this fixed format is supported.
+       */
+      if (i.tm.mnem_off != MN_lea)
+       return x86_tls_error_insn;
+      if (!i.base_reg)
+       return x86_tls_error_no_base_reg;
+      if (i.base_reg->reg_num != RegIP
+         || !i.base_reg->reg_type.bitfield.qword)
+       return x86_tls_error_rip;
+      if (!i.op[1].regs->reg_type.bitfield.qword
+         || i.op[1].regs->reg_num != EDI_REG_NUM
+         || i.op[1].regs->reg_flags)
+       return x86_tls_error_dest_rdi;
+      break;
+
+    case BFD_RELOC_386_TLS_GOTIE:
+      /* Check GOTIE access model:
+
+        subl foo@gotntpoff(%reg1), %reg2
+        movl foo@gotntpoff(%reg1), %reg2
+        addl foo@gotntpoff(%reg1), %reg2
+
+        Memory operand: SIB is not supported.
+       */
+    case BFD_RELOC_386_TLS_IE_32:
+      /* Check IE_32 access model:
+
+        subl foo@gottpoff(%reg1), %reg2
+        movl foo@gottpoff(%reg1), %reg2
+        addl foo@gottpoff(%reg1), %reg2
+
+        Memory operand: SIB is not supported.
+       */
+      if (i.tm.mnem_off != MN_sub
+         && i.tm.mnem_off != MN_add
+         && i.tm.mnem_off != MN_mov)
+       return x86_tls_error_insn;
+      if (i.op[1].regs->reg_type.bitfield.class != Reg
+         || i.op[0].regs->reg_type.bitfield.class
+         || i.imm_operands)
+       return x86_tls_error_opcode;
+      if (!i.base_reg)
+       return x86_tls_error_no_base_reg;
+      if (i.index_reg)
+       return x86_tls_error_sib;
+      if (!i.base_reg->reg_type.bitfield.dword)
+       return x86_tls_error_base_reg_size;
+      if (!i.op[1].regs->reg_type.bitfield.dword)
+       return x86_tls_error_dest_32bit_reg_size;
+      break;
+
+    case BFD_RELOC_386_TLS_IE:
+      /* Check IE access model:
+
+        movl foo@indntpoff, %reg32 --> Mod == 00 && r/m == 5
+        addl foo@indntpoff, %reg32 --> Mod == 00 && r/m == 5
+       */
+      if (i.tm.mnem_off != MN_add && i.tm.mnem_off != MN_mov)
+       return x86_tls_error_insn;
+      if (i.op[1].regs->reg_type.bitfield.class != Reg
+         || i.op[0].regs->reg_type.bitfield.class
+         || i.imm_operands)
+       return x86_tls_error_opcode;
+      if (i.base_reg || i.index_reg)
+       return x86_tls_error_require_no_base_index_reg;
+      if (!i.op[1].regs->reg_type.bitfield.dword)
+       return x86_tls_error_dest_32bit_reg_size;
+      break;
+
+    case BFD_RELOC_X86_64_GOTTPOFF:
+      /* Check GOTTPOFF access model:
+
+        mov foo@gottpoff(%rip), %reg --> Memory Reg must be %rip.
+        add foo@gottpoff(%rip), %reg --> Memory Reg must be %rip.
+        add %reg1, foo@gottpoff(%rip), %reg2 --> Memory Reg must be %rip.
+        add foo@gottpoff(%rip), %reg1, %reg2 --> Memory Reg must be %rip.
+       */
+      if (i.tm.mnem_off != MN_add && i.tm.mnem_off != MN_mov)
+       return x86_tls_error_insn;
+      if (i.op[i.operands - 1].regs->reg_type.bitfield.class != Reg
+         || (i.op[0].regs->reg_type.bitfield.class
+             && i.tm.opcode_modifier.vexvvvv != VexVVVV_DST)
+         || i.imm_operands)
+       return x86_tls_error_opcode;
+      if (!i.base_reg)
+       return x86_tls_error_no_base_reg;
+      if (i.base_reg->reg_num != RegIP
+         || !i.base_reg->reg_type.bitfield.qword)
+       return x86_tls_error_rip;
+      if (x86_elf_abi == X86_64_ABI)
+       {
+         if (!i.op[i.operands - 1].regs->reg_type.bitfield.qword)
+           return x86_tls_error_dest_64bit_reg_size;
+       }
+      else if (!i.op[i.operands - 1].regs->reg_type.bitfield.dword
+              && !i.op[i.operands - 1].regs->reg_type.bitfield.qword)
+       return x86_tls_error_dest_32bit_or_64bit_reg_size;
+      break;
+
+    case BFD_RELOC_386_TLS_DESC_CALL:
+      /* Check GDesc access model:
+
+        call *x@tlscall(%eax) --> Memory reg must be %eax and
+                                  SIB is not supported.
+       */
+    case BFD_RELOC_X86_64_TLSDESC_CALL:
+      /* Check GDesc access model:
+
+        call *x@tlscall(%rax) <--- LP64 mode.
+        call *x@tlscall(%eax) <--- X32 mode.
+
+        Only these fixed formats are supported.
+       */
+      if (i.tm.mnem_off != MN_call)
+       return x86_tls_error_insn;
+      if (i.index_reg)
+       return x86_tls_error_sib;
+      if (!i.base_reg)
+       return x86_tls_error_no_base_reg;
+      if (i.base_reg->reg_type.bitfield.instance != Accum)
+       return x86_tls_error_RegA;
+      break;
+
+    case BFD_RELOC_NONE:
+      /* This isn't a relocation.  */
+      return x86_tls_error_continue;
+
+    default:
+      break;
+    }
+
+  /* This relocation is OK.  */
+  return x86_tls_error_none;
+}
+
+static void
+x86_report_tls_error (enum x86_tls_error_type tls_error,
+                     enum bfd_reloc_code_real r_type)
+{
+  unsigned int k;
+  for (k = 0; k < ARRAY_SIZE (gotrel); k++)
+    if (gotrel[k].rel[object_64bit] == r_type)
+      break;
+
+  switch (tls_error)
+    {
+    case x86_tls_error_insn:
+      as_bad (_("@%s operator cannot be used with `%s'"),
+             gotrel[k].str, insn_name (&i.tm));
+      return;
+
+    case x86_tls_error_opcode:
+      as_bad (_("@%s operator can be used with `%s', but format is wrong"),
+             gotrel[k].str, insn_name (&i.tm));
+      return;
+
+    case x86_tls_error_sib:
+      as_bad (_("@%s operator requires no SIB"), gotrel[k].str);
+      return;
+
+    case x86_tls_error_no_base_reg:
+      as_bad (_("@%s operator requires base register"), gotrel[k].str);
+      return;
+
+    case x86_tls_error_require_no_base_index_reg:
+      as_bad (_("@%s operator requires no base/index register"),
+             gotrel[k].str);
+      return;
+
+    case x86_tls_error_base_reg:
+      as_bad (_("@%s operator requires no base register"), gotrel[k].str);
+      return;
+
+    case x86_tls_error_index_ebx:
+      as_bad (_("@%s operator requires `%sebx' as index register"),
+             gotrel[k].str, register_prefix);
+      return;
+
+    case x86_tls_error_eax:
+      as_bad (_("@%s operator requires `%seax' as base register"),
+             gotrel[k].str, register_prefix);
+      return;
+
+    case x86_tls_error_RegA:
+      as_bad (_("@%s operator requires `%seax/%srax' as base register"),
+             gotrel[k].str, register_prefix, register_prefix);
+      return;
+
+    case x86_tls_error_ebx:
+      as_bad (_("@%s operator requires `%sebx' as base register"),
+             gotrel[k].str, register_prefix);
+      return;
+
+    case x86_tls_error_rip:
+      as_bad (_("@%s operator requires `%srip' as base register"),
+             gotrel[k].str, register_prefix);
+      return;
+
+    case x86_tls_error_dest_eax:
+      as_bad (_("@%s operator requires `%seax' as dest register"),
+             gotrel[k].str, register_prefix);
+      return;
+
+    case x86_tls_error_dest_rdi:
+      as_bad (_("@%s operator requires `%srdi' as dest register"),
+             gotrel[k].str, register_prefix);
+      return;
+
+    case x86_tls_error_scale_factor:
+      as_bad (_("@%s operator requires scale factor of 1"),
+             gotrel[k].str);
+      return;
+
+    case x86_tls_error_base_reg_size:
+      as_bad (_("@%s operator requires 32-bit base register"),
+             gotrel[k].str);
+      return;
+
+    case x86_tls_error_dest_32bit_reg_size:
+      as_bad (_("@%s operator requires 32-bit dest register"),
+             gotrel[k].str);
+      return;
+
+    case x86_tls_error_dest_64bit_reg_size:
+      as_bad (_("@%s operator requires 64-bit dest register"),
+             gotrel[k].str);
+      return;
+
+    case x86_tls_error_dest_32bit_or_64bit_reg_size:
+      as_bad (_("@%s operator requires 32-bit or 64-bit dest register"),
+             gotrel[k].str);
+      return;
+
+    default:
+      abort ();
+    }
+}
+
 /* 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.  */
@@ -6696,6 +7076,21 @@ i386_assemble (char *line)
        i.prefix[LOCK_PREFIX] = 0;
     }
 
+  if (i.has_gotrel && tls_check)
+    {
+      enum x86_tls_error_type tls_error;
+      for (j = 0; j < i.operands; ++j)
+       {
+         tls_error = x86_check_tls_relocation (i.reloc[j]);
+         if (tls_error == x86_tls_error_continue)
+           continue;
+
+         if (tls_error != x86_tls_error_none)
+           x86_report_tls_error (tls_error, i.reloc[j]);
+         break;
+       }
+    }
+
   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)
@@ -6706,28 +7101,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 which will trigger
-        linker error later.  */
-      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_X86_64_TLSLD:
-           for (unsigned int k = 0; k < ARRAY_SIZE (gotrel); k++)
-             {
-               if (gotrel[k].rel[object_64bit] == i.reloc[j])
-                 {
-                   as_bad (_("@%s operator cannot be used with `%s'"),
-                         gotrel[k].str, insn_name (&i.tm));
-                   return;
-                 }
-             }
-           abort ();
-         default:
-           break;
-         }
     }
 
   /* Check if HLE prefix is OK.  */
@@ -12497,6 +12870,7 @@ lex_got (enum bfd_reloc_code_real *rel,
              int first, second;
              char *tmpbuf, *past_reloc;
 
+             i.has_gotrel = true;
              *rel = gotrel[j].rel[object_64bit];
 
              if (types)
@@ -16230,6 +16604,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[] =
 {
@@ -16276,6 +16651,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);
@@ -16832,6 +17208,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 = true;
+      else if (strcasecmp (arg, "no") == 0)
+       tls_check = false;
+      else
+       as_fatal (_("invalid -mtls-check= option: `%s'"), arg);
+      break;
 
     default:
       return 0;
@@ -17074,6 +17458,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_X86_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"));
index 6b96d3a4e0cab164f7acbb48ca47075d7ae83154..be37f31e1af67cca68373ead15334be2d513b0d8 100755 (executable)
@@ -818,6 +818,7 @@ enable_checking
 enable_compressed_debug_sections
 enable_default_compressed_debug_sections_algorithm
 enable_x86_relax_relocations
+enable_x86_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-x86-tls-check  check x86 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 x86 assembler should check TLS relocation.
+ac_default_x86_tls_check=unset
+# Provide a configure time option to override our default.
+# Check whether --enable-x86_tls_check was given.
+if test "${enable_x86_tls_check+set}" = set; then :
+  enableval=$enable_x86_tls_check; case "${enableval}" in
+  no)  ac_default_x86_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_x86_tls_check} = unset; then
+  ac_default_x86_tls_check=1
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_X86_TLS_CHECK $ac_default_x86_tls_check
+_ACEOF
+
+
 if test ${ac_default_elf_stt_common} = unset; then
   ac_default_elf_stt_common=0
 fi
index 6b978aae3f75288621c4a68e3e4ab9932b348485..bf3f9b5b6fa5c72687db4e4524db622355f4c232 100644 (file)
@@ -95,6 +95,17 @@ AC_ARG_ENABLE(x86_relax_relocations,
   no)  ac_default_x86_relax_relocations=0 ;;
 esac])dnl
 
+# PR gas/32022
+# Decide if x86 assembler should check TLS relocation.
+ac_default_x86_tls_check=unset
+# Provide a configure time option to override our default.
+AC_ARG_ENABLE(x86_tls_check,
+             AS_HELP_STRING([--enable-x86-tls-check],
+             [check x86 TLS relocation by default]),
+[case "${enableval}" in
+  no)  ac_default_x86_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_x86_tls_check} = unset; then
+  ac_default_x86_tls_check=1
+fi
+AC_DEFINE_UNQUOTED(DEFAULT_X86_TLS_CHECK,
+  $ac_default_x86_tls_check,
+  [Define to 1 if you want to check x86 TLS relocation by default.])
+
 if test ${ac_default_elf_stt_common} = unset; then
   ac_default_elf_stt_common=0
 fi
index a9e43560aea5624f0c5333462ac3d4d43fce6c6f..9667061752d4044f1a002b63b691ebd2586b0f0a 100644 (file)
@@ -467,6 +467,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-x86-tls-check}.
+
 @cindex @samp{-malign-branch-boundary=} option, i386
 @cindex @samp{-malign-branch-boundary=} option, x86-64
 @item -malign-branch-boundary=@var{NUM}
index 75ad061b32c91f3e3f1be4073378505358c0b156..6710a56d64a7807d749f34d27fb08115441adcd4 100644 (file)
@@ -699,10 +699,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"
index a30173889345a9b2ea195e0aeca4d351f6595bc1..18befccf5fff9a864a98e0d6c29039ebc023b797 100644 (file)
@@ -37,8 +37,9 @@ 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"
+    run_list_test "x32-inval-tls" "-I${srcdir}/$subdir"
 
     set ASFLAGS "$old_ASFLAGS"
 }
index e2c461f24e8394142217636eca050c7e454047fc..84b6aaccc016b1ecf6cdf0a79a9bf31e6c1f4441 100644 (file)
@@ -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/ilp32/x32-inval-tls.l b/gas/testsuite/gas/i386/ilp32/x32-inval-tls.l
new file mode 100644 (file)
index 0000000..f3807c8
--- /dev/null
@@ -0,0 +1,38 @@
+.*: Assembler messages:
+.*:3: Error: @GOTTPOFF operator cannot be used with `kmovq'
+.*:4: Error: @TLSLD operator cannot be used with `kmovq'
+.*:7: Error: @TLSGD operator cannot be used with `add'
+.*:8: Error: @TLSGD operator requires `%rdi' as dest register
+.*:9: Error: @TLSGD operator requires `%rip' as base register
+.*:10: Error: @TLSGD operator requires base register
+.*:11: Error: @TLSGD operator requires `%rip' as base register
+.*:12: Error: @TLSGD operator requires `%rdi' as dest register
+.*:15: Error: @TLSLD operator cannot be used with `add'
+.*:16: Error: @TLSLD operator requires `%rdi' as dest register
+.*:17: Error: @TLSLD operator requires `%rip' as base register
+.*:18: Error: @TLSLD operator requires base register
+.*:19: Error: @TLSLD operator requires `%rip' as base register
+.*:20: Error: @TLSLD operator requires `%rdi' as dest register
+.*:23: Error: @TLSDESC operator cannot be used with `add'
+.*:24: Error: @TLSDESC operator requires `%rip' as base register
+.*:25: Error: @TLSDESC operator requires `%rip' as base register
+.*:27: Error: @TLSDESC operator requires 32-bit or 64-bit dest register
+.*:30: Error: @GOTTPOFF operator cannot be used with `sub'
+.*:31: Error: @GOTTPOFF operator cannot be used with `xor'
+.*:32: Error: @GOTTPOFF operator requires `%rip' as base register
+.*:33: Error: @GOTTPOFF operator requires `%rip' as base register
+.*:34: Error: @GOTTPOFF operator requires 32-bit or 64-bit dest register
+.*:35: Error: @GOTTPOFF operator can be used with `add', but format is wrong
+.*:36: Error: @GOTTPOFF operator can be used with `add', but format is wrong
+.*:37: Error: @GOTTPOFF operator can be used with `add', but format is wrong
+.*:38: Error: @GOTTPOFF operator can be used with `add', but format is wrong
+.*:39: Error: @GOTTPOFF operator requires `%rip' as base register
+.*:40: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*:41: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*:42: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*:43: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*:44: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*:48: Error: @TLSCALL operator cannot be used with `lea'
+.*:49: Error: @TLSCALL operator requires `%eax/%rax' as base register
+.*:49: Error: 0-byte relocation cannot be applied to 4-byte field
+.*:50: Error: `\*foo@tlscall\(%ax\)' is not a valid base/index expression
diff --git a/gas/testsuite/gas/i386/ilp32/x32-inval-tls.s b/gas/testsuite/gas/i386/ilp32/x32-inval-tls.s
new file mode 100644 (file)
index 0000000..b1d967f
--- /dev/null
@@ -0,0 +1 @@
+.include "../x86-64-inval-tls.s"
index ab4da5c730b094fa642d18b516e0ae8e8fa69ba9..ac7d136c1ac83811f1de493b3d15c7f882f042a5 100644 (file)
@@ -1,3 +1,4 @@
+#as: -mtls-check=no
 #objdump: -dw
 #name: x86-64 (ILP32) TLS
 
diff --git a/gas/testsuite/gas/i386/ilp32/x86-64-tls.d b/gas/testsuite/gas/i386/ilp32/x86-64-tls.d
new file mode 100644 (file)
index 0000000..a2261f5
--- /dev/null
@@ -0,0 +1,4 @@
+#source: ../x86-64-tls.s
+#objdump: -drw
+#name: x86-64 (ILP32) TLS
+#dump: ../x86-64-tls.d
index 98f7a29f1abd768bfdf993c58adfedc22dc488c5..e20ba7a43165b167797f8745bc67a5beecb97b30 100644 (file)
@@ -1,2 +1,70 @@
-.*: Assembler messages:
-.*:3: Error: @GOTNTPOFF operator cannot be used with `kmovd'
+.*ssembler messages:
+.* Error: @GOTNTPOFF operator cannot be used with `kmovd'
+.* Error: @TLSGD operator cannot be used with `add'
+.* Error: @TLSGD operator requires `%ebx' as index register
+.* Error: @TLSGD operator requires scale factor of 1
+.* Error: @TLSGD operator requires no base register
+.*: Error: @TLSGD operator requires `%eax' as dest register
+.*: Error: @TLSGD operator requires `%eax' as dest register
+.*: Error: @TLSGD operator requires `%eax' as base register
+.*: Error: @TLSGD operator requires 32-bit dest register
+.*: Error: @TLSLDM operator cannot be used with `add'
+.*: Error: @TLSLDM operator requires `%eax' as dest register
+.*: Error: @TLSLDM operator requires `%eax' as base register
+.*: Error: @TLSLDM operator requires no SIB
+.*: Error: @TLSLDM operator requires 32-bit dest register
+.*: Error: @TLSDESC operator cannot be used with `add'
+.*: Error: @TLSDESC operator requires `%ebx' as base register
+.*: Error: @TLSDESC operator requires no SIB
+.*: Error: @TLSDESC operator requires 32-bit dest register
+.*: Error: @INDNTPOFF operator cannot be used with `sub'
+.*: Error: @INDNTPOFF operator requires no base/index register
+.*: Error: @INDNTPOFF operator requires no base/index register
+.*: Error: @INDNTPOFF operator requires 32-bit dest register
+.*: Error: @INDNTPOFF operator can be used with `add', but format is wrong
+.*: Error: @INDNTPOFF operator can be used with `add', but format is wrong
+.*: Error: @INDNTPOFF operator can be used with `add', but format is wrong
+.*: Error: @INDNTPOFF operator can be used with `add', but format is wrong
+.*: Error: @INDNTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @INDNTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @INDNTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @INDNTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @INDNTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @GOTNTPOFF operator cannot be used with `lea'
+.*: Error: @GOTNTPOFF operator requires base register
+.*: Error: @GOTNTPOFF operator cannot be used with `lea'
+.*: Error: @GOTNTPOFF operator can be used with `sub', but format is wrong
+.*: Error: @GOTNTPOFF operator can be used with `sub', but format is wrong
+.*: Error: @GOTNTPOFF operator can be used with `sub', but format is wrong
+.*: Error: @GOTNTPOFF operator can be used with `sub', but format is wrong
+.*: Error: @GOTNTPOFF operator can be used with `add', but format is wrong
+.*: Error: @GOTNTPOFF operator can be used with `add', but format is wrong
+.*: Error: @GOTNTPOFF operator can be used with `add', but format is wrong
+.*: Error: @GOTNTPOFF operator can be used with `add', but format is wrong
+.*: Error: @GOTNTPOFF operator requires base register
+.*: Error: @GOTNTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @GOTNTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @GOTNTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @GOTNTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @GOTNTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @GOTTPOFF operator cannot be used with `lea'
+.*: Error: @GOTTPOFF operator requires base register
+.*: Error: @GOTTPOFF operator requires 32-bit dest register
+.*: Error: @GOTTPOFF operator can be used with `sub', but format is wrong
+.*: Error: @GOTTPOFF operator can be used with `sub', but format is wrong
+.*: Error: @GOTTPOFF operator can be used with `sub', but format is wrong
+.*: Error: @GOTTPOFF operator can be used with `sub', but format is wrong
+.*: Error: @GOTTPOFF operator can be used with `add', but format is wrong
+.*: Error: @GOTTPOFF operator can be used with `add', but format is wrong
+.*: Error: @GOTTPOFF operator can be used with `add', but format is wrong
+.*: Error: @GOTTPOFF operator requires base register
+.*: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*: Error: @TLSCALL operator cannot be used with `lea'
+.*: Error: @TLSCALL operator requires `%eax/%rax' as base register
+.*: Error: @TLSCALL operator requires no SIB
+.*: Error: 0-byte relocation cannot be applied to 4-byte field
+.*: Error: @TLSCALL operator requires `%eax/%rax' as base register
index ba0e1b81dc9064ec515ad6271fc5b7c82dbe22c8..067e9b4cbdfc97e9d1c6a48697ab8b9374bce6ea 100644 (file)
@@ -1,3 +1,85 @@
        .text
 # All the following should be illegal
        kmovd   foo@gotntpoff(%eax), %k0
+
+       /* Invalid testcase for R_386_TLS_GD.  */
+       addl foo@tlsgd(,%ebx,1), %eax
+       leal foo@tlsgd(,%ecx,1), %eax
+       leal foo@tlsgd(,%ebx,2), %eax
+       leal foo@tlsgd(%ecx,%ebx,1), %eax
+       leal foo@tlsgd(,%ebx,1), %ecx
+       leal foo@tlsgd(%ebx), %ecx
+       leal foo@tlsgd(%eax), %eax
+       lea foo@tlsgd(%ebx), %ax
+
+       /* Invalid testcase for R_386_TLS_LDM.  */
+       addl foo@tlsldm(%ebx), %eax
+       leal foo@tlsldm(%ebx), %ecx
+       leal foo@tlsldm(%eax), %eax
+       leal foo@tlsldm(,%ebx,1), %eax
+       lea foo@tlsldm(%ebx), %ax
+
+       /* Invalid testcase for R_386_TLS_GOTDESC.  */
+       addl x@tlsdesc(%ebx), %eax
+       leal x@tlsdesc(%ecx), %eax
+       leal x@tlsdesc(,%ecx,1), %eax
+       lea  x@tlsdesc(%ebx), %ax
+
+       /* Invalid testcase for R_386_TLS_IE.  */
+       subl foo@indntpoff, %ecx
+       addl foo@indntpoff(%ebx), %ecx
+       movl foo@indntpoff(%ebx), %ecx
+       add foo@indntpoff, %cx
+       addl $foo@indntpoff, %eax
+       addl %ecx, foo@indntpoff
+       addl $0x9090,foo@indntpoff
+       addl $0x90909090,foo@indntpoff
+       movl foo@indntpoff,%eax
+       movl %edx,foo@indntpoff(%eax)
+       movw %ss,foo@indntpoff(%eax)
+       movw foo@indntpoff(%eax),%ss
+       movl $0x90909090,foo@indntpoff(%eax)
+       movl $foo@indntpoff, %eax
+
+       /* Invalid testcase for R_386_TLS_GOTIE.  */
+       leal foo@gotntpoff(%ebx), %ecx
+       subl foo@gotntpoff(,%ebx,1), %ecx
+       lea foo@gotntpoff(%ebx), %cx
+       subl %ecx, foo@gotntpoff(%ebx)
+       subl $0x9090,foo@gotntpoff(%ebx)
+       subl $0x90909090,foo@gotntpoff(%eax)
+       subl $foo@gotntpoff, %eax
+       addl %ecx, foo@gotntpoff(%ebx)
+       addl $0x9090,foo@gotntpoff(%ebx)
+       addl $0x90909090,foo@gotntpoff(%eax)
+       addl $foo@gotntpoff, %eax
+       movl foo@gotntpoff,%eax
+       movl %edx,foo@gotntpoff(%eax)
+       movw %ss,foo@gotntpoff(%eax)
+       movw foo@gotntpoff(%eax),%ss
+       movl $0x90909090,foo@gotntpoff(%eax)
+       movl $foo@gotntpoff, %eax
+
+       /* Invalid testcase for R_386_TLS_IE_32.  */
+       leal foo@gottpoff(%ebx), %ecx
+       subl foo@gottpoff(,%ebx,1), %ecx
+       add foo@gottpoff(%ebx), %cx
+       subl %ecx, foo@gottpoff(%ebx)
+       subl $0x9090,foo@gottpoff(%ebx)
+       subl $0x90909090,foo@gottpoff(%eax)
+       subl $foo@gottpoff, %eax
+       addl %ecx, foo@gottpoff(%ebx)
+       addl $0x9090,foo@gottpoff(%ebx)
+       addl $0x90909090,foo@gottpoff(%eax)
+       movl foo@gottpoff,%eax
+       movl %edx,foo@gottpoff(%eax)
+       movw %ss,foo@gottpoff(%eax)
+       movw foo@gottpoff(%eax),%ss
+       movl $0x90909090,foo@gottpoff(%eax)
+       movl $foo@gottpoff, %eax
+
+       /* Invalid testcase for R_386_TLS_DESC_CALL.  */
+       leal foo@tlscall(%eax), %ebx
+       call *x@tlscall(%ebx)
+       call *x@tlscall(,%eax,1)
+       call *x@tlscall(%bx)
index 263a742022e1478028e5b8949b4fb79bea7e53a0..7d1b1ba2ae012432659a2d328dfa10cc0169866b 100644 (file)
@@ -1,4 +1,4 @@
-#as: -mrelax-relocations=yes
+#as: -mrelax-relocations=yes -mtls-check=no
 #objdump: -Drw
 #name: i386 relocs
 
index a96072d66fb69af56209c36c8fee76ad079b62ad..665ede6f264aded51cd2e3c8b80ffb1ed507572f 100644 (file)
@@ -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 (file)
index 0000000..adfe7ce
--- /dev/null
@@ -0,0 +1,25 @@
+#as:
+#objdump: -drw
+#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   3: R_386_TLS_GD foo
+\s*[a-f0-9]+:\s*8d 81 00 00 00 00[      ]+lea    0x0\(%ecx\),%eax      9: R_386_TLS_GD foo
+\s*[a-f0-9]+:\s*8d 83 00 00 00 00[      ]+lea    0x0\(%ebx\),%eax      f: R_386_TLS_LDM        foo
+\s*[a-f0-9]+:\s*8d 83 00 00 00 00[      ]+lea    0x0\(%ebx\),%eax      15: R_386_TLS_GOTDESC   x
+\s*[a-f0-9]+:\s*a1 00 00 00 00[         ]+mov    0x0,%eax      1a: R_386_TLS_IE        foo
+\s*[a-f0-9]+:\s*8b 1d 00 00 00 00[      ]+mov    0x0,%ebx      20: R_386_TLS_IE        foo
+\s*[a-f0-9]+:\s*03 15 00 00 00 00[      ]+add    0x0,%edx      26: R_386_TLS_IE        foo
+\s*[a-f0-9]+:\s*2b 8b 00 00 00 00[      ]+sub    0x0\(%ebx\),%ecx      2c: R_386_TLS_GOTIE     foo
+\s*[a-f0-9]+:\s*8b 8b 00 00 00 00[      ]+mov    0x0\(%ebx\),%ecx      32: R_386_TLS_GOTIE     foo
+\s*[a-f0-9]+:\s*03 8b 00 00 00 00[      ]+add    0x0\(%ebx\),%ecx      38: R_386_TLS_GOTIE     foo
+\s*[a-f0-9]+:\s*2b 8b 00 00 00 00[      ]+sub    0x0\(%ebx\),%ecx      3e: R_386_TLS_IE_32     foo
+\s*[a-f0-9]+:\s*8b 8b 00 00 00 00[      ]+mov    0x0\(%ebx\),%ecx      44: R_386_TLS_IE_32     foo
+\s*[a-f0-9]+:\s*03 8b 00 00 00 00[      ]+add    0x0\(%ebx\),%ecx      4a: R_386_TLS_IE_32     foo
+\s*[a-f0-9]+:\s*ff 10[  ]+call   \*\(%eax\)    4e: R_386_TLS_DESC_CALL foo
+#pass
diff --git a/gas/testsuite/gas/i386/tls.s b/gas/testsuite/gas/i386/tls.s
new file mode 100644 (file)
index 0000000..6c077ee
--- /dev/null
@@ -0,0 +1,31 @@
+# Check tls relocation 32-bit mode
+
+       .text
+_start:
+       /* R_386_TLS_GD.  */
+       leal foo@tlsgd(,%ebx,1), %eax
+       leal foo@tlsgd(%ecx), %eax
+
+       /* R_386_TLS_LDM.  */
+       leal foo@tlsldm(%ebx), %eax
+
+       /* R_386_TLS_GOTDESC.  */
+       leal x@tlsdesc(%ebx), %eax
+
+       /* R_386_TLS_IE.  */
+       movl foo@indntpoff, %eax
+       movl foo@indntpoff, %ebx
+       addl foo@indntpoff, %edx
+
+       /* R_386_TLS_GOTIE.  */
+       subl foo@gotntpoff(%ebx), %ecx
+       movl foo@gotntpoff(%ebx), %ecx
+       addl foo@gotntpoff(%ebx), %ecx
+
+       /* R_386_TLS_IE_32.  */
+       subl foo@gottpoff(%ebx), %ecx
+       movl foo@gottpoff(%ebx), %ecx
+       addl foo@gottpoff(%ebx), %ecx
+
+       /* R_386_TLS_DESC_CALL.  */
+       call *foo@tlscall(%eax)
index da8ac19f8699f2dbe16d62727e89417d11dee3c3..134d96bf38303dcec138221d2cce05e5d6cbec39 100644 (file)
@@ -1,3 +1,39 @@
 .*: Assembler messages:
 .*:3: Error: @GOTTPOFF operator cannot be used with `kmovq'
 .*:4: Error: @TLSLD operator cannot be used with `kmovq'
+.*:7: Error: @TLSGD operator cannot be used with `add'
+.*:8: Error: @TLSGD operator requires `%rdi' as dest register
+.*:9: Error: @TLSGD operator requires `%rip' as base register
+.*:10: Error: @TLSGD operator requires base register
+.*:11: Error: @TLSGD operator requires `%rip' as base register
+.*:12: Error: @TLSGD operator requires `%rdi' as dest register
+.*:15: Error: @TLSLD operator cannot be used with `add'
+.*:16: Error: @TLSLD operator requires `%rdi' as dest register
+.*:17: Error: @TLSLD operator requires `%rip' as base register
+.*:18: Error: @TLSLD operator requires base register
+.*:19: Error: @TLSLD operator requires `%rip' as base register
+.*:20: Error: @TLSLD operator requires `%rdi' as dest register
+.*:23: Error: @TLSDESC operator cannot be used with `add'
+.*:24: Error: @TLSDESC operator requires `%rip' as base register
+.*:25: Error: @TLSDESC operator requires `%rip' as base register
+.*:26: Error: @TLSDESC operator requires 64-bit dest register
+.*:27: Error: @TLSDESC operator requires 64-bit dest register
+.*:30: Error: @GOTTPOFF operator cannot be used with `sub'
+.*:31: Error: @GOTTPOFF operator cannot be used with `xor'
+.*:32: Error: @GOTTPOFF operator requires `%rip' as base register
+.*:33: Error: @GOTTPOFF operator requires `%rip' as base register
+.*:34: Error: @GOTTPOFF operator requires 64-bit dest register
+.*:35: Error: @GOTTPOFF operator can be used with `add', but format is wrong
+.*:36: Error: @GOTTPOFF operator can be used with `add', but format is wrong
+.*:37: Error: @GOTTPOFF operator can be used with `add', but format is wrong
+.*:38: Error: @GOTTPOFF operator can be used with `add', but format is wrong
+.*:39: Error: @GOTTPOFF operator requires `%rip' as base register
+.*:40: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*:41: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*:42: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*:43: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*:44: Error: @GOTTPOFF operator can be used with `mov', but format is wrong
+.*:48: Error: @TLSCALL operator cannot be used with `lea'
+.*:49: Error: @TLSCALL operator requires `%eax/%rax' as base register
+.*:49: Error: 0-byte relocation cannot be applied to 4-byte field
+.*:50: Error: `\*foo@tlscall\(%ax\)' is not a valid base/index expression
index 71e19272ba90d76bfe33a7fbebf9b35ca1bcedc6..8783530a423dae5e0a5f8b7e025b55b58690c471 100644 (file)
@@ -2,3 +2,49 @@
 # All the following should be illegal
        kmovq   foo@gottpoff(%rip), %k0
        kmovq   foo@tlsld(%rip), %k0
+
+       /* Invalid testcase for R_X86_64_TLSGD.  */
+       addq foo@tlsgd(%rip), %rdi
+       leaq foo@tlsgd(%rip), %rax
+       leaq foo@tlsgd(%rax), %rdi
+       leaq foo@tlsgd(,%rax,1), %rdi
+       leaq foo@tlsgd(%eip), %rdi
+       leal foo@tlsgd(%rip), %edi
+
+       /* Invalid testcase for R_X86_64_TLSLD.  */
+       addq foo@tlsld(%rip), %rdi
+       leaq foo@tlsld(%rip), %rax
+       leaq foo@tlsld(%rax), %rdi
+       leaq foo@tlsld(,%rax,1), %rdi
+       leaq foo@tlsld(%eip), %rdi
+       leal foo@tlsld(%rip), %edi
+
+       /* Invalid testcase for R_X86_64_GOTPC32_TLSDESC.  */
+       addq x@tlsdesc(%rip), %rax
+       leaq x@tlsdesc(%rbx), %rax
+       lea  x@tlsdesc(%eip), %rdi
+       lea  x@tlsdesc(%rip), %eax
+       lea  x@tlsdesc(%rip), %ax
+
+       /* Invalid testcase for R_X86_64_GOTTPOFF.  */
+       subq foo@gottpoff(%rip), %r12
+       xorq foo@gottpoff(%rip), %rax
+       addq foo@gottpoff(%rbx), %rax
+       addq foo@gottpoff(%eip), %rax
+       add  foo@gottpoff(%rip), %ax
+       addq %rax, foo@gottpoff(%rip)
+       addl $0x90909090, foo@gottpoff(%rip)
+       add  $0x90, foo@gottpoff(%rip), %rax
+       add  $0xffffffffffffffff, foo@gottpoff(%rip), %rax
+       movq foo@gottpoff(%rbx), %rax
+       movq %rax, foo@gottpoff(%rip)
+       mov  %ss,foo@gottpoff(%rip)
+       mov  foo@gottpoff(%rip),%ss
+       movl $0x90909090,foo@gottpoff(%rip)
+       mov  $foo@gottpoff, %rax
+
+
+       /* Invalid testcase for R_X86_64_TLSDESC_CALL.  */
+       leaq foo@tlscall(%rax), %rbx
+       call *foo@tlscall(%rip)
+       call *foo@tlscall(%ax)
diff --git a/gas/testsuite/gas/i386/x86-64-tls.d b/gas/testsuite/gas/i386/x86-64-tls.d
new file mode 100644 (file)
index 0000000..1c30496
--- /dev/null
@@ -0,0 +1,25 @@
+#as:
+#objdump: -drw
+#name: Check tls relocation x86-64
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+ +[a-f0-9]+:   48 8d 3d 00 00 00 00    lea    0x0\(%rip\),%rdi        # 7 <_start\+0x7>        3: R_X86_64_TLSGD       foo-0x4
+ +[a-f0-9]+:   48 8d 3d 00 00 00 00    lea    0x0\(%rip\),%rdi        # e <_start\+0xe>        a: R_X86_64_TLSLD       foo-0x4
+ +[a-f0-9]+:   48 8d 05 00 00 00 00    lea    0x0\(%rip\),%rax        # 15 <_start\+0x15>      11: R_X86_64_GOTPC32_TLSDESC    x-0x4
+ +[a-f0-9]+:   4c 03 25 00 00 00 00    add    0x0\(%rip\),%r12        # 1c <_start\+0x1c>      18: R_X86_64_GOTTPOFF   foo-0x4
+ +[a-f0-9]+:   48 8b 05 00 00 00 00    mov    0x0\(%rip\),%rax        # 23 <_start\+0x23>      1f: R_X86_64_GOTTPOFF   foo-0x4
+ +[a-f0-9]+:   d5 48 03 05 00 00 00 00         add    0x0\(%rip\),%r16        # 2b <_start\+0x2b>      27: R_X86_64_CODE_4_GOTTPOFF    foo-0x4
+ +[a-f0-9]+:   d5 48 8b 25 00 00 00 00         mov    0x0\(%rip\),%r20        # 33 <_start\+0x33>      2f: R_X86_64_CODE_4_GOTTPOFF    foo-0x4
+ +[a-f0-9]+:   62 64 bc 18 01 35 00 00 00 00   add    %r30,0x0\(%rip\),%r8        # 3d <_start\+0x3d>  39: R_X86_64_CODE_6_GOTTPOFF    foo-0x4
+ +[a-f0-9]+:   62 f4 dc 10 03 05 00 00 00 00   add    0x0\(%rip\),%rax,%r20        # 47 <_start\+0x47> 43: R_X86_64_CODE_6_GOTTPOFF    foo-0x4
+ +[a-f0-9]+:   62 e4 fc 0c 03 05 00 00 00 00   \{nf\} add 0x0\(%rip\),%r16        # 51 <_start\+0x51>  4d: R_X86_64_CODE_6_GOTTPOFF    foo-0x4
+ +[a-f0-9]+:   62 64 bc 1c 01 35 00 00 00 00   \{nf\} add %r30,0x0\(%rip\),%r8        # 5b <_start\+0x5b>      57: R_X86_64_CODE_6_GOTTPOFF    foo-0x4
+ +[a-f0-9]+:   62 f4 dc 14 03 05 00 00 00 00   \{nf\} add 0x0\(%rip\),%rax,%r20        # 65 <_start\+0x65>     61: R_X86_64_CODE_6_GOTTPOFF    foo-0x4
+ +[a-f0-9]+:   ff 10                   call   \*\(%rax\)       65: R_X86_64_TLSDESC_CALL       x
+ +[a-f0-9]+:   67 ff 10                call   \*\(%eax\)       67: R_X86_64_TLSDESC_CALL       x
+#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 (file)
index 0000000..7c3bd4a
--- /dev/null
@@ -0,0 +1,27 @@
+# Check tls relocation 64-bit mode
+
+       .text
+_start:
+       /* R_X86_64_TLSGD.  */
+       leaq foo@tlsgd(%rip), %rdi
+
+       /* R_X86_64_TLSLD.  */
+       leaq foo@tlsld(%rip), %rdi
+
+       /* R_X86_64_GOTPC32_TLSDESC.  */
+       leaq     x@tlsdesc(%rip), %rax
+
+       /* R_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
+
+       /* R_X86_64_TLSDESC_CALL.  */
+       call *x@tlscall(%rax)
+       call *x@tlscall(%eax)
index 86e7f4a75b3add31bd86daed36fda3689c3fb8fb..740f5268de36d61a2570a23c9f0c8318cdba6317 100644 (file)
@@ -653,7 +653,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"
index 2a70e81c4442891b4cfd83d15c3d559db52fc277..0c853ab0a671ccebe05d2c375b2fd23f71dd082b 100644 (file)
@@ -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
index bbf93bef7674ec2f5a8768ad79d50b576938b9b9..99e1b18b1eaf4b306666bf549f596cbbcaf157a6 100644 (file)
@@ -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 with EAX register only
index f2c29d880f2cf9cc106b73b28f237d88c283b0ed..4bb99c4422b30f2119f86bf825e055ac1aec7796 100644 (file)
@@ -1,5 +1,5 @@
 #source: tlsgdesc2.s
 #name: TLS GDesc call (indirect CALL)
-#as: --32
+#as: --32 -mtls-check=no
 #ld: -shared -melf_i386
 #error: .*: relocation R_386_TLS_DESC_CALL against `foo' must be used in indirect CALL with EAX register only
index 9f9e63029d6a6fc88d2114abe8454d7d1bfc2caa..4e7dc6ea56e7761c7a79b7a97234e45c43df7248 100644 (file)
@@ -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
index 506f1a026059402185b5880cb68aaa6047a2817d..6bfc78e0b4912e1ca66c6ebc24ecf8e96491ef23 100644 (file)
@@ -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
index a516d00266023fa22184be6a5a792adf4401c770..98293f4b36ac36058f4c5773294ca71f6b055591 100644 (file)
@@ -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
index d3447182e19841c22a5686073376694f1d0dd592..4e9c9a8f74a280ec173b90c318e18115c83a6e31 100644 (file)
@@ -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
index bbf22ebeafe45902e1019b0b9e32e3b82b3d89dd..955884885d70c47fba6ea479697cc505a63a07a8 100644 (file)
@@ -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
index c882c877ae392621596bac378deb0551eb516df4..ccaa525c74b54051bdc18d598ce68ef686e4506e 100644 (file)
@@ -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 with RAX register only
index 6a0158b44b7f23243cc78e141ab3a0d8a8db8c90..0876993bca3700904ff16d4c5fb3485961d04c5a 100644 (file)
@@ -1,5 +1,5 @@
 #source: tlsdesc4.s
 #name: TLS GDesc call (indirect CALL)
-#as: --64
+#as: --64 -mtls-check=no
 #ld: -shared -melf_x86_64
 #error: .*: relocation R_X86_64_TLSDESC_CALL against `foo' must be used in indirect CALL with RAX register only
index bf8a8198b5bbde139597cb15218f407d505843de..2e6d41ccf616e7eaaf1a3b5909fe24ecff4faea9 100644 (file)
@@ -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
index 49d8464fbaf08ecab6bd800a1ea029e1f2b8e8e9..b59cc6429dee99914ded23417aef1e9c9a23387e 100644 (file)
@@ -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
index 29de1cebf8e314dd4619bf9dcf77e9843bf06791..d7ab5ab7b323bdb8c2207e6588833204d5838328 100644 (file)
@@ -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