@@ -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
@@ -274,6 +274,23 @@ enum i386_error
internal_error,
};
+enum x86_tls_error_type
+{
+ x86_tls_error_none,
+ 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
{
/* 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)
+{
+ 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)
+ 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;
+
+ default:
+ return x86_tls_error_none;
+ }
+
+ return x86_tls_error_none;
+}
+
+static void
+x86_report_tls_error (enum x86_tls_error_type tls_error, unsigned int 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_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)
+ {
+ 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]);
+ }
+
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"));
@@ -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
@@ -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
@@ -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}
@@ -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"
@@ -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"
@@ -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
@@ -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
@@ -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)
@@ -1,4 +1,4 @@
-#as: -mrelax-relocations=yes
+#as: -mrelax-relocations=yes -mtls-check=no
#objdump: -Drw
#name: i386 relocs
@@ -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*
new file mode 100644
@@ -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
new file mode 100644
@@ -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)
@@ -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
@@ -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)
new file mode 100644
@@ -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
new file mode 100644
@@ -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)
@@ -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"
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -526,6 +526,7 @@ static const struct {
INSTANCE (RegC),
INSTANCE (RegD),
INSTANCE (RegB),
+ INSTANCE (RegDI),
};
#undef INSTANCE
@@ -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. */
@@ -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
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