From patchwork Wed Sep 11 06:08:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Cui, Lili" X-Patchwork-Id: 97414 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C178A3858435 for ; Wed, 11 Sep 2024 06:09:14 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) by sourceware.org (Postfix) with ESMTPS id DAC713858C98 for ; Wed, 11 Sep 2024 06:08:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DAC713858C98 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org DAC713858C98 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=192.198.163.12 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1726034924; cv=none; b=NjfDgPRbDnujHgxJo5rYuIbY5FB8MrVI9TOmZIIqDFtL8g7g84jAONKIMHYosco3yymuI7M6eZkbVACptvHJT0mjbHpQ4bvz2VMcX5Nv9CWvReHYRJLlpnai9Q3hQW4txFTwUNMi2MD40hgs1qJv5ilx+mgvLqgAlC0NyYbopAc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1726034924; c=relaxed/simple; bh=IP66pCN1cvsNkU8DMybStbEaw7HLL2ponvchWAwIL04=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=HvASalLafkGt8VUQxDzUa+MrzfNutGkrzharVlYviWUW5LpNqquLyYODTzsUJIOi0/RgePzfYslvWMIqlU5xCNqeywVI7Ga5T2t2/TjNpiT4p6WvHXa6vt1iPRXXSwHtpVAGHFfpTYQF6yUWQUobTqmN4twIGencYUh9wnaDQnE= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1726034918; x=1757570918; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=IP66pCN1cvsNkU8DMybStbEaw7HLL2ponvchWAwIL04=; b=TnrvdKbM8kAiCv6inp5rrD/FMECi0WVHcJbEb96ddHMRfKYN8U3MqNrg 7tp/CafflSnG89szCHCDqtQJcn7i2z0350AeBcg/MSRMF+TNgsDZIgmln 3kpAc7x/lBo8bSnKT0Tj/4cfFNfmCcm6xcBkYNLdVhNhnEfH4a7eCIy7H VP3YXX566wtKIh+IDkg2MemiKj9jko+pPgfs+BntItMBjTw3Fs3xDnzW8 IMcTcfKtimGhUtgIM0EIx/S1jJJ2hKCpFTh9eraJfo4kx9yrzY273d6V1 WNaABQI8Fndkxh7AbP+zxIeMNbm+p2N2xbD7QOcFfLkbfur0bEPgWUojO Q==; X-CSE-ConnectionGUID: 2wdrl1U9RLmItNEnC1rZPg== X-CSE-MsgGUID: LGwD/Lb5TK60zrLZ4WtBVw== X-IronPort-AV: E=McAfee;i="6700,10204,11191"; a="28703455" X-IronPort-AV: E=Sophos;i="6.10,219,1719903600"; d="scan'208";a="28703455" Received: from orviesa005.jf.intel.com ([10.64.159.145]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Sep 2024 23:08:36 -0700 X-CSE-ConnectionGUID: pZAo193/RbakdJ3m9Bsn6A== X-CSE-MsgGUID: s9ez7IstSvWjAPItmXPSxA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.10,219,1719903600"; d="scan'208";a="72063990" Received: from scymds04.sc.intel.com ([10.82.73.238]) by orviesa005.jf.intel.com with ESMTP; 10 Sep 2024 23:08:36 -0700 Received: from shgcc10.sh.intel.com (shgcc10.sh.intel.com [10.239.85.189]) by scymds04.sc.intel.com (Postfix) with ESMTP id 702192003B00; Tue, 10 Sep 2024 23:08:34 -0700 (PDT) From: "Cui, Lili" To: binutils@sourceware.org Cc: hjl.tools@gmail.com, jbeulich@suse.com Subject: [PATCH v3] x86: Add tls check in gas Date: Wed, 11 Sep 2024 14:08:33 +0800 Message-Id: <20240911060833.3669361-1-lili.cui@intel.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SCC_5_SHORT_WORD_LINES, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org 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 v3: 1. Added has_gotrel to indicate whether tls relocations need to be checked. 2. Removed RegDI, check register rdi with reg_num and reg_flags. 3. Added dest register size check in x86_check_tls_relocation, and reloc() will check memory registers. 4. Added rex/rex2 prefix check for X32 in BFD_RELOC_X86_64_GOTPC32_TLSDESC and add comments for it. 5. Refine tls error report. 6. Add more invalid test cases. ----------------------------- gas/ChangeLog: PR gas/32022 * config.in: Regenerate. * config/tc-i386.c *(enum x86_tls_error_type): New. *(struct _i386_insn): Added has_gotrel to indicate whether tls relocations need to be checked. (x86_check_tls_relocation): Added a new function to check tls relocation. (x86_report_tls_error): Created a new function to report tls error. (i386_assemble): Handle x86_check_tls_relocation. (lex_got): Set i.has_gotrel. (OPTION_MTLS_CHECK): Added a new option to contrl tls check. (struct option): Ditto. (md_parse_option): Ditto. (md_show_usage): Ditto. * configure: 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/tls.d: New test. * testsuite/gas/i386/tls.s: Ditto. * testsuite/gas/i386/x86-64-tls.d: Ditto. * testsuite/gas/i386/x86-64-tls.s: Ditto. ld/ChangeLog: PR gas/32022 * testsuite/ld-i386/tlsgdesc1.d: Disable tls check for it. * testsuite/ld-i386/tlsgdesc2.d: Ditto. * testsuite/ld-i386/tlsie2.d: Ditto. * testsuite/ld-i386/tlsie3.d: Ditto. * testsuite/ld-i386/tlsie4.d: Ditto. * testsuite/ld-i386/tlsie5.d: Ditto. * testsuite/ld-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 | 383 ++++++++++++++++++++-- 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/ilp32/x32-tls.d | 1 + gas/testsuite/gas/i386/inval-tls.l | 32 ++ gas/testsuite/gas/i386/inval-tls.s | 45 +++ 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 | 18 + gas/testsuite/gas/i386/x86-64-inval-tls.s | 27 ++ gas/testsuite/gas/i386/x86-64-tls.d | 31 ++ gas/testsuite/gas/i386/x86-64-tls.s | 33 ++ 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 +- 33 files changed, 680 insertions(+), 43 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 6cd57d9c12b..e0ece142ed2 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -274,6 +274,26 @@ 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_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_ebx, + 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_dest_reg_size, + x86_tls_error_REX_prefix +}; + struct _i386_insn { /* TM holds the template for the insn were currently assembling. */ @@ -365,6 +385,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 +740,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, @@ -6353,6 +6379,305 @@ 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), %reg --> 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_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(%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; + 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_reg_size; + 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_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_RegA; + } + break; + + case BFD_RELOC_386_TLS_LDM: + /* Check 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; + 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; + 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_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, when dest is Egpr, gas will automatically add rex2 to it. + When dest is Gpr, we need to check whether there is a rex/rex2 prefix. + */ + 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) + return x86_tls_error_rip; + if (i.op[1].regs->reg_type.bitfield.dword + && !(i.op[1].regs->reg_flags & RegRex2) + && (pp.rex2_encoding == false + && pp.rex_encoding == false + && i.prefix[REX_PREFIX] != REX_OPCODE)) + return x86_tls_error_REX_prefix; + 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) + 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.base_reg) + return x86_tls_error_no_base_reg; + if (i.index_reg) + return x86_tls_error_sib; + if (!i.op[1].regs->reg_type.bitfield.dword) + return x86_tls_error_dest_reg_size; + break; + + case BFD_RELOC_386_TLS_IE: + /* Check 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; + 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_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. + */ + if (i.tm.mnem_off != MN_add && i.tm.mnem_off != MN_mov) + return x86_tls_error_insn; + if (!i.base_reg) + return x86_tls_error_no_base_reg; + if (i.base_reg->reg_num != RegIP) + return x86_tls_error_rip; + 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_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_name: + 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_RegA: + as_bad (_("@%s operator requires `%seax/rax' as base register"), + gotrel[k].str, 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_dest_reg_size: + as_bad (_("@%s operator requires 32-bit dest register"), + gotrel[k].str); + return; + + case x86_tls_error_REX_prefix: + as_bad (_("@%s operator requires REX prefix in x32 mode"), + 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. */ @@ -6691,6 +7016,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) @@ -6701,28 +7041,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. */ @@ -12492,6 +12810,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) @@ -16225,6 +16544,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[] = { @@ -16271,6 +16591,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); @@ -16827,6 +17148,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; @@ -17069,6 +17398,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/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/inval-tls.l b/gas/testsuite/gas/i386/inval-tls.l index 98f7a29f1ab..20a7324c13e 100644 --- a/gas/testsuite/gas/i386/inval-tls.l +++ b/gas/testsuite/gas/i386/inval-tls.l @@ -1,2 +1,34 @@ .*: Assembler messages: .*:3: Error: @GOTNTPOFF operator cannot be used with `kmovd' +.*:6: Error: @TLSGD operator cannot be used with `add' +.*:7: Error: @TLSGD operator requires `%ebx' as index register +.*:8: Error: @TLSGD operator requires scale factor of 1 +.*:9: Error: @TLSGD operator requires no base register +.*:10: Error: @TLSGD operator requires `%eax' as dest register +.*:11: Error: @TLSGD operator requires `%eax' as dest register +.*:12: Error: @TLSGD operator requires `%eax/rax' as base register +.*:13: Error: @TLSGD operator requires 32-bit dest register +.*:16: Error: @TLSLDM operator cannot be used with `add' +.*:17: Error: @TLSLDM operator requires `%eax' as dest register +.*:18: Error: @TLSLDM operator requires `%eax/rax' as base register +.*:19: Error: @TLSLDM operator requires no SIB +.*:20: Error: @TLSLDM operator requires 32-bit dest register +.*:23: Error: @TLSDESC operator cannot be used with `add' +.*:24: Error: @TLSDESC operator requires `%ebx' as base register +.*:25: Error: @TLSDESC operator requires no SIB +.*:26: Error: @TLSDESC operator requires 32-bit dest register +.*:29: Error: @INDNTPOFF operator cannot be used with `sub' +.*:30: Error: @INDNTPOFF operator requires no base/index register +.*:31: Error: @INDNTPOFF operator requires no base/index register +.*:32: Error: @INDNTPOFF operator requires 32-bit dest register +.*:35: Error: @GOTNTPOFF operator cannot be used with `lea' +.*:36: Error: @GOTNTPOFF operator requires base register +.*:37: Error: @GOTNTPOFF operator cannot be used with `lea' +.*:40: Error: @GOTTPOFF operator cannot be used with `lea' +.*:41: Error: @GOTTPOFF operator requires base register +.*:42: Error: @GOTTPOFF operator requires 32-bit dest register +.*:45: Error: @TLSCALL operator cannot be used with `lea' +.*:46: Error: @TLSCALL operator requires `%eax/rax' as base register +.*:47: Error: @TLSCALL operator requires no SIB +.*:47: Error: 0-byte relocation cannot be applied to 4-byte field +.*:48: 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..9ea4a74e235 100644 --- a/gas/testsuite/gas/i386/inval-tls.s +++ b/gas/testsuite/gas/i386/inval-tls.s @@ -1,3 +1,48 @@ .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(%ebx), %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(%ebx), %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 + lea x@tlsdesc(%ebx), %ax + + /* 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 + lea foo@gotntpoff(%ebx), %cx + + /* Invalid testcase for BFD_RELOC_386_TLS_IE_32. */ + leal foo@gottpoff(%ebx), %ecx + subl foo@gottpoff(,%ebx,1), %ecx + add foo@gottpoff(%ebx), %cx + + /* Invalid testcase for BFD_RELOC_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..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..26bf69ef157 100644 --- a/gas/testsuite/gas/i386/x86-64-inval-tls.l +++ b/gas/testsuite/gas/i386/x86-64-inval-tls.l @@ -1,3 +1,21 @@ .*: 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 +.*:13: Error: @TLSLD operator cannot be used with `add' +.*:14: Error: @TLSLD operator requires `%rdi' as dest register +.*:15: Error: @TLSLD operator requires `%rip' as base register +.*:16: Error: @TLSLD operator requires base register +.*:19: Error: @TLSDESC operator cannot be used with `add' +.*:20: Error: @TLSDESC operator requires `%rip' as base register +.*:21: Error: @TLSDESC operator requires REX prefix in x32 mode +.*:24: Error: @GOTTPOFF operator cannot be used with `sub' +.*:25: Error: @GOTTPOFF operator cannot be used with `xor' +.*:26: Error: @GOTTPOFF operator requires `%rip' as base register +.*:27: Error: @GOTTPOFF operator requires `%rip' as base register +.*:30: Error: @TLSCALL operator cannot be used with `lea' +.*:31: Error: @TLSCALL operator requires `%eax/rax' as base register +.*:31: 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..66e3d9038af 100644 --- a/gas/testsuite/gas/i386/x86-64-inval-tls.s +++ b/gas/testsuite/gas/i386/x86-64-inval-tls.s @@ -2,3 +2,30 @@ # 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 + leal x@tlsdesc(%rip), %eax + + /* 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..0bceeb63d94 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-tls.d @@ -0,0 +1,31 @@ +#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*40 8d 05 00 00 00 00 rex lea 0x0\(%rip\),%eax # 23 <_start\+0x23> 1f: R_X86_64_GOTPC32_TLSDESC x-0x4 +\s*[a-f0-9]+:\s*d5 00 8d 05 00 00 00 00 \{rex2 0x0\} lea 0x0\(%rip\),%eax # 2b <_start\+0x2b> 27: R_X86_64_CODE_4_GOTPC32_TLSDESC x-0x4 +\s*[a-f0-9]+:\s*d5 40 8d 05 00 00 00 00 lea 0x0\(%rip\),%r16d # 33 <_start\+0x33> 2f: 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 # 3a <_start\+0x3a> 36: R_X86_64_GOTTPOFF foo-0x4 +\s*[a-f0-9]+:\s*48 8b 05 00 00 00 00 mov 0x0\(%rip\),%rax # 41 <_start\+0x41> 3d: R_X86_64_GOTTPOFF foo-0x4 +\s*[a-f0-9]+:\s*44 03 25 00 00 00 00 add 0x0\(%rip\),%r12d # 48 <_start\+0x48> 44: R_X86_64_GOTTPOFF foo-0x4 +\s*[a-f0-9]+:\s*8b 05 00 00 00 00 mov 0x0\(%rip\),%eax # 4e <_start\+0x4e> 4a: R_X86_64_GOTTPOFF foo-0x4 +\s*[a-f0-9]+:\s*d5 48 03 05 00 00 00 00 add 0x0\(%rip\),%r16 # 56 <_start\+0x56> 52: 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 # 5e <_start\+0x5e> 5a: 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 # 68 <_start\+0x68> 64: 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 # 72 <_start\+0x72> 6e: 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 # 7c <_start\+0x7c> 78: 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 # 86 <_start\+0x86> 82: 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 # 90 <_start\+0x90> 8c: R_X86_64_CODE_6_GOTTPOFF foo-0x4 +\s*[a-f0-9]+:\s*ff 10 call \*\(%rax\) 90: R_X86_64_TLSDESC_CALL x +\s*[a-f0-9]+:\s*67 ff 10 call \*\(%eax\) 92: 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..94bcb0af4e7 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-tls.s @@ -0,0 +1,33 @@ +# 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 + {rex} leal x@tlsdesc(%rip), %eax + {rex2} 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