[PATCH v2] x86: Add tls check in gas
H.J. Lu
hjl.tools@gmail.com
Fri Sep 6 13:51:35 GMT 2024
On Fri, Sep 6, 2024 at 6:07 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Fri, Sep 6, 2024 at 5:34 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Thu, Sep 5, 2024 at 1:57 AM Cui, Lili <lili.cui@intel.com> wrote:
> > >
> > > Sorry, added v2 to the patch name
> > >
> > > ---
> > > 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.
> > >
> > > ---
> > > V2:
> > > 1. Add format checks for each operator. And add a function to report errors.
> > > 2. Replace DEFAULT_TLS_CHECK with DEFAULT_X86_TLS_CHECK, and all related names.
> > > 3. Add more invalid test cases.
> > > 4. Remove the handling of "call *x@tlsdesc(%rax)", which is now illegal.
> > > 5. Add new INSTANCE RegDI
> > > 6. Use option drw for objdump.
> > > ---
> > >
> > > gas/ChangeLog:
> > >
> > > PR gas/32022
> > > * config.in: Regenerate.
> > > * config/tc-i386.c (_BFD_MAKE_TABLE_bfd_reloc_code_real): New.
> > > (x86_check_tls_relocation): Added a new function to check tls relocation.
> > > (i386_assemble): Handle x86_check_tls_relocation.
> > > (OPTION_MTLS_CHECK): Added a new option to contrl tls check.
> > > (struct option): Ditto.
> > > (md_parse_option): Ditto.
> > > (md_show_usage): Ditto.
> > > * configure: Added a new option to check tls relocation by default.
> > > * configure.ac: Ditto.
> > > * doc/c-i386.texi: Ditto.
> > > * testsuite/gas/i386/i386.exp: Added new tests.
> > > * testsuite/gas/i386/ilp32/ilp32.exp: Ditto.
> > > * testsuite/gas/i386/ilp32/reloc64.d: Disable tls check for it.
> > > * testsuite/gas/i386/inval-tls.l: Added more test cases.
> > > * testsuite/gas/i386/inval-tls.s: Ditto.
> > > * testsuite/gas/i386/reloc32.d: Disable tls check for it.
> > > * testsuite/gas/i386/reloc64.d: Ditto.
> > > * testsuite/gas/i386/x86-64-inval-tls.l: Added more test cases.
> > > * testsuite/gas/i386/x86-64-inval-tls.s: Ditto.
> > > * testsuite/gas/i386/x86-64.exp: Added new tests.
> > > * testsuite/gas/i386/tls.d: New test.
> > > * testsuite/gas/i386/tls.s: Ditto.
> > > * testsuite/gas/i386/x86-64-tls.d: Ditto.
> > > * testsuite/gas/i386/x86-64-tls.s: Ditto.
> > >
> > > opcodes/ChangeLog:
> > >
> > > PR gas/32022
> > > * i386-gen.c: Added new INSTANCE RegDI.
> > > * i386-opc.h (enum operand_instance): Ditto.
> > > * i386-reg.tbl: Added RegDI to rdi.
> > >
> > > 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 | 348 ++++++++++++++++++++--
> > > gas/configure | 26 +-
> > > gas/configure.ac | 18 ++
> > > gas/doc/c-i386.texi | 10 +
> > > gas/testsuite/gas/i386/i386.exp | 3 +-
> > > gas/testsuite/gas/i386/ilp32/ilp32.exp | 2 +-
> > > gas/testsuite/gas/i386/ilp32/reloc64.d | 2 +-
> > > gas/testsuite/gas/i386/inval-tls.l | 28 ++
> > > gas/testsuite/gas/i386/inval-tls.s | 42 +++
> > > 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 | 17 ++
> > > gas/testsuite/gas/i386/x86-64-inval-tls.s | 26 ++
> > > gas/testsuite/gas/i386/x86-64-tls.d | 29 ++
> > > gas/testsuite/gas/i386/x86-64-tls.s | 31 ++
> > > gas/testsuite/gas/i386/x86-64.exp | 3 +-
> > > ld/testsuite/ld-i386/tlsgdesc1.d | 2 +-
> > > ld/testsuite/ld-i386/tlsgdesc2.d | 2 +-
> > > ld/testsuite/ld-i386/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 +-
> > > opcodes/i386-gen.c | 1 +
> > > opcodes/i386-opc.h | 1 +
> > > opcodes/i386-reg.tbl | 2 +-
> > > 35 files changed, 634 insertions(+), 44 deletions(-)
> > > create mode 100644 gas/testsuite/gas/i386/tls.d
> > > create mode 100644 gas/testsuite/gas/i386/tls.s
> > > create mode 100644 gas/testsuite/gas/i386/x86-64-tls.d
> > > create mode 100644 gas/testsuite/gas/i386/x86-64-tls.s
> > >
> > > diff --git a/gas/config.in b/gas/config.in
> > > index a1f83499332..3f199d5b4a6 100644
> > > --- a/gas/config.in
> > > +++ b/gas/config.in
> > > @@ -60,6 +60,9 @@
> > > /* Define default value for RISC-V -mpriv-spec */
> > > #undef DEFAULT_RISCV_PRIV_SPEC
> > >
> > > +/* Define to 1 if you want to check tls relocation by default. */
> > > +#undef DEFAULT_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 a9d3536429b..a0222580106 100644
> > > --- a/gas/config/tc-i386.c
> > > +++ b/gas/config/tc-i386.c
> > > @@ -274,6 +274,23 @@ enum i386_error
> > > internal_error,
> > > };
> > >
> > > +enum x86_tls_error_type
> > > +{
> > > + x86_tls_error_none,
Add x86_tls_error_continue.
> > > + x86_tls_error_insn,
> > > + x86_tls_error_sib,
> > > + x86_tls_error_no_base_reg,
> > > + x86_tls_error_require_no_base_index_reg,
> > > + x86_tls_error_base_reg_name,
> > > + x86_tls_error_index_RegB,
> > > + x86_tls_error_RegA,
> > > + x86_tls_error_RegB,
> > > + x86_tls_error_RegIP,
> > > + x86_tls_error_dest_RegA,
> > > + x86_tls_error_dest_RegDI,
> > > + x86_tls_error_scale_factor
> > > +};
> > > +
> > > struct _i386_insn
> > > {
Add
bool has_gotrel;
and set it to true for relocation from the gotrel array.
> > > /* TM holds the template for the insn were currently assembling. */
> > > @@ -717,6 +734,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,
> > > @@ -6318,6 +6338,284 @@ 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 (unsigned int r_type)
>
> Please use enum bfd_reloc_code_real r_type.
>
> > > +{
> > > + switch (r_type)
> > > + {
> > > + case BFD_RELOC_386_TLS_GOTDESC:
> > > + /* Check transition from GDesc access model:
> > > +
> > > + leal x@tlsdesc(%ebx), %reg --> Memory reg must be %ebx and
> > > + SIB is not supported.
> > > + */
> > > + if (i.tm.mnem_off != MN_lea)
> > > + return x86_tls_error_insn;
> > > + else if (i.index_reg)
> > > + return x86_tls_error_sib;
> > > + else if (!i.base_reg)
> > > + return x86_tls_error_no_base_reg;
> > > + else if (i.base_reg->reg_type.bitfield.instance != RegB)
> > > + return x86_tls_error_RegB;
> > > + break;
> > > +
> > > + case BFD_RELOC_386_TLS_GD:
> > > + /* Check transition from GD access model:
> > > +
> > > + leal foo@tlsgd(,%ebx,1), %eax --> Only this fixed format is supported.
> > > + leal foo@tlsgd(%reg), %eax --> Dest reg must be '%eax'
> > > + Memory reg can't be %eax.
> > > + */
> > > + if (i.tm.mnem_off != MN_lea)
> > > + return x86_tls_error_insn;
> > > + else if (i.index_reg)
> > > + {
> > > + if (i.base_reg)
> > > + return x86_tls_error_base_reg_name;
> > > + if (i.index_reg->reg_type.bitfield.instance != RegB)
> > > + return x86_tls_error_index_RegB;
> > > + else if (i.types[1].bitfield.instance != Accum)
> > > + return x86_tls_error_dest_RegA;
> > > + else 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_RegA;
> > > + else if (i.types[1].bitfield.instance != Accum)
> > > + return x86_tls_error_dest_RegA;
> > > + }
> > > + break;
> > > +
> > > + case BFD_RELOC_386_TLS_LDM:
> > > + /* Check transition from LDM access model:
> > > +
> > > + leal foo@tlsldm(%reg), %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;
> > > + else if (i.index_reg)
> > > + return x86_tls_error_sib;
> > > + else if (!i.base_reg)
> > > + return x86_tls_error_no_base_reg;
> > > + else if (i.base_reg->reg_type.bitfield.instance == Accum)
> > > + return x86_tls_error_RegA;
> > > + else if (i.types[1].bitfield.instance != Accum)
> > > + return x86_tls_error_dest_RegA;
> > > + break;
> > > +
> > > + case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
> > > + /* Check transition from GOTPC32 TLSDESC access model:
> > > +
> > > + --- LP64 mode ---
> > > + leaq x@tlsdesc(%rip), %rax --> Memory reg must be %rip.
> > > +
> > > + --- X32 mode ---
> > > + rex leal x@tlsdesc(%rip), %eax --> Memory reg must be %rip.
> > > +
> > > + */
> > > + if (i.tm.mnem_off != MN_lea)
> > > + return x86_tls_error_insn;
> > > + else if (!i.base_reg)
> > > + return x86_tls_error_no_base_reg;
> > > + else if (i.base_reg->reg_num != RegIP)
> > > + return x86_tls_error_RegIP;
> > > + break;
> > > +
> > > + case BFD_RELOC_X86_64_TLSGD:
> > > + /* Check transition from GD access model:
> > > +
> > > + leaq foo@tlsgd(%rip), %rdi --> Only this fixed format is supported.
> > > + */
> > > + case BFD_RELOC_X86_64_TLSLD:
> > > + /* Check transition from 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;
> > > + else if (!i.base_reg)
> > > + return x86_tls_error_no_base_reg;
> > > + else if (i.base_reg->reg_num != RegIP)
> > > + return x86_tls_error_RegIP;
> > > + else if (i.types[1].bitfield.instance != RegDI)
>
> Use
>
> else if (i.types[1].bitfield.class != Reg
> || !i.op[1].regs->reg_type.bitfield.qword
> || i.op[1].regs->reg_num != EDI_REG_NUM)
> return x86_tls_error_dest_RegDI;
>
> > > + return x86_tls_error_dest_RegDI;
> > > + break;
> > > +
> > > + case BFD_RELOC_386_TLS_GOTIE:
> > > + /* Check transition from GOTIE access model:
> > > +
> > > + subl foo@gotntpoff(%reg1), %reg2
> > > + movl foo@gotntpoff(%reg1), %reg2
> > > + addl foo@gotntpoff(%reg1), %reg2
> > > +
> > > + Memory operand: SIB is not supported.
> > > + */
> > > + case BFD_RELOC_386_TLS_IE_32:
> > > + /* Check transition from IE_32 access model:
> > > +
> > > + subl foo@gottpoff(%reg1), %reg2
> > > + movl foo@gottpoff(%reg1), %reg2
> > > + addl foo@gottpoff(%reg1), %reg2
> > > +
> > > + 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;
> > > + else if (!i.base_reg)
> > > + return x86_tls_error_no_base_reg;
> > > + else if (i.index_reg)
> > > + return x86_tls_error_sib;
> > > + break;
> > > +
> > > + case BFD_RELOC_386_TLS_IE:
> > > + /* Check transition from IE access model:
> > > +
> > > + movl foo@indntpoff, %reg --> Mod == 00 && r/m == 5
> > > + addl foo@indntpoff, %reg --> Mod == 00 && r/m == 5
> > > + */
> > > + if (i.tm.mnem_off != MN_add && i.tm.mnem_off != MN_mov)
> > > + return x86_tls_error_insn;
> > > + else if (i.base_reg || i.index_reg)
> > > + return x86_tls_error_require_no_base_index_reg;
> > > + break;
> > > +
> > > + case BFD_RELOC_X86_64_GOTTPOFF:
> > > + /* Check transition from GOTTPOFF access model:
> > > +
> > > + mov foo@gottpoff(%rip), %reg --> Memory Reg must be %rip.
> > > + add foo@gottpoff(%rip), %reg --> Memory Reg must be %rip.
> > > + */
> > > + if (i.tm.mnem_off != MN_add && i.tm.mnem_off != MN_mov)
> > > + return x86_tls_error_insn;
> > > + else if (!i.base_reg)
> > > + return x86_tls_error_no_base_reg;
> > > + else if (i.base_reg->reg_num != RegIP)
> > > + return x86_tls_error_RegIP;
> > > + break;
> > > +
> > > + case BFD_RELOC_386_TLS_DESC_CALL:
> > > + /* Check transition from GDesc access model:
> > > +
> > > + call *x@tlscall(%eax) --> Memory reg must be %eax and
> > > + SIB is not supported.
> > > + */
> > > + if (i.tm.mnem_off != MN_call)
> > > + return x86_tls_error_insn;
> > > + else if (i.index_reg)
> > > + return x86_tls_error_sib;
> > > + else if (!i.base_reg)
> > > + return x86_tls_error_no_base_reg;
> > > + else if (i.base_reg->reg_type.bitfield.instance != Accum)
> > > + return x86_tls_error_RegA;
> > > + break;
> > > +
> > > + case BFD_RELOC_X86_64_TLSDESC_CALL:
> > > + /* Check transition from GDesc access model:
> > > +
> > > + call *x@tlscall(%rax) <--- LP64 mode.
> > > + call *x@tlscall(%eax) <--- X32 mode.
> > > +
> > > + Only these fixed formats are supported.
> > > + */
> > > + if (i.tm.mnem_off != MN_call)
> > > + return x86_tls_error_insn;
> > > + else if (i.index_reg)
> > > + return x86_tls_error_sib;
> > > + else if (!i.base_reg)
> > > + return x86_tls_error_no_base_reg;
> > > + else if (i.base_reg->reg_type.bitfield.instance != Accum)
> > > + return x86_tls_error_RegA;
> > > + break;
> > > +
case BFD_RELOC_NONE:
return x86_tls_error_continue;
> > > + default:
> > > + return x86_tls_error_none;
break;
> > > + }
> > > +
> > > + return x86_tls_error_none;
> > > +}
> > > +
> > > +static void
> > > +x86_report_tls_error (enum x86_tls_error_type tls_error, unsigned int r_type)
Use 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;
> > > + }
Drop {}.
> > > +
> > > + 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_sib:
> > > + as_bad (_("@%s operator do not support SIB"), gotrel[k].str);
> > > + return;
> > > +
> > > + case x86_tls_error_no_base_reg:
> > > + as_bad (_("@%s operator must have base regster"), gotrel[k].str);
> > > + return;
> > > +
> > > + case x86_tls_error_require_no_base_index_reg:
> > > + as_bad (_("@%s operator should not have base/index register"),
> > > + gotrel[k].str);
> > > + return;
> > > +
> > > + case x86_tls_error_base_reg_name:
> > > + as_bad (_("@%s operator should not have base register"), gotrel[k].str);
> > > + return;
> > > +
> > > + case x86_tls_error_index_RegB:
> > > + as_bad (_("@%s operator only supports ebx/rbx as index register"),
> > > + gotrel[k].str);
> > > + return;
> > > +
> > > + case x86_tls_error_RegA:
> > > + as_bad (_("@%s operator only supports eax/rax as base register"),
> > > + gotrel[k].str);
> > > + return;
> > > +
> > > + case x86_tls_error_RegB:
> > > + as_bad (_("@%s operator only supports ebx/rbx as base register"),
> > > + gotrel[k].str);
> > > + return;
> > > +
> > > + case x86_tls_error_RegIP:
> > > + as_bad (_("@%s operator only supports rip as base register"),
> > > + gotrel[k].str);
> > > + return;
> > > +
> > > + case x86_tls_error_dest_RegA:
> > > + as_bad (_("@%s operator only supports eax/rax as dest register"),
> > > + gotrel[k].str);
> > > + return;
> > > +
> > > + case x86_tls_error_dest_RegDI:
> > > + as_bad (_("@%s operator only supports eax/rax as dest register"),
> > > + gotrel[k].str);
> > > + return;
> > > +
> > > + case x86_tls_error_scale_factor:
> > > + as_bad (_("@%s operator only supports scale factor of 00"),
> > > + 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. */
> > > @@ -6656,6 +6954,14 @@ i386_assemble (char *line)
> > > i.prefix[LOCK_PREFIX] = 0;
> > > }
> > >
> > > + if (tls_check)
if (i.has_gotrel && tls_check)
> > > + {
> > > + enum x86_tls_error_type tls_error;
> > > + for (j = 0; j < i.operands; ++j)
> > > + if ((tls_error = x86_check_tls_relocation (i.reloc[j])) != x86_tls_error_none)
> > > + x86_report_tls_error (tls_error, i.reloc[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)
> > > @@ -6666,28 +6972,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. */
> > > @@ -16184,6 +16468,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[] =
> > > {
> > > @@ -16230,6 +16515,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);
> > > @@ -16786,6 +17072,14 @@ md_parse_option (int c, const char *arg)
> > > optimize_for_space = 0;
> > > }
> > > break;
> > > + case OPTION_MTLS_CHECK:
> > > + if (strcasecmp (arg, "yes") == 0)
> > > + tls_check = 1;
> > > + else if (strcasecmp (arg, "no") == 0)
> > > + tls_check = 0;
> > > + else
> > > + as_fatal (_("invalid -mtls-check= option: `%s'"), arg);
> > > + break;
> > >
> > > default:
> > > return 0;
> > > @@ -17028,6 +17322,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..a4cdeb80900 100755
> > > --- a/gas/configure
> > > +++ b/gas/configure
> > > @@ -818,6 +818,7 @@ enable_checking
> > > enable_compressed_debug_sections
> > > enable_default_compressed_debug_sections_algorithm
> > > enable_x86_relax_relocations
> > > +enable_tls_check
> > > enable_elf_stt_common
> > > enable_generate_build_notes
> > > enable_mips_fix_loongson3_llsc
> > > @@ -1493,6 +1494,7 @@ Optional Features:
> > > --enable-compressed-debug-sections.
> > > --enable-x86-relax-relocations
> > > generate x86 relax relocations by default
> > > + --enable-tls-check check tls relocation by default
> > > --enable-elf-stt-common generate ELF common symbols with STT_COMMON type by
> > > default
> > > --enable-generate-build-notes
> > > @@ -10775,7 +10777,7 @@ else
> > > lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
> > > lt_status=$lt_dlunknown
> > > cat > conftest.$ac_ext <<_LT_EOF
> > > -#line 10778 "configure"
> > > +#line 10780 "configure"
> > > #include "confdefs.h"
> > >
> > > #if HAVE_DLFCN_H
> > > @@ -10881,7 +10883,7 @@ else
> > > lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
> > > lt_status=$lt_dlunknown
> > > cat > conftest.$ac_ext <<_LT_EOF
> > > -#line 10884 "configure"
> > > +#line 10886 "configure"
> > > #include "confdefs.h"
> > >
> > > #if HAVE_DLFCN_H
> > > @@ -11575,6 +11577,17 @@ if test "${enable_x86_relax_relocations+set}" = set; then :
> > > esac
> > > fi
> > >
> > > +# PR gas/32022
> > > +# Decide if check tls relocation.
> > > +ac_default_x86_tls_check=unset
> > > +# Provide a configure time option to override our default.
> > > +# Check whether --enable-tls_check was given.
> > > +if test "${enable_tls_check+set}" = set; then :
> > > + enableval=$enable_tls_check; case "${enableval}" in
> > > + no) ac_default_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..5fe57e52746 100644
> > > --- a/gas/configure.ac
> > > +++ b/gas/configure.ac
> > > @@ -95,6 +95,17 @@ AC_ARG_ENABLE(x86_relax_relocations,
> > > no) ac_default_x86_relax_relocations=0 ;;
> > > esac])dnl
> > >
> > > +# PR gas/32022
> > > +# Decide if check tls relocation.
> > > +ac_default_x86_tls_check=unset
> > > +# Provide a configure time option to override our default.
> > > +AC_ARG_ENABLE(tls_check,
> > > + AS_HELP_STRING([--enable-tls-check],
> > > + [check tls relocation by default]),
> > > +[case "${enableval}" in
> > > + no) ac_default_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 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..5da673a0287 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-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..b32da8725b5 100644
> > > --- a/gas/testsuite/gas/i386/ilp32/ilp32.exp
> > > +++ b/gas/testsuite/gas/i386/ilp32/ilp32.exp
> > > @@ -37,7 +37,7 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_x32_check] &
> > > }
> > > }
> > >
> > > - run_list_test "reloc64" "--defsym _bad_=1"
> > > + run_list_test "reloc64" "--defsym _bad_=1 -mtls-check=no"
> > > run_list_test "reloc-2"
> > >
> > > set ASFLAGS "$old_ASFLAGS"
> > > diff --git a/gas/testsuite/gas/i386/ilp32/reloc64.d b/gas/testsuite/gas/i386/ilp32/reloc64.d
> > > index e2c461f24e8..84b6aaccc01 100644
> > > --- a/gas/testsuite/gas/i386/ilp32/reloc64.d
> > > +++ b/gas/testsuite/gas/i386/ilp32/reloc64.d
> > > @@ -1,4 +1,4 @@
> > > -#as: -mx86-used-note=no --generate-missing-build-notes=no
> > > +#as: -mx86-used-note=no --generate-missing-build-notes=no -mtls-check=no
> > > #objdump: -Drw
> > > #name: x86-64 (ILP32) relocs
> > >
> > > diff --git a/gas/testsuite/gas/i386/inval-tls.l b/gas/testsuite/gas/i386/inval-tls.l
> > > index 98f7a29f1ab..40443bf68a2 100644
> > > --- a/gas/testsuite/gas/i386/inval-tls.l
> > > +++ b/gas/testsuite/gas/i386/inval-tls.l
> > > @@ -1,2 +1,30 @@
> > > .*: Assembler messages:
> > > .*:3: Error: @GOTNTPOFF operator cannot be used with `kmovd'
> > > +.*:6: Error: @TLSGD operator cannot be used with `add'
> > > +.*:7: Error: @TLSGD operator only supports ebx/rbx as index register
> > > +.*:8: Error: @TLSGD operator only supports scale factor of 00
> > > +.*:9: Error: @TLSGD operator should not have base register
> > > +.*:10: Error: @TLSGD operator only supports eax/rax as dest register
> > > +.*:11: Error: @TLSGD operator only supports eax/rax as dest register
> > > +.*:12: Error: @TLSGD operator only supports eax/rax as base register
> > > +.*:13: Error: 4-byte relocation cannot be applied to 2-byte field
> > > +.*:16: Error: @TLSLDM operator cannot be used with `add'
> > > +.*:17: Error: @TLSLDM operator only supports eax/rax as dest register
> > > +.*:18: Error: @TLSLDM operator only supports eax/rax as base register
> > > +.*:19: Error: @TLSLDM operator do not support SIB
> > > +.*:20: Error: 4-byte relocation cannot be applied to 2-byte field
> > > +.*:23: Error: @TLSDESC operator cannot be used with `add'
> > > +.*:24: Error: @TLSDESC operator only supports ebx/rbx as base register
> > > +.*:25: Error: @TLSDESC operator do not support SIB
> > > +.*:28: Error: @INDNTPOFF operator cannot be used with `sub'
> > > +.*:29: Error: @INDNTPOFF operator should not have base/index register
> > > +.*:30: Error: @INDNTPOFF operator should not have base/index register
> > > +.*:34: Error: @GOTNTPOFF operator cannot be used with `lea'
> > > +.*:35: Error: @GOTNTPOFF operator must have base regster
> > > +.*:38: Error: @GOTTPOFF operator cannot be used with `lea'
> > > +.*:39: Error: @GOTTPOFF operator must have base regster
> > > +.*:40: Error: 4-byte relocation cannot be applied to 2-byte field
> > > +.*:43: Error: @TLSCALL operator cannot be used with `lea'
> > > +.*:44: Error: @TLSCALL operator only supports eax/rax as base register
> > > +.*:45: Error: @TLSCALL operator do not support SIB
> > > +.*:45: Error: 0-byte relocation cannot be applied to 4-byte field
> > > diff --git a/gas/testsuite/gas/i386/inval-tls.s b/gas/testsuite/gas/i386/inval-tls.s
> > > index ba0e1b81dc9..d00dbfa3008 100644
> > > --- a/gas/testsuite/gas/i386/inval-tls.s
> > > +++ b/gas/testsuite/gas/i386/inval-tls.s
> > > @@ -1,3 +1,45 @@
> > > .text
> > > # All the following should be illegal
> > > kmovd foo@gotntpoff(%eax), %k0
> > > +
> > > + /* Invalid testcase for BFD_RELOC_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(%bx), %ax
> > > +
> > > + /* Invalid testcase for BFD_RELOC_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(%bx), %ax
> > > +
> > > + /* Invalid testcase for BFD_RELOC_386_TLS_GOTDESC. */
> > > + addl x@tlsdesc(%ebx), %eax
> > > + leal x@tlsdesc(%ecx), %eax
> > > + leal x@tlsdesc(,%ecx,1), %eax
> > > +
> > > + /* Invalid testcase for BFD_RELOC_386_TLS_IE. */
> > > + subl foo@indntpoff, %ecx
> > > + addl foo@indntpoff(%ebx), %ecx
> > > + movl foo@indntpoff(%ebx), %ecx
> > > + add foo@indntpoff, %cx
> > > +
> > > + /* Invalid testcase for BFD_RELOC_386_TLS_GOTIE. */
> > > + leal foo@gotntpoff(%ebx), %ecx
> > > + subl foo@gotntpoff(,%ebx,1), %ecx
> > > +
> > > + /* Invalid testcase for BFD_RELOC_386_TLS_IE_32. */
> > > + leal foo@gottpoff(%ebx), %ecx
> > > + subl foo@gottpoff(,%ebx,1), %ecx
> > > + add foo@gottpoff(%bx), %cx
> > > +
> > > + /* Invalid testcase for BFD_RELOC_386_TLS_DESC_CALL. */
> > > + leal foo@tlscall(%eax), %ebx
> > > + call *x@tlscall(%ebx)
> > > + call *x@tlscall(,%eax,1)
> > > 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..7a0a83147e4
> > > --- /dev/null
> > > +++ b/gas/testsuite/gas/i386/tls.s
> > > @@ -0,0 +1,31 @@
> > > +# Check tls relocation 32-bit mode
> > > +
> > > + .text
> > > +_start:
> > > + /* BFD_RELOC_386_TLS_GD. */
> > > + leal foo@tlsgd(,%ebx,1), %eax
> > > + leal foo@tlsgd(%ecx), %eax
> > > +
> > > + /* BFD_RELOC_386_TLS_LDM. */
> > > + leal foo@tlsldm(%ebx), %eax
> > > +
> > > + /* BFD_RELOC_386_TLS_GOTDESC. */
> > > + leal x@tlsdesc(%ebx), %eax
> > > +
> > > + /* BFD_RELOC_386_TLS_IE. */
> > > + movl foo@indntpoff, %eax
> > > + movl foo@indntpoff, %ebx
> > > + addl foo@indntpoff, %edx
> > > +
> > > + /* BFD_RELOC_386_TLS_GOTIE. */
> > > + subl foo@gotntpoff(%ebx), %ecx
> > > + movl foo@gotntpoff(%ebx), %ecx
> > > + addl foo@gotntpoff(%ebx), %ecx
> > > +
> > > + /* BFD_RELOC_386_TLS_IE_32. */
> > > + subl foo@gottpoff(%ebx), %ecx
> > > + movl foo@gottpoff(%ebx), %ecx
> > > + addl foo@gottpoff(%ebx), %ecx
> > > +
> > > + /* BFD_RELOC_386_TLS_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..b9a53693c4f 100644
> > > --- a/gas/testsuite/gas/i386/x86-64-inval-tls.l
> > > +++ b/gas/testsuite/gas/i386/x86-64-inval-tls.l
> > > @@ -1,3 +1,20 @@
> > > .*: 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 only supports eax/rax as dest register
> > > +.*:9: Error: @TLSGD operator only supports rip as base register
> > > +.*:10: Error: @TLSGD operator must have base regster
> > > +.*:13: Error: @TLSLD operator cannot be used with `add'
> > > +.*:14: Error: @TLSLD operator only supports eax/rax as dest register
> > > +.*:15: Error: @TLSLD operator only supports rip as base register
> > > +.*:16: Error: @TLSLD operator must have base regster
> > > +.*:19: Error: @TLSDESC operator cannot be used with `add'
> > > +.*:20: Error: @TLSDESC operator only supports rip as base register
> > > +.*:23: Error: @GOTTPOFF operator cannot be used with `sub'
> > > +.*:24: Error: @GOTTPOFF operator cannot be used with `xor'
> > > +.*:25: Error: @GOTTPOFF operator only supports rip as base register
> > > +.*:26: Error: @GOTTPOFF operator only supports rip as base register
> > > +.*:29: Error: @TLSCALL operator cannot be used with `lea'
> > > +.*:30: Error: @TLSCALL operator only supports eax/rax as base register
> > > +.*:30: Error: 0-byte relocation cannot be applied to 4-byte field
> > > diff --git a/gas/testsuite/gas/i386/x86-64-inval-tls.s b/gas/testsuite/gas/i386/x86-64-inval-tls.s
> > > index 71e19272ba9..ccefeb780b6 100644
> > > --- a/gas/testsuite/gas/i386/x86-64-inval-tls.s
> > > +++ b/gas/testsuite/gas/i386/x86-64-inval-tls.s
> > > @@ -2,3 +2,29 @@
> > > # All the following should be illegal
> > > kmovq foo@gottpoff(%rip), %k0
> > > kmovq foo@tlsld(%rip), %k0
> > > +
> > > + /* Invalid testcase for BFD_RELOC_X86_64_TLSGD. */
> > > + addq foo@tlsgd(%rip), %rdi
> > > + leaq foo@tlsgd(%rip), %rax
> > > + leaq foo@tlsgd(%rax), %rdi
> > > + leaq foo@tlsgd(,%rax,1), %rdi
> > > +
> > > + /* Invalid testcase for BFD_RELOC_X86_64_TLSLD. */
> > > + addq foo@tlsld(%rip), %rdi
> > > + leaq foo@tlsld(%rip), %rax
> > > + leaq foo@tlsld(%rax), %rdi
> > > + leaq foo@tlsld(,%rax,1), %rdi
> > > +
> > > + /* Invalid testcase for BFD_RELOC_X86_64_GOTPC32_TLSDESC. */
> > > + addq x@tlsdesc(%rip), %rax
> > > + leaq x@tlsdesc(%rbx), %rax
> > > +
> > > + /* Invalid testcase for BFD_RELOC_X86_64_GOTTPOFF. */
> > > + subq foo@gottpoff(%rip), %r12
> > > + xorq foo@gottpoff(%rip), %rax
> > > + movq foo@gottpoff(%rbx), %rax
> > > + addq foo@gottpoff(%rbx), %rax
> > > +
> > > + /* Invalid testcase for BFD_RELOC_X86_64_TLSDESC_CALL. */
> > > + leaq foo@tlscall(%rax), %rbx
> > > + call *foo@tlscall(%rip)
> > > 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..c4e5a8a4b29
> > > --- /dev/null
> > > +++ b/gas/testsuite/gas/i386/x86-64-tls.d
> > > @@ -0,0 +1,29 @@
> > > +#as:
> > > +#objdump: -drw
> > > +#name: Check tls relocation x86-64
> > > +
> > > +.*: +file format .*
> > > +
> > > +
> > > +Disassembly of section .text:
> > > +
> > > +0000000000000000 <_start>:
> > > +\s*[a-f0-9]+:\s*48 8d 3d 00 00 00 00 lea 0x0\(%rip\),%rdi # 7 <_start\+0x7> 3: R_X86_64_TLSGD foo-0x4
> > > +\s*[a-f0-9]+:\s*48 8d 3d 00 00 00 00 lea 0x0\(%rip\),%rdi # e <_start\+0xe> a: R_X86_64_TLSLD foo-0x4
> > > +\s*[a-f0-9]+:\s*48 8d 05 00 00 00 00 lea 0x0\(%rip\),%rax # 15 <_start\+0x15> 11: R_X86_64_GOTPC32_TLSDESC x-0x4
> > > +\s*[a-f0-9]+:\s*40 8d 05 00 00 00 00 rex lea 0x0\(%rip\),%eax # 1c <_start\+0x1c> 18: R_X86_64_GOTPC32_TLSDESC x-0x4
> > > +\s*[a-f0-9]+:\s*d5 40 8d 05 00 00 00 00 lea 0x0\(%rip\),%r16d # 24 <_start\+0x24> 20: R_X86_64_CODE_4_GOTPC32_TLSDESC x-0x4
> > > +\s*[a-f0-9]+:\s*4c 03 25 00 00 00 00 add 0x0\(%rip\),%r12 # 2b <_start\+0x2b> 27: R_X86_64_GOTTPOFF foo-0x4
> > > +\s*[a-f0-9]+:\s*48 8b 05 00 00 00 00 mov 0x0\(%rip\),%rax # 32 <_start\+0x32> 2e: R_X86_64_GOTTPOFF foo-0x4
> > > +\s*[a-f0-9]+:\s*44 03 25 00 00 00 00 add 0x0\(%rip\),%r12d # 39 <_start\+0x39> 35: R_X86_64_GOTTPOFF foo-0x4
> > > +\s*[a-f0-9]+:\s*8b 05 00 00 00 00 mov 0x0\(%rip\),%eax # 3f <_start\+0x3f> 3b: R_X86_64_GOTTPOFF foo-0x4
> > > +\s*[a-f0-9]+:\s*d5 48 03 05 00 00 00 00 add 0x0\(%rip\),%r16 # 47 <_start\+0x47> 43: R_X86_64_CODE_4_GOTTPOFF foo-0x4
> > > +\s*[a-f0-9]+:\s*d5 48 8b 25 00 00 00 00 mov 0x0\(%rip\),%r20 # 4f <_start\+0x4f> 4b: R_X86_64_CODE_4_GOTTPOFF foo-0x4
> > > +\s*[a-f0-9]+:\s*62 64 bc 18 01 35 00 00 00 00 add %r30,0x0\(%rip\),%r8 # 59 <_start\+0x59> 55: R_X86_64_CODE_6_GOTTPOFF foo-0x4
> > > +\s*[a-f0-9]+:\s*62 f4 dc 10 03 05 00 00 00 00 add 0x0\(%rip\),%rax,%r20 # 63 <_start\+0x63> 5f: R_X86_64_CODE_6_GOTTPOFF foo-0x4
> > > +\s*[a-f0-9]+:\s*62 e4 fc 0c 03 05 00 00 00 00 {nf} add 0x0\(%rip\),%r16 # 6d <_start\+0x6d> 69: R_X86_64_CODE_6_GOTTPOFF foo-0x4
> > > +\s*[a-f0-9]+:\s*62 64 bc 1c 01 35 00 00 00 00 {nf} add %r30,0x0\(%rip\),%r8 # 77 <_start\+0x77> 73: R_X86_64_CODE_6_GOTTPOFF foo-0x4
> > > +\s*[a-f0-9]+:\s*62 f4 dc 14 03 05 00 00 00 00 {nf} add 0x0\(%rip\),%rax,%r20 # 81 <_start\+0x81> 7d: R_X86_64_CODE_6_GOTTPOFF foo-0x4
> > > +\s*[a-f0-9]+:\s*ff 10 call \*\(%rax\) 81: R_X86_64_TLSDESC_CALL x
> > > +\s*[a-f0-9]+:\s*67 ff 10 call \*\(%eax\) 83: 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..4c573922773
> > > --- /dev/null
> > > +++ b/gas/testsuite/gas/i386/x86-64-tls.s
> > > @@ -0,0 +1,31 @@
> > > +# Check tls relocation 64-bit mode
> > > +
> > > + .text
> > > +_start:
> > > + /* BFD_RELOC_X86_64_TLSGD. */
> > > + leaq foo@tlsgd(%rip), %rdi
> > > +
> > > + /* BFD_RELOC_X86_64_TLSLD. */
> > > + leaq foo@tlsld(%rip), %rdi
> > > +
> > > + /* BFD_RELOC_X86_64_GOTPC32_TLSDESC. */
> > > + leaq x@tlsdesc(%rip), %rax
> > > + rex leal x@tlsdesc(%rip), %eax
> > > + leal x@tlsdesc(%rip), %r16d
> > > +
> > > + /* BFD_RELOC_X86_64_GOTTPOFF. */
> > > + addq foo@gottpoff(%rip), %r12
> > > + movq foo@gottpoff(%rip), %rax
> > > + addl foo@gottpoff(%rip), %r12d
> > > + movl foo@gottpoff(%rip), %eax
> > > + addq foo@gottpoff(%rip), %r16
> > > + movq foo@gottpoff(%rip), %r20
> > > + addq %r30, foo@gottpoff(%rip), %r8
> > > + addq foo@gottpoff(%rip), %rax, %r20
> > > + {nf} addq foo@gottpoff(%rip), %r16
> > > + {nf} addq %r30, foo@gottpoff(%rip), %r8
> > > + {nf} addq foo@gottpoff(%rip), %rax, %r20
> > > +
> > > + /* BFD_RELOC_X86_64_TLSDESC_CALL. */
> > > + call *x@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
> > > diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c
> > > index 565aae722f8..dd5e8744efe 100644
> > > --- a/opcodes/i386-gen.c
> > > +++ b/opcodes/i386-gen.c
> > > @@ -526,6 +526,7 @@ static const struct {
> > > INSTANCE (RegC),
> > > INSTANCE (RegD),
> > > INSTANCE (RegB),
> > > + INSTANCE (RegDI),
> > > };
> > >
> > > #undef INSTANCE
> > > diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h
> > > index c0d5e44d461..608e238fa18 100644
> > > --- a/opcodes/i386-opc.h
> > > +++ b/opcodes/i386-opc.h
> > > @@ -843,6 +843,7 @@ enum operand_instance
> > > RegC, /* %cl / %cx / %ecx / %rcx, e.g. register to hold shift count */
> > > RegD, /* %dl / %dx / %edx / %rdx, e.g. register to hold I/O port addr */
> > > RegB, /* %bl / %bx / %ebx / %rbx */
> > > + RegDI, /* %rdx */
> > > };
> > >
> > > /* Position of operand_type bits. */
> > > diff --git a/opcodes/i386-reg.tbl b/opcodes/i386-reg.tbl
> > > index e3146456133..028f9523b52 100644
> > > --- a/opcodes/i386-reg.tbl
> > > +++ b/opcodes/i386-reg.tbl
> > > @@ -135,7 +135,7 @@ rbx, Class=Reg|Instance=RegB|Qword|BaseIndex, 0, 3, Dw2Inval, 3
> > > rsp, Class=Reg|Qword, 0, 4, Dw2Inval, 7
> > > rbp, Class=Reg|Qword|BaseIndex, 0, 5, Dw2Inval, 6
> > > rsi, Class=Reg|Qword|BaseIndex, 0, 6, Dw2Inval, 4
> > > -rdi, Class=Reg|Qword|BaseIndex, 0, 7, Dw2Inval, 5
> > > +rdi, Class=Reg|Instance=RegDI|Qword|BaseIndex, 0, 7, Dw2Inval, 5
>
> Remove it. Unused and not needed.
>
> > > r8, Class=Reg|Qword|BaseIndex, RegRex, 0, Dw2Inval, 8
> > > r9, Class=Reg|Qword|BaseIndex, RegRex, 1, Dw2Inval, 9
> > > r10, Class=Reg|Qword|BaseIndex, RegRex, 2, Dw2Inval, 10
> > > --
> > > 2.34.1
> > >
> >
> > This failed with GCC 14:
> >
> > FAIL: Check tls relocation x86-64
> > FAIL: Build size-8
> >
> > gcc -B/export/build/gnu/tools-build/binutils-gitlab/build-x86_64-linux/ld/tmpdir/ld/
> > -I/export/gnu/import/git/gitlab/x86-binutils/ld/testsuite/ld-size -g
> > -O2 -fno-sanitize=all -c -fno-lto -fPIC -c
> > /export/gnu/import/git/gitlab/x86-binutils/ld/testsuite/ld-size/size-8b.c
> > -o tmpdir/size-8b.o
> > Executing on host: sh -c {gcc
> > -B/export/build/gnu/tools-build/binutils-gitlab/build-x86_64-linux/ld/tmpdir/ld/
> > -I/export/gnu/import/git/gitlab/x86-binutils/ld/testsuite/ld-size -g
> > -O2 -fno-sanitize=all -c -fno-lto -fPIC -c
> > /export/gnu/import/git/gitlab/x86-binutils/ld/testsuite/ld-size/size-8b.c
> > -o tmpdir/size-8b.o 2>&1} /dev/null ld.tmp (timeout = 300)
> > spawn [open ...]^M
> > /tmp/cc6aqbbv.s: Assembler messages:
> > /tmp/cc6aqbbv.s:27: Error: @TLSGD operator only supports eax/rax as
> > dest register
> > /tmp/cc6aqbbv.s:27: Error: @TLSGD operator only supports eax/rax as
> > dest register
> >
> > UNSUPPORTED: Build libsize-8.so
> >
> > FAIL: Run size-2
> > FAIL: Run size-8
> > FAIL: Run size-10
> > FAIL: Build libtls-1b.so
> > FAIL: Build libtls-1bn.so
> > FAIL: TLS GD/LD -> LE transition without PLT (dynamic)
> > FAIL: TLS GD/LD -> LE transition without PLT (dynamic, -z now)
> > FAIL: TLS GD/LD -> LE transition without PLT (PIE)
> > FAIL: TLS GD/LD -> LE transition without PLT (PIE, -z now)
> > FAIL: TLS GD/LD -> LE transition without PLT (static)
> > FAIL: TLS GD/LD -> IE transition without PLT
> > FAIL: TLS GD/LD -> IE transition without PLT (-z now)
> > FAIL: TLS without PLT (1)
> > FAIL: TLS without PLT (2)
> > FAIL: TLS without PLT (3)
> > FAIL: TLS without PLT (4)
> > FAIL: TLS -fpic and -fno-pic exec transitions
> > FAIL: TLS -fpic and -fno-pic exec transitions without PLT
> > FAIL: TLS with global dynamic and descriptors
> > FAIL: TLS GD->LE transition
> > FAIL: TLS LD->LE transition
> > FAIL: TLS X32 GD->LE transition
> > FAIL: TLS GD->IE transition
> > FAIL: TLS GD->IE transition without PLT
> > FAIL: TLS X32 GD->IE transition
> > FAIL: TLS X32 GD->IE transition without PLT
> > FAIL: TLS X32 LD->LE transition
> > FAIL: TLS -mcmodel=large GD->LE transition
> > FAIL: TLS -mcmodel=large LD->LE transition
> > FAIL: TLS -mcmodel=large LD->LE transition with r15 as GOT base
> > FAIL: TLS LD->LE transition without PLT
> > FAIL: TLS X32 LD->LE transition without PLT
> > FAIL: TLS -mcmodel=large GD->IE transition
> > FAIL: TLS -mcmodel=large GD->LE transition with r15 as GOT base
> > FAIL: TLS -mcmodel=large GD->IE transition with r15 as GOT base
> > FAIL: TLS GD->LE transition without PLT
> > FAIL: TLS X32 GD->LE transition without PLT
> > FAIL: TLS -fpic -shared transitions
> > FAIL: TLS -fpic -shared transitions with r15 as GOT base
> > FAIL: TLS GD->IE transition check
> > FAIL: TLS GD->LE transition check
> > FAIL: TLS GD->IE transition check without PLT
> > FAIL: TLS GD->LE transition check without PLT
> > FAIL: TLS with PIE (1 x86_64)
> > FAIL: ld-x86-64/tlspie2a
> > FAIL: ld-x86-64/tlspie2b
> > FAIL: ld-x86-64/tlspie2c
> > FAIL: ld-x86-64/align-branch-1
> >
> >
> > --
> > H.J.
>
>
>
> --
> H.J.
--
H.J.
More information about the Binutils
mailing list