[PATCH V5] x86: Add tls check in gas

Cui, Lili lili.cui@intel.com
Thu Sep 19 06:58:37 GMT 2024



> -----Original Message-----
> From: H.J. Lu <hjl.tools@gmail.com>
> Sent: Thursday, September 19, 2024 2:50 PM
> To: Cui, Lili <lili.cui@intel.com>
> Cc: Beulich, Jan <JBeulich@suse.com>; binutils@sourceware.org
> Subject: Re: [PATCH V5] x86: Add tls check in gas
> 
> On Thu, Sep 19, 2024 at 2:38 PM Cui, Lili <lili.cui@intel.com> wrote:
> >
> > 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. 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.
> >
> > ----------------------
> > Changes in V5:
> >
> > 1. Separated the register size judgment of X32 and ILP64.
> > 2. Added new x32 TLS relocation tests.
> > 3. Adjusted comments and error types.
> >
> > ----------------------
> >
> > 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.
> 
> LIne too long.
> 

Done.

> >         (x86_check_tls_relocation): Added a new function to check tls relocation.
> 
> Line too long.
> 

Done.

> Also please use TLS, instead of tls, in the commit message and ChangeLog.
> 
> It looks OK to me.  Please give Jan a day to comment before committing
> it.
> 

Ok.

Thanks,
Lili.

> Thanks.
> 
> >         (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: 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/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.
> > ---
> >  gas/config.in                                |   3 +
> >  gas/config/tc-i386.c                         | 438 ++++++++++++++++++-
> >  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       |   3 +-
> >  gas/testsuite/gas/i386/ilp32/reloc64.d       |   2 +-
> >  gas/testsuite/gas/i386/ilp32/x32-inval-tls.l |  38 ++
> >  gas/testsuite/gas/i386/ilp32/x32-inval-tls.s |   1 +
> >  gas/testsuite/gas/i386/ilp32/x32-tls.d       |   1 +
> >  gas/testsuite/gas/i386/ilp32/x86-64-tls.d    |   4 +
> >  gas/testsuite/gas/i386/inval-tls.l           |  72 ++-
> >  gas/testsuite/gas/i386/inval-tls.s           |  82 ++++
> >  gas/testsuite/gas/i386/reloc32.d             |   2 +-
> >  gas/testsuite/gas/i386/reloc64.d             |   2 +-
> >  gas/testsuite/gas/i386/tls.d                 |  25 ++
> >  gas/testsuite/gas/i386/tls.s                 |  31 ++
> >  gas/testsuite/gas/i386/x86-64-inval-tls.l    |  36 ++
> >  gas/testsuite/gas/i386/x86-64-inval-tls.s    |  46 ++
> >  gas/testsuite/gas/i386/x86-64-tls.d          |  25 ++
> >  gas/testsuite/gas/i386/x86-64-tls.s          |  27 ++
> >  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/tlsgdesc3.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/tlsdesc5.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 +-
> >  36 files changed, 879 insertions(+), 45 deletions(-)
> >  create mode 100644 gas/testsuite/gas/i386/ilp32/x32-inval-tls.l
> >  create mode 100644 gas/testsuite/gas/i386/ilp32/x32-inval-tls.s
> >  create mode 100644 gas/testsuite/gas/i386/ilp32/x86-64-tls.d
> >  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..c32b46b93f5 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 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
> > diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
> > index 4739a6d0c21..2b6b5ab5538 100644
> > --- a/gas/config/tc-i386.c
> > +++ b/gas/config/tc-i386.c
> > @@ -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,
> > @@ -6357,6 +6387,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.  */
> > @@ -6695,6 +7075,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)
> > @@ -6705,28 +7100,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.  */
> > @@ -12496,6 +12869,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)
> > @@ -16229,6 +16603,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[] =
> >  {
> > @@ -16275,6 +16650,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);
> > @@ -16831,6 +17207,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;
> > @@ -17073,6 +17457,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"));
> > diff --git a/gas/configure b/gas/configure
> > index 6b96d3a4e0c..be37f31e1af 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_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
> > diff --git a/gas/configure.ac b/gas/configure.ac
> > index 6b978aae3f7..bf3f9b5b6fa 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 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
> > diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
> > index a9e43560aea..9667061752d 100644
> > --- a/gas/doc/c-i386.texi
> > +++ b/gas/doc/c-i386.texi
> > @@ -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}
> > diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
> > index 75ad061b32c..6710a56d64a 100644
> > --- a/gas/testsuite/gas/i386/i386.exp
> > +++ b/gas/testsuite/gas/i386/i386.exp
> > @@ -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"
> > diff --git a/gas/testsuite/gas/i386/ilp32/ilp32.exp
> b/gas/testsuite/gas/i386/ilp32/ilp32.exp
> > index a3017388934..18befccf5ff 100644
> > --- a/gas/testsuite/gas/i386/ilp32/ilp32.exp
> > +++ b/gas/testsuite/gas/i386/ilp32/ilp32.exp
> > @@ -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"
> >  }
> > 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/ilp32/x32-inval-tls.l
> b/gas/testsuite/gas/i386/ilp32/x32-inval-tls.l
> > new file mode 100644
> > index 00000000000..f3807c8b69d
> > --- /dev/null
> > +++ b/gas/testsuite/gas/i386/ilp32/x32-inval-tls.l
> > @@ -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
> > index 00000000000..b1d967f88db
> > --- /dev/null
> > +++ b/gas/testsuite/gas/i386/ilp32/x32-inval-tls.s
> > @@ -0,0 +1 @@
> > +.include "../x86-64-inval-tls.s"
> > diff --git a/gas/testsuite/gas/i386/ilp32/x32-tls.d
> b/gas/testsuite/gas/i386/ilp32/x32-tls.d
> > index ab4da5c730b..ac7d136c1ac 100644
> > --- a/gas/testsuite/gas/i386/ilp32/x32-tls.d
> > +++ b/gas/testsuite/gas/i386/ilp32/x32-tls.d
> > @@ -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
> > index 00000000000..a2261f5cdcb
> > --- /dev/null
> > +++ b/gas/testsuite/gas/i386/ilp32/x86-64-tls.d
> > @@ -0,0 +1,4 @@
> > +#source: ../x86-64-tls.s
> > +#objdump: -drw
> > +#name: x86-64 (ILP32) TLS
> > +#dump: ../x86-64-tls.d
> > diff --git a/gas/testsuite/gas/i386/inval-tls.l b/gas/testsuite/gas/i386/inval-tls.l
> > index 98f7a29f1ab..e20ba7a4316 100644
> > --- a/gas/testsuite/gas/i386/inval-tls.l
> > +++ b/gas/testsuite/gas/i386/inval-tls.l
> > @@ -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
> > diff --git a/gas/testsuite/gas/i386/inval-tls.s b/gas/testsuite/gas/i386/inval-tls.s
> > index ba0e1b81dc9..067e9b4cbdf 100644
> > --- a/gas/testsuite/gas/i386/inval-tls.s
> > +++ b/gas/testsuite/gas/i386/inval-tls.s
> > @@ -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)
> > 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..adfe7ce9551
> > --- /dev/null
> > +++ b/gas/testsuite/gas/i386/tls.d
> > @@ -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
> > index 00000000000..6c077ee48fb
> > --- /dev/null
> > +++ b/gas/testsuite/gas/i386/tls.s
> > @@ -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)
> > diff --git a/gas/testsuite/gas/i386/x86-64-inval-tls.l
> b/gas/testsuite/gas/i386/x86-64-inval-tls.l
> > index da8ac19f869..134d96bf383 100644
> > --- a/gas/testsuite/gas/i386/x86-64-inval-tls.l
> > +++ b/gas/testsuite/gas/i386/x86-64-inval-tls.l
> > @@ -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
> > diff --git a/gas/testsuite/gas/i386/x86-64-inval-tls.s
> b/gas/testsuite/gas/i386/x86-64-inval-tls.s
> > index 71e19272ba9..8783530a423 100644
> > --- a/gas/testsuite/gas/i386/x86-64-inval-tls.s
> > +++ b/gas/testsuite/gas/i386/x86-64-inval-tls.s
> > @@ -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
> > index 00000000000..1c30496e227
> > --- /dev/null
> > +++ b/gas/testsuite/gas/i386/x86-64-tls.d
> > @@ -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
> > index 00000000000..7c3bd4a982c
> > --- /dev/null
> > +++ b/gas/testsuite/gas/i386/x86-64-tls.s
> > @@ -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)
> > diff --git a/gas/testsuite/gas/i386/x86-64.exp b/gas/testsuite/gas/i386/x86-
> 64.exp
> > index 86e7f4a75b3..740f5268de3 100644
> > --- a/gas/testsuite/gas/i386/x86-64.exp
> > +++ b/gas/testsuite/gas/i386/x86-64.exp
> > @@ -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"
> > 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 bbf93bef767..99e1b18b1ea 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 with EAX register only
> > diff --git a/ld/testsuite/ld-i386/tlsgdesc3.d b/ld/testsuite/ld-i386/tlsgdesc3.d
> > index f2c29d880f2..4bb99c4422b 100644
> > --- a/ld/testsuite/ld-i386/tlsgdesc3.d
> > +++ b/ld/testsuite/ld-i386/tlsgdesc3.d
> > @@ -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
> > 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 c882c877ae3..ccaa525c74b 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 with RAX register only
> > diff --git a/ld/testsuite/ld-x86-64/tlsdesc5.d b/ld/testsuite/ld-x86-64/tlsdesc5.d
> > index 6a0158b44b7..0876993bca3 100644
> > --- a/ld/testsuite/ld-x86-64/tlsdesc5.d
> > +++ b/ld/testsuite/ld-x86-64/tlsdesc5.d
> > @@ -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
> > 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
> >
> 
> 
> --
> H.J.


More information about the Binutils mailing list