From patchwork Thu Dec 28 14:58:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 82920 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 3064C3857B81 for ; Thu, 28 Dec 2023 15:00:32 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-pg1-x534.google.com (mail-pg1-x534.google.com [IPv6:2607:f8b0:4864:20::534]) by sourceware.org (Postfix) with ESMTPS id E79963858412 for ; Thu, 28 Dec 2023 14:58:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E79963858412 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E79963858412 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::534 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1703775493; cv=none; b=ms+dL2l5QQ5I/jzEtq4O6N85uSefWg+qRv/ypFubzG8wXTpOvNJjXi0Qo7dgUHfwfLizr5U33Ie1tZwSyZiIEqC3SOtbTC+PY6PmzT+Ysfi2qxhzjqrnE2v/kiIJjSgoWSow0WoYse/X4atxd9TLi/sdyoS6HR845zHsaBYPlT4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1703775493; c=relaxed/simple; bh=e3jiLn8vZvybYaZyrcVTOc6XjsQfmfehN/g7zqFlaXs=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=SuN57lqTKq8LMjK7KMgMc7d83ICyMI6/1A2+5VLGN8XCkb6D5zSOMOYF9sf3KaLSp3HXif1+82GXQmIueyj3kQUpzOJi+W8VUdSFQ8/gOVMDhTue5/XJcOqCKRWyjkZjU348/izrax1ppuFG6v1ByLZdvg3BmPSx4fPUs8UGHgQ= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pg1-x534.google.com with SMTP id 41be03b00d2f7-5c21e185df5so4617444a12.1 for ; Thu, 28 Dec 2023 06:58:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1703775487; x=1704380287; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=VZEHBeEsjYwvqwMb1v8I00fbnxZBkZK3nq10NfIXxiU=; b=RqQEbPvvmaYt6HaCp6mwiWQFiUonUCvz3TYmf/nqjHTJILZsiNy6/ENCYgBGQXFmpj B/haecb91GzTbOMM3sDYffZjEU9mAI9VD/JIYrG5r6faB1jMfxMD25ZEdFFDTpWgViG2 am5K3TIdVtW16MPzlXJyvakZhyFGP4F8kEzaQGCiqPh6z8Ubg9VCV0NBHNND8VWn3EZq Tdnu/t5kbHHXcl9PmOfCHKhh5EYduuS0k+ujDP6CQtVf8e3fpB+4nZ3TJvzqS9HCZsnq VInd+KEQYaJe6HFpqvfADbLkzgxG7at/c2R2yjqc+JEcbvVzyh03FlF3FPcYBP2dckT9 zBzw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703775487; x=1704380287; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VZEHBeEsjYwvqwMb1v8I00fbnxZBkZK3nq10NfIXxiU=; b=oruSdDuv27F4idpYLAb7MGYoeC9/mfDg0c05tvaFMrsErruqXYWI0d4lzVEvPcHp94 iOIpROpNlJ1LkjwQFfCpti4KnuDFo/uqPf01jR9WYO+WNkBWPLt7CHhsxJGI0xR4UZ9d h4tP4Rl4U0p6X9HvpAhvHhc5m6uBt5vf9tSC/FTAHPhRU5cf6Q2nPpd49KIAdqGgMLjI vTq2DGl0I+e1gzHnSXKDMpzAi4R+LIoDyXOmkg5AasWpO35r+X3EpIGqmuUxUePwFhx6 +o5mN4eKO42Hovk4zBpwfTfZiC+I1HLIxNI4U3CZzlqQhI8LL0B7VGWnIrAKpqhg40Z8 gEDw== X-Gm-Message-State: AOJu0YwKIwvcZMwSAfbGNTf4lSdI2XvxWmlcKaMF5j0c1ZrAZ9kq1fji WjsCK2eLcTzMfwSYyrsj+lLTDqv+8ZU= X-Google-Smtp-Source: AGHT+IHxfKxc/qS6EuX5EvdEEogWydiS5jzp4H7pSWyUadr+lXVbv/3e8lXSAWX/mWg2jFMwTDzOCw== X-Received: by 2002:a17:90a:6082:b0:28b:77c5:9017 with SMTP id z2-20020a17090a608200b0028b77c59017mr5594749pji.35.1703775487079; Thu, 28 Dec 2023 06:58:07 -0800 (PST) Received: from gnu-cfl-3.localdomain ([172.56.169.119]) by smtp.gmail.com with ESMTPSA id sc17-20020a17090b511100b0028ad273525dsm18188127pjb.25.2023.12.28.06.58.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Dec 2023 06:58:05 -0800 (PST) Received: from gnu-cfl-3.. (localhost [IPv6:::1]) by gnu-cfl-3.localdomain (Postfix) with ESMTP id BACC6740498 for ; Thu, 28 Dec 2023 06:58:04 -0800 (PST) From: "H.J. Lu" To: binutils@sourceware.org Subject: [PATCH 1/4] x86-64: Add R_X86_64_CODE_4_GOTPCRELX Date: Thu, 28 Dec 2023 06:58:01 -0800 Message-ID: <20231228145804.658337-2-hjl.tools@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231228145804.658337-1-hjl.tools@gmail.com> References: <20231228145804.658337-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3024.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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 For mov name@GOTPCREL(%rip), %reg test %reg, name@GOTPCREL(%rip) binop name@GOTPCREL(%rip), %reg where binop is one of adc, add, add, cmp, or, sbb, sub, xor instructions, add # define R_X86_64_CODE_4_GOTPCRELX 43 if the instruction starts at 4 bytes before the relocation offset. It similar to R_X86_64_GOTPCRELX. Linker can treat R_X86_64_CODE_4_GOTPCRELX as R_X86_64_GOTPCREL or convert the above instructions to lea name(%rip), %reg mov $name, %reg test $name, %reg binop $name, %reg if the instruction is encoded with the REX2 prefix when possible. bfd/ * elf64-x86-64.c (x86_64_elf_howto_table): Add R_X86_64_CODE_4_GOTPCRELX. (R_X86_64_standard): Updated. (x86_64_reloc_map): Add BFD_RELOC_X86_64_CODE_4_GOTPCRELX. (elf_x86_64_convert_load_reloc): Handle R_X86_64_CODE_4_GOTPCRELX. (elf_x86_64_scan_relocs): Likewise. (elf_x86_64_relocate_section): Likewise. * reloc.c (bfd_reloc_code_real): Add BFD_RELOC_X86_64_CODE_4_GOTPCRELX. * bfd-in2.h: Regenerated. * libbfd.h: Likewise. gas/ * write.h (fix): Add fx_tcbit3. Change fx_unused to 1 bit. * config/tc-i386.c (tc_i386_fix_adjustable): Handle BFD_RELOC_X86_64_CODE_4_GOTPCRELX. (tc_gen_reloc): Likewise. (output_disp): Set fixP->fx_tcbit3 for REX2 prefix. (i386_validate_fix): Generate BFD_RELOC_X86_64_CODE_4_GOTPCRELX if fixp->fx_tcbit3 is set. * config/tc-i386.h (TC_FORCE_RELOCATION_LOCAL): Add BFD_RELOC_X86_64_CODE_4_GOTPCRELX. (TC_FORCE_RELOCATION_ABS): Likewise. * testsuite/gas/i386/x86-64-gotpcrel.s: Add tests for R_X86_64_CODE_4_GOTPCRELX. * testsuite/gas/i386/x86-64-localpic.s: Likewise. * testsuite/gas/i386/x86-64-gotpcrel.d: Updated. * testsuite/gas/i386/x86-64-localpic.d: Likewise. * testsuite/gas/i386/ilp32/x86-64-localpic.d: Likewise. include/ * elf/x86-64.h (elf_x86_64_reloc_type): Add R_X86_64_CODE_4_GOTPCRELX. ld/ * testsuite/ld-x86-64/apx-load1.s: New file. * testsuite/ld-x86-64/apx-load1a.d: Likewise. * testsuite/ld-x86-64/apx-load1b.d: Likewise. * testsuite/ld-x86-64/apx-load1c.d: Likewise. * testsuite/ld-x86-64/apx-load1d.d: Likewise. * testsuite/ld-x86-64/x86-64.exp: Run apx-load1a, apx-load1b, apx-load1c and apx-load1d. --- bfd/bfd-in2.h | 1 + bfd/elf64-x86-64.c | 73 ++++++++++++++----- bfd/libbfd.h | 1 + bfd/reloc.c | 2 + gas/config/tc-i386.c | 18 ++++- gas/config/tc-i386.h | 6 +- .../gas/i386/ilp32/x86-64-localpic.d | 4 +- gas/testsuite/gas/i386/x86-64-gotpcrel.d | 12 +++ gas/testsuite/gas/i386/x86-64-gotpcrel.s | 19 +++++ gas/testsuite/gas/i386/x86-64-localpic.d | 4 +- gas/testsuite/gas/i386/x86-64-localpic.s | 2 + gas/write.h | 3 +- include/elf/x86-64.h | 6 +- ld/testsuite/ld-x86-64/apx-load1.s | 51 +++++++++++++ ld/testsuite/ld-x86-64/apx-load1a.d | 54 ++++++++++++++ ld/testsuite/ld-x86-64/apx-load1b.d | 55 ++++++++++++++ ld/testsuite/ld-x86-64/apx-load1c.d | 47 ++++++++++++ ld/testsuite/ld-x86-64/apx-load1d.d | 47 ++++++++++++ ld/testsuite/ld-x86-64/x86-64.exp | 4 + 19 files changed, 382 insertions(+), 27 deletions(-) create mode 100644 ld/testsuite/ld-x86-64/apx-load1.s create mode 100644 ld/testsuite/ld-x86-64/apx-load1a.d create mode 100644 ld/testsuite/ld-x86-64/apx-load1b.d create mode 100644 ld/testsuite/ld-x86-64/apx-load1c.d create mode 100644 ld/testsuite/ld-x86-64/apx-load1d.d diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 782845926ea..96709da9170 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -3891,6 +3891,7 @@ enum bfd_reloc_code_real BFD_RELOC_X86_64_PLT32_BND, BFD_RELOC_X86_64_GOTPCRELX, BFD_RELOC_X86_64_REX_GOTPCRELX, + BFD_RELOC_X86_64_CODE_4_GOTPCRELX, /* ns32k relocations. */ BFD_RELOC_NS32K_IMM_8, diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 3b7a8aeee11..a2d1b6f14b7 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -170,12 +170,15 @@ static reloc_howto_type x86_64_elf_howto_table[] = HOWTO(R_X86_64_REX_GOTPCRELX, 0, 4, 32, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_X86_64_REX_GOTPCRELX", false, 0, 0xffffffff, true), + HOWTO(R_X86_64_CODE_4_GOTPCRELX, 0, 4, 32, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_CODE_4_GOTPCRELX", false, 0, 0xffffffff, + true), /* We have a gap in the reloc numbers here. R_X86_64_standard counts the number up to this point, and R_X86_64_vt_offset is the value to subtract from a reloc type of R_X86_64_GNU_VT* to form an index into this table. */ -#define R_X86_64_standard (R_X86_64_REX_GOTPCRELX + 1) +#define R_X86_64_standard (R_X86_64_CODE_4_GOTPCRELX + 1) #define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard) /* GNU extension to record C++ vtable hierarchy. */ @@ -244,6 +247,7 @@ static const struct elf_reloc_map x86_64_reloc_map[] = { BFD_RELOC_X86_64_PLT32_BND, R_X86_64_PLT32_BND, }, { BFD_RELOC_X86_64_GOTPCRELX, R_X86_64_GOTPCRELX, }, { BFD_RELOC_X86_64_REX_GOTPCRELX, R_X86_64_REX_GOTPCRELX, }, + { BFD_RELOC_X86_64_CODE_4_GOTPCRELX, R_X86_64_CODE_4_GOTPCRELX, }, { BFD_RELOC_VTABLE_INHERIT, R_X86_64_GNU_VTINHERIT, }, { BFD_RELOC_VTABLE_ENTRY, R_X86_64_GNU_VTENTRY, }, }; @@ -1586,7 +1590,8 @@ elf_x86_64_convert_load_reloc (bfd *abfd, bfd_vma roff = irel->r_offset; bfd_vma abs_relocation; - if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2)) + if (roff < (r_type == R_X86_64_CODE_4_GOTPCRELX + ? 4 : (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2))) return true; raddend = irel->r_addend; @@ -1597,8 +1602,18 @@ elf_x86_64_convert_load_reloc (bfd *abfd, htab = elf_x86_hash_table (link_info, X86_64_ELF_DATA); is_pic = bfd_link_pic (link_info); - relocx = (r_type == R_X86_64_GOTPCRELX - || r_type == R_X86_64_REX_GOTPCRELX); + if (r_type == R_X86_64_CODE_4_GOTPCRELX) + { + /* Skip if this isn't a REX2 instruction. */ + opcode = bfd_get_8 (abfd, contents + roff - 4); + if (opcode != 0xd5) + return true; + + relocx = true; + } + else + relocx = (r_type == R_X86_64_GOTPCRELX + || r_type == R_X86_64_REX_GOTPCRELX); /* TRUE if --no-relax is used. */ no_overflow = link_info->disable_target_specific_optimizations > 1; @@ -1610,9 +1625,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd, /* Convert mov to lea since it has been done for a while. */ if (opcode != 0x8b) { - /* Only convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX - for call, jmp or one of adc, add, and, cmp, or, sbb, sub, - test, xor instructions. */ + /* Only convert R_X86_64_GOTPCRELX, R_X86_64_REX_GOTPCRELX + and R_X86_64_CODE_4_GOTPCRELX for call, jmp or one of adc, + add, and, cmp, or, sbb, sub, test, xor instructions. */ if (!relocx) return true; } @@ -1797,13 +1812,22 @@ elf_x86_64_convert_load_reloc (bfd *abfd, } else { - unsigned int rex; + unsigned int rex = 0; unsigned int rex_mask = REX_R; + unsigned int rex2 = 0; + unsigned int rex2_mask = REX_R | REX_R << 4; + bool rex_w = false; - if (r_type == R_X86_64_REX_GOTPCRELX) - rex = bfd_get_8 (abfd, contents + roff - 3); - else - rex = 0; + if (r_type == R_X86_64_CODE_4_GOTPCRELX) + { + rex2 = bfd_get_8 (abfd, contents + roff - 3); + rex_w = (rex2 & REX_W) != 0; + } + else if (r_type == R_X86_64_REX_GOTPCRELX) + { + rex = bfd_get_8 (abfd, contents + roff - 3); + rex_w = (rex & REX_W) != 0; + } if (opcode == 0x8b) { @@ -1824,8 +1848,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd, opcode = 0xc7; modrm = bfd_get_8 (abfd, contents + roff - 1); modrm = 0xc0 | (modrm & 0x38) >> 3; - if ((rex & REX_W) != 0 - && ABI_64_P (link_info->output_bfd)) + if (rex_w && ABI_64_P (link_info->output_bfd)) { /* Keep the REX_W bit in REX byte for LP64. */ r_type = R_X86_64_32S; @@ -1837,8 +1860,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd, use R_X86_64_32 and clear the W bit to avoid sign-extend imm32 to imm64. */ r_type = R_X86_64_32; - /* Clear the W bit in REX byte. */ + /* Clear the W bit in REX byte and REX2 payload. */ rex_mask |= REX_W; + rex2_mask |= REX_W; goto rewrite_modrm_rex; } } @@ -1867,7 +1891,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd, /* Use R_X86_64_32 with 32-bit operand to avoid relocation overflow when sign-extending imm32 to imm64. */ - r_type = (rex & REX_W) != 0 ? R_X86_64_32S : R_X86_64_32; + r_type = rex_w ? R_X86_64_32S : R_X86_64_32; rewrite_modrm_rex: if (abs_relocation) @@ -1893,6 +1917,13 @@ elf_x86_64_convert_load_reloc (bfd *abfd, rex = (rex & ~rex_mask) | (rex & REX_R) >> 2; bfd_put_8 (abfd, rex, contents + roff - 3); } + else if (rex2) + { + /* Move the R bits to the B bits in REX2 payload byte. */ + rex2 = ((rex2 & ~rex2_mask) + | (rex2 & (REX_R | REX_R << 4)) >> 2); + bfd_put_8 (abfd, rex2, contents + roff - 3); + } /* No addend for R_X86_64_32/R_X86_64_32S relocations. */ irel->r_addend = 0; @@ -2058,7 +2089,8 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, converted_reloc = false; if ((r_type == R_X86_64_GOTPCREL || r_type == R_X86_64_GOTPCRELX - || r_type == R_X86_64_REX_GOTPCRELX) + || r_type == R_X86_64_REX_GOTPCRELX + || r_type == R_X86_64_CODE_4_GOTPCRELX) && (h == NULL || h->type != STT_GNU_IFUNC)) { Elf_Internal_Rela *irel = (Elf_Internal_Rela *) rel; @@ -2108,6 +2140,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, case R_X86_64_GOTPCREL: case R_X86_64_GOTPCRELX: case R_X86_64_REX_GOTPCRELX: + case R_X86_64_CODE_4_GOTPCRELX: case R_X86_64_TLSGD: case R_X86_64_GOT64: case R_X86_64_GOTPCREL64: @@ -2710,6 +2743,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, case R_X86_64_GOTPCREL: case R_X86_64_GOTPCRELX: case R_X86_64_REX_GOTPCRELX: + case R_X86_64_CODE_4_GOTPCRELX: case R_X86_64_GOTPCREL64: base_got = htab->elf.sgot; off = h->got.offset; @@ -2935,6 +2969,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, case R_X86_64_GOTPCREL: case R_X86_64_GOTPCRELX: case R_X86_64_REX_GOTPCRELX: + case R_X86_64_CODE_4_GOTPCRELX: case R_X86_64_GOTPCREL64: /* Use global offset table entry as symbol value. */ case R_X86_64_GOTPLT64: @@ -3025,7 +3060,8 @@ elf_x86_64_relocate_section (bfd *output_bfd, && !(sym->st_shndx == SHN_ABS && (r_type == R_X86_64_GOTPCREL || r_type == R_X86_64_GOTPCRELX - || r_type == R_X86_64_REX_GOTPCRELX))) + || r_type == R_X86_64_REX_GOTPCRELX + || r_type == R_X86_64_CODE_4_GOTPCRELX))) relative_reloc = true; } } @@ -3063,6 +3099,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, if (r_type != R_X86_64_GOTPCREL && r_type != R_X86_64_GOTPCRELX && r_type != R_X86_64_REX_GOTPCRELX + && r_type != R_X86_64_CODE_4_GOTPCRELX && r_type != R_X86_64_GOTPCREL64) relocation -= htab->elf.sgotplt->output_section->vma - htab->elf.sgotplt->output_offset; diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 8dab44110a6..8873fafdde9 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1460,6 +1460,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_X86_64_PLT32_BND", "BFD_RELOC_X86_64_GOTPCRELX", "BFD_RELOC_X86_64_REX_GOTPCRELX", + "BFD_RELOC_X86_64_CODE_4_GOTPCRELX", "BFD_RELOC_NS32K_IMM_8", "BFD_RELOC_NS32K_IMM_16", "BFD_RELOC_NS32K_IMM_32", diff --git a/bfd/reloc.c b/bfd/reloc.c index 6fd0f1fb547..56d852d084f 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2475,6 +2475,8 @@ ENUMX BFD_RELOC_X86_64_GOTPCRELX ENUMX BFD_RELOC_X86_64_REX_GOTPCRELX +ENUMX + BFD_RELOC_X86_64_CODE_4_GOTPCRELX ENUMDOC x86-64/elf relocations. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index ee948a61b18..8d76446010b 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -3595,6 +3595,7 @@ tc_i386_fix_adjustable (fixS *fixP) || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX || fixP->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX + || fixP->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTPCRELX || fixP->fx_r_type == BFD_RELOC_X86_64_TLSGD || fixP->fx_r_type == BFD_RELOC_X86_64_TLSLD || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32 @@ -10856,6 +10857,10 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off) && !i.prefix[ADDR_PREFIX]) fixP->fx_signed = 1; + /* Set fx_tcbit3 for REX2 prefix. */ + if (is_apx_rex2_encoding ()) + fixP->fx_tcbit3 = 1; + /* Check for "call/jmp *mem", "mov mem, %reg", "test %reg, mem" and "binop mem, %reg" where binop is one of adc, add, and, cmp, or, sbb, sub, xor @@ -15936,9 +15941,14 @@ i386_validate_fix (fixS *fixp) abort (); #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) if (fixp->fx_tcbit2) - fixp->fx_r_type = (fixp->fx_tcbit - ? BFD_RELOC_X86_64_REX_GOTPCRELX - : BFD_RELOC_X86_64_GOTPCRELX); + { + if (fixp->fx_tcbit3) + fixp->fx_r_type = BFD_RELOC_X86_64_CODE_4_GOTPCRELX; + else + fixp->fx_r_type = (fixp->fx_tcbit + ? BFD_RELOC_X86_64_REX_GOTPCRELX + : BFD_RELOC_X86_64_GOTPCRELX); + } else #endif fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL; @@ -16042,6 +16052,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) case BFD_RELOC_X86_64_GOTPCREL: case BFD_RELOC_X86_64_GOTPCRELX: case BFD_RELOC_X86_64_REX_GOTPCRELX: + case BFD_RELOC_X86_64_CODE_4_GOTPCRELX: case BFD_RELOC_386_PLT32: case BFD_RELOC_386_GOT32: case BFD_RELOC_386_GOT32X: @@ -16200,6 +16211,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) case BFD_RELOC_X86_64_GOTPCREL: case BFD_RELOC_X86_64_GOTPCRELX: case BFD_RELOC_X86_64_REX_GOTPCRELX: + case BFD_RELOC_X86_64_CODE_4_GOTPCRELX: case BFD_RELOC_X86_64_TLSGD: case BFD_RELOC_X86_64_TLSLD: case BFD_RELOC_X86_64_GOTTPOFF: diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h index 3cb0c784819..44227a8376c 100644 --- a/gas/config/tc-i386.h +++ b/gas/config/tc-i386.h @@ -171,7 +171,8 @@ extern int tc_i386_fix_adjustable (struct fix *); || (FIX)->fx_r_type == BFD_RELOC_386_GOTPC \ || (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCREL \ || (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX \ - || (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX) + || (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX \ + || (FIX)->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTPCRELX) #define TC_FORCE_RELOCATION_ABS(FIX) \ (TC_FORCE_RELOCATION (FIX) \ @@ -179,7 +180,8 @@ extern int tc_i386_fix_adjustable (struct fix *); || (FIX)->fx_r_type == BFD_RELOC_386_GOT32X \ || (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCREL \ || (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX \ - || (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX) + || (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX \ + || (FIX)->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTPCRELX) extern int i386_parse_name (char *, expressionS *, char *); #define md_parse_name(s, e, m, c) i386_parse_name (s, e, c) diff --git a/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d b/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d index d0cc4e8efc9..57d4843a5b5 100644 --- a/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d +++ b/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d @@ -3,10 +3,12 @@ #readelf: -rsW #name: x86-64 (ILP32) local PIC -Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 2 entries: +Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 4 entries: +Offset +Info +Type +Sym. Value +Symbol's Name \+ Addend [0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +foo - 4 [0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +bar - 4 +[0-9a-f]+ +[0-9a-f]+ R_X86_64_CODE_4_GOTPCRELX +[0-9a-f]+ +foo - 4 +[0-9a-f]+ +[0-9a-f]+ R_X86_64_CODE_4_GOTPCRELX +[0-9a-f]+ +bar - 4 #... +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo +[0-9]+: +fffffff0 +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +ABS +bar diff --git a/gas/testsuite/gas/i386/x86-64-gotpcrel.d b/gas/testsuite/gas/i386/x86-64-gotpcrel.d index 57792216e9a..12fadfbca4e 100644 --- a/gas/testsuite/gas/i386/x86-64-gotpcrel.d +++ b/gas/testsuite/gas/i386/x86-64-gotpcrel.d @@ -24,4 +24,16 @@ Disassembly of section .text: [ ]*[a-f0-9]+: ff 90 00 00 00 00 call \*0x0\(%rax\) 5a: R_X86_64_GOTPCREL foo [ ]*[a-f0-9]+: ff 25 00 00 00 00 jmp \*0x0\(%rip\) # 64 <_start\+0x64> 60: R_X86_64_GOTPCRELX foo-0x4 [ ]*[a-f0-9]+: ff a1 00 00 00 00 jmp \*0x0\(%rcx\) 66: R_X86_64_GOTPCREL foo +[ ]*[a-f0-9]+: d5 18 c7 c0 00 00 00 00 mov \$0x0,%r16 6e: R_X86_64_GOTPCREL foo +[ ]*[a-f0-9]+: d5 48 8b 24 25 00 00 00 00 mov 0x0,%r20 77: R_X86_64_GOTPCREL foo +[ ]*[a-f0-9]+: d5 48 8b 35 00 00 00 00 mov 0x0\(%rip\),%r22 # 83 <_start\+0x83> 7f: R_X86_64_CODE_4_GOTPCRELX foo-0x4 +[ ]*[a-f0-9]+: d5 59 8b b4 24 00 00 00 00 mov 0x0\(%r28\),%r22 88: R_X86_64_GOTPCREL foo +[ ]*[a-f0-9]+: d5 10 ff 90 00 00 00 00 call \*0x0\(%r16\) 90: R_X86_64_GOTPCREL foo +[ ]*[a-f0-9]+: d5 11 ff a4 24 00 00 00 00 jmp \*0x0\(%r28\) 99: R_X86_64_GOTPCREL foo +[ ]*[a-f0-9]+: d5 18 c7 c0 00 00 00 00 mov \$0x0,%r16 a1: R_X86_64_GOTPCREL foo +[ ]*[a-f0-9]+: d5 48 8b 24 25 00 00 00 00 mov 0x0,%r20 aa: R_X86_64_GOTPCREL foo +[ ]*[a-f0-9]+: d5 48 8b 35 00 00 00 00 mov 0x0\(%rip\),%r22 # b6 <_start\+0xb6> b2: R_X86_64_CODE_4_GOTPCRELX foo-0x4 +[ ]*[a-f0-9]+: d5 59 8b b4 24 00 00 00 00 mov 0x0\(%r28\),%r22 bb: R_X86_64_GOTPCREL foo +[ ]*[a-f0-9]+: d5 10 ff 90 00 00 00 00 call \*0x0\(%r16\) c3: R_X86_64_GOTPCREL foo +[ ]*[a-f0-9]+: d5 11 ff a4 24 00 00 00 00 jmp \*0x0\(%r28\) cc: R_X86_64_GOTPCREL foo #pass diff --git a/gas/testsuite/gas/i386/x86-64-gotpcrel.s b/gas/testsuite/gas/i386/x86-64-gotpcrel.s index 981b14ff4df..91b1ca204c8 100644 --- a/gas/testsuite/gas/i386/x86-64-gotpcrel.s +++ b/gas/testsuite/gas/i386/x86-64-gotpcrel.s @@ -21,3 +21,22 @@ _start: call QWORD PTR [rax + foo@GOTPCREL] jmp QWORD PTR [rip + foo@GOTPCREL] jmp QWORD PTR [rcx + foo@GOTPCREL] + + .att_syntax prefix + movq $foo@GOTPCREL, %r16 + movq foo@GOTPCREL, %r20 + movq foo@GOTPCREL(%rip), %r22 + movq foo@GOTPCREL(%r28), %r22 + + call *foo@GOTPCREL(%r16) + jmp *foo@GOTPCREL(%r28) + + .intel_syntax noprefix + + mov r16, offset foo@gotpcrel + mov r20, QWORD PTR [foo@GOTPCREL] + mov r22, QWORD PTR [rip + foo@GOTPCREL] + mov r22, QWORD PTR [r28 + foo@GOTPCREL] + + call QWORD PTR [r16 + foo@GOTPCREL] + jmp QWORD PTR [r28 + foo@GOTPCREL] diff --git a/gas/testsuite/gas/i386/x86-64-localpic.d b/gas/testsuite/gas/i386/x86-64-localpic.d index 62030d410ad..11eb57b30b7 100644 --- a/gas/testsuite/gas/i386/x86-64-localpic.d +++ b/gas/testsuite/gas/i386/x86-64-localpic.d @@ -2,10 +2,12 @@ #readelf: -rsW #name: x86-64 local PIC -Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 2 entries: +Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 4 entries: +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend [0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +foo - 4 [0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +bar - 4 +[0-9a-f]+ +[0-9a-f]+ R_X86_64_CODE_4_GOTPCRELX +[0-9a-f]+ +foo - 4 +[0-9a-f]+ +[0-9a-f]+ R_X86_64_CODE_4_GOTPCRELX +[0-9a-f]+ +bar - 4 #... +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo +[0-9]+: +0+fffffff0 +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +ABS +bar diff --git a/gas/testsuite/gas/i386/x86-64-localpic.s b/gas/testsuite/gas/i386/x86-64-localpic.s index beda94dc2f3..183dfb6293b 100644 --- a/gas/testsuite/gas/i386/x86-64-localpic.s +++ b/gas/testsuite/gas/i386/x86-64-localpic.s @@ -3,4 +3,6 @@ foo: .quad 0 movq foo@GOTPCREL(%rip), %rax movq bar@GOTPCREL(%rip), %rax + movq foo@GOTPCREL(%rip), %r26 + movq bar@GOTPCREL(%rip), %r26 bar = 0xfffffff0 diff --git a/gas/write.h b/gas/write.h index eb30a76bf85..fd0ab553b23 100644 --- a/gas/write.h +++ b/gas/write.h @@ -81,9 +81,10 @@ struct fix /* Some bits for the CPU specific code. */ unsigned fx_tcbit : 1; unsigned fx_tcbit2 : 1; + unsigned fx_tcbit3 : 1; /* Spare bits. */ - unsigned fx_unused : 2; + unsigned fx_unused : 1; bfd_reloc_code_real_type fx_r_type; diff --git a/include/elf/x86-64.h b/include/elf/x86-64.h index 1b87beef41a..30d1722cb73 100644 --- a/include/elf/x86-64.h +++ b/include/elf/x86-64.h @@ -77,11 +77,15 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_type) RELOC_NUMBER (R_X86_64_PLT32_BND, 40) /* 32 bit PLT address with BND prefix */ /* Load from 32 bit signed pc relative offset to GOT entry without - REX prefix, relaxable. */ + REX nor REX2 prefixes, relaxable. */ RELOC_NUMBER (R_X86_64_GOTPCRELX, 41) /* Load from 32 bit signed pc relative offset to GOT entry with REX prefix, relaxable. */ RELOC_NUMBER (R_X86_64_REX_GOTPCRELX, 42) + /* Load from 32 bit signed pc relative offset to GOT entry if the + instruction starts at 4 bytes before the relocation offset, + relaxable. */ + RELOC_NUMBER (R_X86_64_CODE_4_GOTPCRELX, 43) RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250) /* GNU C++ hack */ RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251) /* GNU C++ hack */ END_RELOC_NUMBERS (R_X86_64_max) diff --git a/ld/testsuite/ld-x86-64/apx-load1.s b/ld/testsuite/ld-x86-64/apx-load1.s new file mode 100644 index 00000000000..f5eac57d82e --- /dev/null +++ b/ld/testsuite/ld-x86-64/apx-load1.s @@ -0,0 +1,51 @@ + .data + .type bar, @object +bar: + .byte 1 + .size bar, .-bar + .globl foo + .type foo, @object +foo: + .byte 1 + .size foo, .-foo + .text + .globl _start + .type _start, @function +_start: + adcl bar@GOTPCREL(%rip), %r16d + addl bar@GOTPCREL(%rip), %r17d + andl bar@GOTPCREL(%rip), %r18d + cmpl bar@GOTPCREL(%rip), %r19d + orl bar@GOTPCREL(%rip), %r20d + sbbl bar@GOTPCREL(%rip), %r21d + subl bar@GOTPCREL(%rip), %r22d + xorl bar@GOTPCREL(%rip), %r23d + testl %r24d, bar@GOTPCREL(%rip) + adcq bar@GOTPCREL(%rip), %r16 + addq bar@GOTPCREL(%rip), %r17 + andq bar@GOTPCREL(%rip), %r18 + cmpq bar@GOTPCREL(%rip), %r19 + orq bar@GOTPCREL(%rip), %r20 + sbbq bar@GOTPCREL(%rip), %r21 + subq bar@GOTPCREL(%rip), %r22 + xorq bar@GOTPCREL(%rip), %r23 + testq %r24, bar@GOTPCREL(%rip) + adcl foo@GOTPCREL(%rip), %r16d + addl foo@GOTPCREL(%rip), %r17d + andl foo@GOTPCREL(%rip), %r18d + cmpl foo@GOTPCREL(%rip), %r19d + orl foo@GOTPCREL(%rip), %r20d + sbbl foo@GOTPCREL(%rip), %r21d + subl foo@GOTPCREL(%rip), %r22d + xorl foo@GOTPCREL(%rip), %r23d + testl %r24d, foo@GOTPCREL(%rip) + adcq foo@GOTPCREL(%rip), %r16 + addq foo@GOTPCREL(%rip), %r17 + andq foo@GOTPCREL(%rip), %r18 + cmpq foo@GOTPCREL(%rip), %r19 + orq foo@GOTPCREL(%rip), %r20 + sbbq foo@GOTPCREL(%rip), %r21 + subq foo@GOTPCREL(%rip), %r22 + xorq foo@GOTPCREL(%rip), %r23 + testq %r24, foo@GOTPCREL(%rip) + .size _start, .-_start diff --git a/ld/testsuite/ld-x86-64/apx-load1a.d b/ld/testsuite/ld-x86-64/apx-load1a.d new file mode 100644 index 00000000000..162a2343ebe --- /dev/null +++ b/ld/testsuite/ld-x86-64/apx-load1a.d @@ -0,0 +1,54 @@ +#source: apx-load1.s +#as: --64 -mrelax-relocations=yes +#ld: -melf_x86_64 -z max-page-size=0x200000 -z noseparate-code +#objdump: -dw --sym + +.*: +file format .* + +SYMBOL TABLE: +#... +0+6001d0 l O .data 0+1 bar +#... +0+6001d1 g O .data 0+1 foo +#... + +Disassembly of section .text: + +0+4000b0 <_start>: + +[a-f0-9]+: d5 10 81 d0 d0 01 60 00 adc \$0x6001d0,%r16d + +[a-f0-9]+: d5 10 81 c1 d0 01 60 00 add \$0x6001d0,%r17d + +[a-f0-9]+: d5 10 81 e2 d0 01 60 00 and \$0x6001d0,%r18d + +[a-f0-9]+: d5 10 81 fb d0 01 60 00 cmp \$0x6001d0,%r19d + +[a-f0-9]+: d5 10 81 cc d0 01 60 00 or \$0x6001d0,%r20d + +[a-f0-9]+: d5 10 81 dd d0 01 60 00 sbb \$0x6001d0,%r21d + +[a-f0-9]+: d5 10 81 ee d0 01 60 00 sub \$0x6001d0,%r22d + +[a-f0-9]+: d5 10 81 f7 d0 01 60 00 xor \$0x6001d0,%r23d + +[a-f0-9]+: d5 11 f7 c0 d0 01 60 00 test \$0x6001d0,%r24d + +[a-f0-9]+: d5 18 81 d0 d0 01 60 00 adc \$0x6001d0,%r16 + +[a-f0-9]+: d5 18 81 c1 d0 01 60 00 add \$0x6001d0,%r17 + +[a-f0-9]+: d5 18 81 e2 d0 01 60 00 and \$0x6001d0,%r18 + +[a-f0-9]+: d5 18 81 fb d0 01 60 00 cmp \$0x6001d0,%r19 + +[a-f0-9]+: d5 18 81 cc d0 01 60 00 or \$0x6001d0,%r20 + +[a-f0-9]+: d5 18 81 dd d0 01 60 00 sbb \$0x6001d0,%r21 + +[a-f0-9]+: d5 18 81 ee d0 01 60 00 sub \$0x6001d0,%r22 + +[a-f0-9]+: d5 18 81 f7 d0 01 60 00 xor \$0x6001d0,%r23 + +[a-f0-9]+: d5 19 f7 c0 d0 01 60 00 test \$0x6001d0,%r24 + +[a-f0-9]+: d5 10 81 d0 d1 01 60 00 adc \$0x6001d1,%r16d + +[a-f0-9]+: d5 10 81 c1 d1 01 60 00 add \$0x6001d1,%r17d + +[a-f0-9]+: d5 10 81 e2 d1 01 60 00 and \$0x6001d1,%r18d + +[a-f0-9]+: d5 10 81 fb d1 01 60 00 cmp \$0x6001d1,%r19d + +[a-f0-9]+: d5 10 81 cc d1 01 60 00 or \$0x6001d1,%r20d + +[a-f0-9]+: d5 10 81 dd d1 01 60 00 sbb \$0x6001d1,%r21d + +[a-f0-9]+: d5 10 81 ee d1 01 60 00 sub \$0x6001d1,%r22d + +[a-f0-9]+: d5 10 81 f7 d1 01 60 00 xor \$0x6001d1,%r23d + +[a-f0-9]+: d5 11 f7 c0 d1 01 60 00 test \$0x6001d1,%r24d + +[a-f0-9]+: d5 18 81 d0 d1 01 60 00 adc \$0x6001d1,%r16 + +[a-f0-9]+: d5 18 81 c1 d1 01 60 00 add \$0x6001d1,%r17 + +[a-f0-9]+: d5 18 81 e2 d1 01 60 00 and \$0x6001d1,%r18 + +[a-f0-9]+: d5 18 81 fb d1 01 60 00 cmp \$0x6001d1,%r19 + +[a-f0-9]+: d5 18 81 cc d1 01 60 00 or \$0x6001d1,%r20 + +[a-f0-9]+: d5 18 81 dd d1 01 60 00 sbb \$0x6001d1,%r21 + +[a-f0-9]+: d5 18 81 ee d1 01 60 00 sub \$0x6001d1,%r22 + +[a-f0-9]+: d5 18 81 f7 d1 01 60 00 xor \$0x6001d1,%r23 + +[a-f0-9]+: d5 19 f7 c0 d1 01 60 00 test \$0x6001d1,%r24 +#pass diff --git a/ld/testsuite/ld-x86-64/apx-load1b.d b/ld/testsuite/ld-x86-64/apx-load1b.d new file mode 100644 index 00000000000..8c8962cad2d --- /dev/null +++ b/ld/testsuite/ld-x86-64/apx-load1b.d @@ -0,0 +1,55 @@ +#source: apx-load1.s +#as: --x32 -mrelax-relocations=yes +#ld: -melf32_x86_64 -z max-page-size=0x200000 -z noseparate-code +#objdump: -dw --sym + +.*: +file format .* + +SYMBOL TABLE: +#... +0+600194 l O .data 0+1 bar +#... +0+600195 g O .data 0+1 foo +#... + + +Disassembly of section .text: + +0+400074 <_start>: + +[a-f0-9]+: d5 10 81 d0 94 01 60 00 adc \$0x600194,%r16d + +[a-f0-9]+: d5 10 81 c1 94 01 60 00 add \$0x600194,%r17d + +[a-f0-9]+: d5 10 81 e2 94 01 60 00 and \$0x600194,%r18d + +[a-f0-9]+: d5 10 81 fb 94 01 60 00 cmp \$0x600194,%r19d + +[a-f0-9]+: d5 10 81 cc 94 01 60 00 or \$0x600194,%r20d + +[a-f0-9]+: d5 10 81 dd 94 01 60 00 sbb \$0x600194,%r21d + +[a-f0-9]+: d5 10 81 ee 94 01 60 00 sub \$0x600194,%r22d + +[a-f0-9]+: d5 10 81 f7 94 01 60 00 xor \$0x600194,%r23d + +[a-f0-9]+: d5 11 f7 c0 94 01 60 00 test \$0x600194,%r24d + +[a-f0-9]+: d5 18 81 d0 94 01 60 00 adc \$0x600194,%r16 + +[a-f0-9]+: d5 18 81 c1 94 01 60 00 add \$0x600194,%r17 + +[a-f0-9]+: d5 18 81 e2 94 01 60 00 and \$0x600194,%r18 + +[a-f0-9]+: d5 18 81 fb 94 01 60 00 cmp \$0x600194,%r19 + +[a-f0-9]+: d5 18 81 cc 94 01 60 00 or \$0x600194,%r20 + +[a-f0-9]+: d5 18 81 dd 94 01 60 00 sbb \$0x600194,%r21 + +[a-f0-9]+: d5 18 81 ee 94 01 60 00 sub \$0x600194,%r22 + +[a-f0-9]+: d5 18 81 f7 94 01 60 00 xor \$0x600194,%r23 + +[a-f0-9]+: d5 19 f7 c0 94 01 60 00 test \$0x600194,%r24 + +[a-f0-9]+: d5 10 81 d0 95 01 60 00 adc \$0x600195,%r16d + +[a-f0-9]+: d5 10 81 c1 95 01 60 00 add \$0x600195,%r17d + +[a-f0-9]+: d5 10 81 e2 95 01 60 00 and \$0x600195,%r18d + +[a-f0-9]+: d5 10 81 fb 95 01 60 00 cmp \$0x600195,%r19d + +[a-f0-9]+: d5 10 81 cc 95 01 60 00 or \$0x600195,%r20d + +[a-f0-9]+: d5 10 81 dd 95 01 60 00 sbb \$0x600195,%r21d + +[a-f0-9]+: d5 10 81 ee 95 01 60 00 sub \$0x600195,%r22d + +[a-f0-9]+: d5 10 81 f7 95 01 60 00 xor \$0x600195,%r23d + +[a-f0-9]+: d5 11 f7 c0 95 01 60 00 test \$0x600195,%r24d + +[a-f0-9]+: d5 18 81 d0 95 01 60 00 adc \$0x600195,%r16 + +[a-f0-9]+: d5 18 81 c1 95 01 60 00 add \$0x600195,%r17 + +[a-f0-9]+: d5 18 81 e2 95 01 60 00 and \$0x600195,%r18 + +[a-f0-9]+: d5 18 81 fb 95 01 60 00 cmp \$0x600195,%r19 + +[a-f0-9]+: d5 18 81 cc 95 01 60 00 or \$0x600195,%r20 + +[a-f0-9]+: d5 18 81 dd 95 01 60 00 sbb \$0x600195,%r21 + +[a-f0-9]+: d5 18 81 ee 95 01 60 00 sub \$0x600195,%r22 + +[a-f0-9]+: d5 18 81 f7 95 01 60 00 xor \$0x600195,%r23 + +[a-f0-9]+: d5 19 f7 c0 95 01 60 00 test \$0x600195,%r24 +#pass diff --git a/ld/testsuite/ld-x86-64/apx-load1c.d b/ld/testsuite/ld-x86-64/apx-load1c.d new file mode 100644 index 00000000000..fdfe00cc61c --- /dev/null +++ b/ld/testsuite/ld-x86-64/apx-load1c.d @@ -0,0 +1,47 @@ +#source: apx-load1.s +#as: --64 +#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS +#objdump: -dw + +.*: +file format .* + +Disassembly of section .text: + +0+188 <_start>: + +[a-f0-9]+: d5 40 13 05 f8 01 20 00 adc 0x2001f8\(%rip\),%r16d # 200388 <.*> + +[a-f0-9]+: d5 40 03 0d f0 01 20 00 add 0x2001f0\(%rip\),%r17d # 200388 <.*> + +[a-f0-9]+: d5 40 23 15 e8 01 20 00 and 0x2001e8\(%rip\),%r18d # 200388 <.*> + +[a-f0-9]+: d5 40 3b 1d e0 01 20 00 cmp 0x2001e0\(%rip\),%r19d # 200388 <.*> + +[a-f0-9]+: d5 40 0b 25 d8 01 20 00 or 0x2001d8\(%rip\),%r20d # 200388 <.*> + +[a-f0-9]+: d5 40 1b 2d d0 01 20 00 sbb 0x2001d0\(%rip\),%r21d # 200388 <.*> + +[a-f0-9]+: d5 40 2b 35 c8 01 20 00 sub 0x2001c8\(%rip\),%r22d # 200388 <.*> + +[a-f0-9]+: d5 40 33 3d c0 01 20 00 xor 0x2001c0\(%rip\),%r23d # 200388 <.*> + +[a-f0-9]+: d5 44 85 05 b8 01 20 00 test %r24d,0x2001b8\(%rip\) # 200388 <.*> + +[a-f0-9]+: d5 48 13 05 b0 01 20 00 adc 0x2001b0\(%rip\),%r16 # 200388 <.*> + +[a-f0-9]+: d5 48 03 0d a8 01 20 00 add 0x2001a8\(%rip\),%r17 # 200388 <.*> + +[a-f0-9]+: d5 48 23 15 a0 01 20 00 and 0x2001a0\(%rip\),%r18 # 200388 <.*> + +[a-f0-9]+: d5 48 3b 1d 98 01 20 00 cmp 0x200198\(%rip\),%r19 # 200388 <.*> + +[a-f0-9]+: d5 48 0b 25 90 01 20 00 or 0x200190\(%rip\),%r20 # 200388 <.*> + +[a-f0-9]+: d5 48 1b 2d 88 01 20 00 sbb 0x200188\(%rip\),%r21 # 200388 <.*> + +[a-f0-9]+: d5 48 2b 35 80 01 20 00 sub 0x200180\(%rip\),%r22 # 200388 <.*> + +[a-f0-9]+: d5 48 33 3d 78 01 20 00 xor 0x200178\(%rip\),%r23 # 200388 <.*> + +[a-f0-9]+: d5 4c 85 05 70 01 20 00 test %r24,0x200170\(%rip\) # 200388 <.*> + +[a-f0-9]+: d5 40 13 05 70 01 20 00 adc 0x200170\(%rip\),%r16d # 200390 <.*> + +[a-f0-9]+: d5 40 03 0d 68 01 20 00 add 0x200168\(%rip\),%r17d # 200390 <.*> + +[a-f0-9]+: d5 40 23 15 60 01 20 00 and 0x200160\(%rip\),%r18d # 200390 <.*> + +[a-f0-9]+: d5 40 3b 1d 58 01 20 00 cmp 0x200158\(%rip\),%r19d # 200390 <.*> + +[a-f0-9]+: d5 40 0b 25 50 01 20 00 or 0x200150\(%rip\),%r20d # 200390 <.*> + +[a-f0-9]+: d5 40 1b 2d 48 01 20 00 sbb 0x200148\(%rip\),%r21d # 200390 <.*> + +[a-f0-9]+: d5 40 2b 35 40 01 20 00 sub 0x200140\(%rip\),%r22d # 200390 <.*> + +[a-f0-9]+: d5 40 33 3d 38 01 20 00 xor 0x200138\(%rip\),%r23d # 200390 <.*> + +[a-f0-9]+: d5 44 85 05 30 01 20 00 test %r24d,0x200130\(%rip\) # 200390 <.*> + +[a-f0-9]+: d5 48 13 05 28 01 20 00 adc 0x200128\(%rip\),%r16 # 200390 <.*> + +[a-f0-9]+: d5 48 03 0d 20 01 20 00 add 0x200120\(%rip\),%r17 # 200390 <.*> + +[a-f0-9]+: d5 48 23 15 18 01 20 00 and 0x200118\(%rip\),%r18 # 200390 <.*> + +[a-f0-9]+: d5 48 3b 1d 10 01 20 00 cmp 0x200110\(%rip\),%r19 # 200390 <.*> + +[a-f0-9]+: d5 48 0b 25 08 01 20 00 or 0x200108\(%rip\),%r20 # 200390 <.*> + +[a-f0-9]+: d5 48 1b 2d 00 01 20 00 sbb 0x200100\(%rip\),%r21 # 200390 <.*> + +[a-f0-9]+: d5 48 2b 35 f8 00 20 00 sub 0x2000f8\(%rip\),%r22 # 200390 <.*> + +[a-f0-9]+: d5 48 33 3d f0 00 20 00 xor 0x2000f0\(%rip\),%r23 # 200390 <.*> + +[a-f0-9]+: d5 4c 85 05 e8 00 20 00 test %r24,0x2000e8\(%rip\) # 200390 <.*> +#pass diff --git a/ld/testsuite/ld-x86-64/apx-load1d.d b/ld/testsuite/ld-x86-64/apx-load1d.d new file mode 100644 index 00000000000..4da967822ea --- /dev/null +++ b/ld/testsuite/ld-x86-64/apx-load1d.d @@ -0,0 +1,47 @@ +#source: apx-load1.s +#as: --x32 +#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS +#objdump: -dw + +.*: +file format .* + +Disassembly of section .text: + +0+100 <_start>: + +[a-f0-9]+: d5 40 13 05 88 01 20 00 adc 0x200188\(%rip\),%r16d # 200290 <.*> + +[a-f0-9]+: d5 40 03 0d 80 01 20 00 add 0x200180\(%rip\),%r17d # 200290 <.*> + +[a-f0-9]+: d5 40 23 15 78 01 20 00 and 0x200178\(%rip\),%r18d # 200290 <.*> + +[a-f0-9]+: d5 40 3b 1d 70 01 20 00 cmp 0x200170\(%rip\),%r19d # 200290 <.*> + +[a-f0-9]+: d5 40 0b 25 68 01 20 00 or 0x200168\(%rip\),%r20d # 200290 <.*> + +[a-f0-9]+: d5 40 1b 2d 60 01 20 00 sbb 0x200160\(%rip\),%r21d # 200290 <.*> + +[a-f0-9]+: d5 40 2b 35 58 01 20 00 sub 0x200158\(%rip\),%r22d # 200290 <.*> + +[a-f0-9]+: d5 40 33 3d 50 01 20 00 xor 0x200150\(%rip\),%r23d # 200290 <.*> + +[a-f0-9]+: d5 44 85 05 48 01 20 00 test %r24d,0x200148\(%rip\) # 200290 <.*> + +[a-f0-9]+: d5 48 13 05 40 01 20 00 adc 0x200140\(%rip\),%r16 # 200290 <.*> + +[a-f0-9]+: d5 48 03 0d 38 01 20 00 add 0x200138\(%rip\),%r17 # 200290 <.*> + +[a-f0-9]+: d5 48 23 15 30 01 20 00 and 0x200130\(%rip\),%r18 # 200290 <.*> + +[a-f0-9]+: d5 48 3b 1d 28 01 20 00 cmp 0x200128\(%rip\),%r19 # 200290 <.*> + +[a-f0-9]+: d5 48 0b 25 20 01 20 00 or 0x200120\(%rip\),%r20 # 200290 <.*> + +[a-f0-9]+: d5 48 1b 2d 18 01 20 00 sbb 0x200118\(%rip\),%r21 # 200290 <.*> + +[a-f0-9]+: d5 48 2b 35 10 01 20 00 sub 0x200110\(%rip\),%r22 # 200290 <.*> + +[a-f0-9]+: d5 48 33 3d 08 01 20 00 xor 0x200108\(%rip\),%r23 # 200290 <.*> + +[a-f0-9]+: d5 4c 85 05 00 01 20 00 test %r24,0x200100\(%rip\) # 200290 <.*> + +[a-f0-9]+: d5 40 13 05 00 01 20 00 adc 0x200100\(%rip\),%r16d # 200298 <.*> + +[a-f0-9]+: d5 40 03 0d f8 00 20 00 add 0x2000f8\(%rip\),%r17d # 200298 <.*> + +[a-f0-9]+: d5 40 23 15 f0 00 20 00 and 0x2000f0\(%rip\),%r18d # 200298 <.*> + +[a-f0-9]+: d5 40 3b 1d e8 00 20 00 cmp 0x2000e8\(%rip\),%r19d # 200298 <.*> + +[a-f0-9]+: d5 40 0b 25 e0 00 20 00 or 0x2000e0\(%rip\),%r20d # 200298 <.*> + +[a-f0-9]+: d5 40 1b 2d d8 00 20 00 sbb 0x2000d8\(%rip\),%r21d # 200298 <.*> + +[a-f0-9]+: d5 40 2b 35 d0 00 20 00 sub 0x2000d0\(%rip\),%r22d # 200298 <.*> + +[a-f0-9]+: d5 40 33 3d c8 00 20 00 xor 0x2000c8\(%rip\),%r23d # 200298 <.*> + +[a-f0-9]+: d5 44 85 05 c0 00 20 00 test %r24d,0x2000c0\(%rip\) # 200298 <.*> + +[a-f0-9]+: d5 48 13 05 b8 00 20 00 adc 0x2000b8\(%rip\),%r16 # 200298 <.*> + +[a-f0-9]+: d5 48 03 0d b0 00 20 00 add 0x2000b0\(%rip\),%r17 # 200298 <.*> + +[a-f0-9]+: d5 48 23 15 a8 00 20 00 and 0x2000a8\(%rip\),%r18 # 200298 <.*> + +[a-f0-9]+: d5 48 3b 1d a0 00 20 00 cmp 0x2000a0\(%rip\),%r19 # 200298 <.*> + +[a-f0-9]+: d5 48 0b 25 98 00 20 00 or 0x200098\(%rip\),%r20 # 200298 <.*> + +[a-f0-9]+: d5 48 1b 2d 90 00 20 00 sbb 0x200090\(%rip\),%r21 # 200298 <.*> + +[a-f0-9]+: d5 48 2b 35 88 00 20 00 sub 0x200088\(%rip\),%r22 # 200298 <.*> + +[a-f0-9]+: d5 48 33 3d 80 00 20 00 xor 0x200080\(%rip\),%r23 # 200298 <.*> + +[a-f0-9]+: d5 4c 85 05 78 00 20 00 test %r24,0x200078\(%rip\) # 200298 <.*> +#pass diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 95a2986265b..d5c5219222c 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -605,6 +605,10 @@ run_dump_test "load1a" run_dump_test "load1b" run_dump_test "load1c" run_dump_test "load1d" +run_dump_test "apx-load1a" +run_dump_test "apx-load1b" +run_dump_test "apx-load1c" +run_dump_test "apx-load1d" run_dump_test "load2" run_dump_test "call1a" run_dump_test "call1b" From patchwork Thu Dec 28 14:58:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 82917 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 1DF6E3858004 for ; Thu, 28 Dec 2023 14:58:54 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-pg1-x529.google.com (mail-pg1-x529.google.com [IPv6:2607:f8b0:4864:20::529]) by sourceware.org (Postfix) with ESMTPS id E90E93858288 for ; Thu, 28 Dec 2023 14:58:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E90E93858288 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E90E93858288 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::529 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1703775490; cv=none; b=b4bVpRn3IeZlRl4FvH9R1Ut7wAFnM9s0ytCkE1P3/6Q2iXNvxZIWg29HqGlHgXmCX3MW48SN8V67WngLLDIgtYPDYN++7dPWcDPTTG9L4/9SkPvHzSQ7+LdOv5tE4XQktOAWC2O2R5XuoA62TlaQ/uMXk72JOUb4KcBNwbL4s1s= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1703775490; c=relaxed/simple; bh=ZfYhQtvhD5amxjySmMNOAwjxONNNBXHpxoexphDUnmA=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=kPk04JJGEqUd1YeCppCVZ/vuZ5o+Xgzp30swbU4Upp40cFRS1xqWgrvpfoXmEDE82nzwCRAAPvjlXTi2AFuRrERVI4RGe2MBX3yU9SyHXXnf3AmqJb05xWQfBdXQap37Diib0rIB7cL2EX2nNhpdzs0rMbL8PMc02vf6V3oSyu0= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pg1-x529.google.com with SMTP id 41be03b00d2f7-5cd51c0e8ebso2260111a12.3 for ; Thu, 28 Dec 2023 06:58:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1703775486; x=1704380286; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=g4azVjjVGpRdoUKZneI6fghF77OOJDWSdm51IY4UgLo=; b=V8aeKWyRRPtFaPd8d2F8V2B+yMUEoIvMms/Oc0TNohPpH66MUfWFzcEUP+e8YNyHjO LZbMNYP5ATVsTTRFeTDeqL7XPEZWnvlSq16YCix8UcNe+tB1WgtYc+0phG+oXbLHAoTs 3h28web4Y8IG7UsckmE1798QMF444PhuWkAgYJuyFebVymfeVPYo5NE0PJmYNXxvGjpA X949Z8OLGORF0haL9TmgFwlq5xnPCC3mTrNWlSCeygZeLD64VoqbbYjMyRjsBZ2vwKT1 GwASQIU8VLb8EARSSxgRqPN+JhQQ49T6Uw9DzpEN8GRz3o3/2Pg2I0aYsmTaegiZOVxh D4+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703775486; x=1704380286; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=g4azVjjVGpRdoUKZneI6fghF77OOJDWSdm51IY4UgLo=; b=SUXezQrcUaBiuiOhGM6uoGlpEeep/iDcVGAiJsGetfA4e4yTpj63IoU42AVeJz9irP Q6MQnt22AUWEDhlj9W6nRp/A+Y9KN6RSuin7qxLhJSvWLWtEWQmUCSyFshnnsfS/fA40 mh+n3ZENCP9m02NeFqpTLK5PhUZQ1jPWyRij9EQjkrmPmJcvuh2BZhmTKQ8pQQRwNnPb GwRV6PjfDq442dTMxgmFgLkm/abO35HbAcww/paLKa0n4tyq2DRE9/MqWWzX033HH6RE dNOrpKWBn0kL/5uh+fsgkWPBAuX2d+qpfegGERZBSIO9AcrRKy3Pk2PvGxRw6qeWq0cm 5SMA== X-Gm-Message-State: AOJu0YyGUWw3ddcr+KKq/G/o3+zBlFo9dzPXI2RHKO9SgGdIQE9O57FL a0hma6XjyB+aQ4nYJdNje5p1+VnVqYg= X-Google-Smtp-Source: AGHT+IH8GK8xkWwfymjSJu5li0FokmDMcI5Xsci3IrGKjxy95iK7uyimpjNg4iGcDYnww1Fvs4wMlg== X-Received: by 2002:a05:6a20:429b:b0:196:6208:8ffb with SMTP id o27-20020a056a20429b00b0019662088ffbmr330374pzj.11.1703775486260; Thu, 28 Dec 2023 06:58:06 -0800 (PST) Received: from gnu-cfl-3.localdomain ([172.56.169.119]) by smtp.gmail.com with ESMTPSA id y12-20020aa7854c000000b006d9af59eecesm8626196pfn.20.2023.12.28.06.58.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Dec 2023 06:58:05 -0800 (PST) Received: from gnu-cfl-3.. (localhost [IPv6:::1]) by gnu-cfl-3.localdomain (Postfix) with ESMTP id C7562740652 for ; Thu, 28 Dec 2023 06:58:04 -0800 (PST) From: "H.J. Lu" To: binutils@sourceware.org Subject: [PATCH 2/4] gold: Handle R_X86_64_CODE_4_GOTPCRELX Date: Thu, 28 Dec 2023 06:58:02 -0800 Message-ID: <20231228145804.658337-3-hjl.tools@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231228145804.658337-1-hjl.tools@gmail.com> References: <20231228145804.658337-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3024.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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 Handle R_X86_64_CODE_4_GOTPCRELX and convert mov name@GOTPCREL(%rip), %r31 to lea name@GOTPCREL(%rip), %r31 if the instruction is encoded with the REX2 prefix when possible. elfcpp/ * x86_64.h (R_X86_64_CODE_4_GOTPCRELX): New. gold/ * x86_64.cc (Target_x86_64::can_convert_mov_to_lea): Handle R_X86_64_CODE_4_GOTPCRELX. (Target_x86_64::Scan::get_reference_flags): Likewise. (Target_x86_64::Scan::local): Likewise. (Target_x86_64::Scan::possible_function_pointer_reloc): Likewise. (Target_x86_64::Scan::global): Likewise. (Target_x86_64::Relocate::relocate): Likewise. * testsuite/x86_64_mov_to_lea1.s: Add a test for R_X86_64_CODE_4_GOTPCRELX. * testsuite/x86_64_mov_to_lea2.s: Likewise. * testsuite/x86_64_mov_to_lea3.s: Likewise. * testsuite/x86_64_mov_to_lea4.s: Likewise. * testsuite/x86_64_mov_to_lea5.s: Likewise. * testsuite/x86_64_mov_to_lea.sh: Updated. --- elfcpp/x86_64.h | 6 ++++- gold/testsuite/x86_64_mov_to_lea.sh | 16 +++++++++++++ gold/testsuite/x86_64_mov_to_lea1.s | 1 + gold/testsuite/x86_64_mov_to_lea2.s | 1 + gold/testsuite/x86_64_mov_to_lea3.s | 1 + gold/testsuite/x86_64_mov_to_lea4.s | 1 + gold/testsuite/x86_64_mov_to_lea5.s | 1 + gold/x86_64.cc | 37 ++++++++++++++++++++++------- 8 files changed, 54 insertions(+), 10 deletions(-) diff --git a/elfcpp/x86_64.h b/elfcpp/x86_64.h index 0377e773071..97a87ae424d 100644 --- a/elfcpp/x86_64.h +++ b/elfcpp/x86_64.h @@ -95,9 +95,13 @@ enum R_X86_64_PC32_BND = 39, // PC relative 32 bit signed with BND prefix R_X86_64_PLT32_BND = 40, // 32 bit PLT address with BND prefix R_X86_64_GOTPCRELX = 41, // 32 bit signed PC relative offset to GOT - // without REX prefix, relaxable. + // without REX nor REX2 prefixes, relaxable. R_X86_64_REX_GOTPCRELX = 42, // 32 bit signed PC relative offset to GOT // with REX prefix, relaxable. + R_X86_64_CODE_4_GOTPCRELX = 43, // 32 bit signed PC relative offset to + // GOT if the instruction starts at 4 + // bytes before the relocation offset, + // relaxable. // GNU vtable garbage collection extensions. R_X86_64_GNU_VTINHERIT = 250, R_X86_64_GNU_VTENTRY = 251 diff --git a/gold/testsuite/x86_64_mov_to_lea.sh b/gold/testsuite/x86_64_mov_to_lea.sh index 1b30e1aa048..3e248ebec3c 100755 --- a/gold/testsuite/x86_64_mov_to_lea.sh +++ b/gold/testsuite/x86_64_mov_to_lea.sh @@ -25,20 +25,36 @@ set -e grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea1.stdout +grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea1.stdout grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea2.stdout +grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea2.stdout grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea3.stdout +grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea3.stdout grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea4.stdout +grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea4.stdout grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea5.stdout +grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea5.stdout grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea6.stdout +grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea6.stdout grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea7.stdout +grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea7.stdout grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea8.stdout +grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea8.stdout grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea9.stdout +grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea9.stdout grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea10.stdout +grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea10.stdout grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea11.stdout +grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea11.stdout grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea12.stdout +grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea12.stdout grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea13.stdout +grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea13.stdout grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea14.stdout +grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea14.stdout grep -q "mov 0x[a-f0-9]\+(%rip),%eax" x86_64_mov_to_lea15.stdout +grep -q "mov 0x[a-f0-9]\+(%rip),%r26d" x86_64_mov_to_lea15.stdout grep -q "mov 0x[a-f0-9]\+(%rip),%eax" x86_64_mov_to_lea16.stdout +grep -q "mov 0x[a-f0-9]\+(%rip),%r26d" x86_64_mov_to_lea16.stdout exit 0 diff --git a/gold/testsuite/x86_64_mov_to_lea1.s b/gold/testsuite/x86_64_mov_to_lea1.s index 4dce487c3fc..298ede12f80 100644 --- a/gold/testsuite/x86_64_mov_to_lea1.s +++ b/gold/testsuite/x86_64_mov_to_lea1.s @@ -8,4 +8,5 @@ foo: .type _start, @function _start: movq foo@GOTPCREL(%rip), %rax + movq foo@GOTPCREL(%rip), %r26 .size _start, .-_start diff --git a/gold/testsuite/x86_64_mov_to_lea2.s b/gold/testsuite/x86_64_mov_to_lea2.s index 2a11b7a19f4..404f4c1dd48 100644 --- a/gold/testsuite/x86_64_mov_to_lea2.s +++ b/gold/testsuite/x86_64_mov_to_lea2.s @@ -3,4 +3,5 @@ .type _start, @function _start: movq _DYNAMIC@GOTPCREL(%rip), %rax + movq _DYNAMIC@GOTPCREL(%rip), %r26 .size _start, .-_start diff --git a/gold/testsuite/x86_64_mov_to_lea3.s b/gold/testsuite/x86_64_mov_to_lea3.s index ac43b783758..838c33edae0 100644 --- a/gold/testsuite/x86_64_mov_to_lea3.s +++ b/gold/testsuite/x86_64_mov_to_lea3.s @@ -7,4 +7,5 @@ foo: .type _start, @function _start: movq foo@GOTPCREL(%rip), %rax + movq foo@GOTPCREL(%rip), %r26 .size _start, .-_start diff --git a/gold/testsuite/x86_64_mov_to_lea4.s b/gold/testsuite/x86_64_mov_to_lea4.s index 37bee32bb4e..a68a4cf0d19 100644 --- a/gold/testsuite/x86_64_mov_to_lea4.s +++ b/gold/testsuite/x86_64_mov_to_lea4.s @@ -9,4 +9,5 @@ foo: .type _start, @function _start: movq foo@GOTPCREL(%rip), %rax + movq foo@GOTPCREL(%rip), %r26 .size _start, .-_start diff --git a/gold/testsuite/x86_64_mov_to_lea5.s b/gold/testsuite/x86_64_mov_to_lea5.s index e793a2b9b73..e818989deb7 100644 --- a/gold/testsuite/x86_64_mov_to_lea5.s +++ b/gold/testsuite/x86_64_mov_to_lea5.s @@ -9,4 +9,5 @@ foo: .type _start, @function _start: movl foo@GOTPCREL+4(%rip), %eax + movl foo@GOTPCREL+4(%rip), %r26d .size _start, .-_start diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 928dfa8ea34..b7be9bf0d48 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -1053,8 +1053,9 @@ class Target_x86_64 : public Sized_target gold_assert(gsym != NULL); // We cannot do the conversion unless it's one of these relocations. if (r_type != elfcpp::R_X86_64_GOTPCREL - && r_type != elfcpp::R_X86_64_GOTPCRELX - && r_type != elfcpp::R_X86_64_REX_GOTPCRELX) + && r_type != elfcpp::R_X86_64_GOTPCRELX + && r_type != elfcpp::R_X86_64_REX_GOTPCRELX + && r_type != elfcpp::R_X86_64_CODE_4_GOTPCRELX) return false; // We cannot convert references to IFUNC symbols, or to symbols that // are not local to the current module. @@ -2971,6 +2972,7 @@ Target_x86_64::Scan::get_reference_flags(unsigned int r_type) case elfcpp::R_X86_64_GOTPCREL: case elfcpp::R_X86_64_GOTPCRELX: case elfcpp::R_X86_64_REX_GOTPCRELX: + case elfcpp::R_X86_64_CODE_4_GOTPCRELX: case elfcpp::R_X86_64_GOTPLT64: // Absolute in GOT. return Symbol::ABSOLUTE_REF; @@ -3251,6 +3253,7 @@ Target_x86_64::Scan::local(Symbol_table* symtab, case elfcpp::R_X86_64_GOTPCREL: case elfcpp::R_X86_64_GOTPCRELX: case elfcpp::R_X86_64_REX_GOTPCRELX: + case elfcpp::R_X86_64_CODE_4_GOTPCRELX: case elfcpp::R_X86_64_GOTPLT64: { // The symbol requires a GOT section. @@ -3261,21 +3264,30 @@ Target_x86_64::Scan::local(Symbol_table* symtab, // mov foo@GOTPCREL(%rip), %reg // to lea foo(%rip), %reg. // in Relocate::relocate. + size_t r_offset = reloc.get_r_offset(); if (!parameters->incremental() - && (r_type == elfcpp::R_X86_64_GOTPCREL - || r_type == elfcpp::R_X86_64_GOTPCRELX - || r_type == elfcpp::R_X86_64_REX_GOTPCRELX) + && (((r_type == elfcpp::R_X86_64_GOTPCREL + || r_type == elfcpp::R_X86_64_GOTPCRELX + || r_type == elfcpp::R_X86_64_REX_GOTPCRELX) + && r_offset >= 2) + || (r_type == elfcpp::R_X86_64_CODE_4_GOTPCRELX + && r_offset >= 4)) && reloc.get_r_addend() == -4 - && reloc.get_r_offset() >= 2 && !is_ifunc) { section_size_type stype; const unsigned char* view = object->section_contents(data_shndx, &stype, true); - if (view[reloc.get_r_offset() - 2] == 0x8b) + if (r_type == elfcpp::R_X86_64_CODE_4_GOTPCRELX + && view[r_offset - 4] != 0xd5) + goto need_got; + + if (view[r_offset - 2] == 0x8b) break; } +need_got: + // The symbol requires a GOT entry. unsigned int r_sym = elfcpp::elf_r_sym(reloc.get_r_info()); @@ -3498,6 +3510,7 @@ Target_x86_64::Scan::possible_function_pointer_reloc( case elfcpp::R_X86_64_GOTPCREL: case elfcpp::R_X86_64_GOTPCRELX: case elfcpp::R_X86_64_REX_GOTPCRELX: + case elfcpp::R_X86_64_CODE_4_GOTPCRELX: case elfcpp::R_X86_64_GOTPLT64: { return true; @@ -3714,6 +3727,7 @@ Target_x86_64::Scan::global(Symbol_table* symtab, case elfcpp::R_X86_64_GOTPCREL: case elfcpp::R_X86_64_GOTPCRELX: case elfcpp::R_X86_64_REX_GOTPCRELX: + case elfcpp::R_X86_64_CODE_4_GOTPCRELX: case elfcpp::R_X86_64_GOTPLT64: { // The symbol requires a GOT entry. @@ -3736,8 +3750,12 @@ Target_x86_64::Scan::global(Symbol_table* symtab, size_t r_offset = reloc.get_r_offset(); if (!parameters->incremental() && reloc.get_r_addend() == -4 - && r_offset >= 2 - && Target_x86_64::can_convert_mov_to_lea(gsym, r_type, + && ((r_type != elfcpp::R_X86_64_CODE_4_GOTPCRELX + && r_offset >= 2) + || (r_type == elfcpp::R_X86_64_CODE_4_GOTPCRELX + && r_offset >= 4 + && view[r_offset - 4] == 0xd5)) + && Target_x86_64::can_convert_mov_to_lea(gsym, r_type, r_offset, &view)) break; @@ -4420,6 +4438,7 @@ Target_x86_64::Relocate::relocate( case elfcpp::R_X86_64_GOTPCREL: case elfcpp::R_X86_64_GOTPCRELX: case elfcpp::R_X86_64_REX_GOTPCRELX: + case elfcpp::R_X86_64_CODE_4_GOTPCRELX: { bool converted_p = false; From patchwork Thu Dec 28 14:58:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 82919 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 792323857BB2 for ; Thu, 28 Dec 2023 14:59:45 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-oa1-x30.google.com (mail-oa1-x30.google.com [IPv6:2001:4860:4864:20::30]) by sourceware.org (Postfix) with ESMTPS id D66613858294 for ; Thu, 28 Dec 2023 14:58:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D66613858294 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D66613858294 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2001:4860:4864:20::30 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1703775494; cv=none; b=XNCCRG7UcZcYSsrN58EXp6nEgDN5C1F9PDzFa1fXA7KQ3KZRqWUdQiWtMfz+lu7bIrmIueHEE0V8te783IbetpXRVU1EKXe2yrGZm3kfRUMZeuFkeinPMghktLQIvrkyBFnOSGNaGzp+m4GWRw9FT2R2IiGBDO8BT0tMXbB8ytQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1703775494; c=relaxed/simple; bh=GoKoYcQfAoZpCBKXWP2wwmoIIlNcEzQEzpDUTHF5ErU=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=ZRAGWc/jcBZtU2fW+Ioh1mNIe32X+eNfbd9zXWiNmxbCxfV1xW+8wh5cLQg68rmA8qC7zRAld7gxAJfcHxhmzbVhKtz+aQcbO68+6R38UDfNOlzE9VnkXeoaOUUxu9sp596DiOrPNrRoSQW3tbe60HHDdtAZXmbqG8hr4rgZHaE= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-oa1-x30.google.com with SMTP id 586e51a60fabf-20403a18a51so3440527fac.3 for ; Thu, 28 Dec 2023 06:58:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1703775488; x=1704380288; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=jUHrNC1tkpzPW6esQt7nSVr+fIDnxVFl7BlqrAA/roI=; b=B/1xWQYKMLSd3Xn00eCqkiDoI87c0xoSFBxoZExJDHM99l46NwbHQ/RMuZUZXuRDyh LGt53yH8DHrxYBHcKZqa4X1jWqLz1los5Hex92T3xcMXrjuyysbjh6T8FldQi8bLdh4s TYyv5KBWDWE05UU2xHjFcLLMPGUkAMddYpzkapnabKgbeiV5moN/q8xL466iRPg2Lb6s gCdnewzw1qbwJCO0O/saP882a/byHLEodrgPTnVasWf00L4lyBviN5HO+DOaydTdJoAl jGkoZX2YjRkhePyJ97u+RVr3dxvkntebb8ZH/fkZY9b0b/+dk9sLvtGf3fQ2jdfGnjtZ tvrg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703775488; x=1704380288; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jUHrNC1tkpzPW6esQt7nSVr+fIDnxVFl7BlqrAA/roI=; b=SzIEXbyV0fqMRhf2YsfdKGLAiuhfGtc1hRwwhDsLCQ7Sv8jeRS5peYBvAYx0zQUZfP LDScRZ2eWBzL8KBL9MQJRLYtAs1hkhMfzubM8YicX7XMCUBEeg7oUxnG7F10aDXn50t9 XbBTZhq9/EWhHbQG3tQVN4hHguXSQm0fxdVJGL0/NR2oc+BfSo3OJ6t1TmuMGA6AZoSj MKr47UyIK2pQqib39xmszErBOfNtLjZ+aJF8aHDpXYpdm05uTopo4LSN2q1YBuUxLteE yWwkUTUGZmFfGKQukw7FXxQSe1Ka5+itZq0RtnLg16LduRNMaqFMTKgDBTO6tfvKLH9t lchg== X-Gm-Message-State: AOJu0YxMyyaNnlaV4jQhGQn9/nM3sDIQCJeKxKKm1LjZBAIB24xaHCQG 7G1g/RkEbxpFBYaYAXtwt8STIi1hxwI= X-Google-Smtp-Source: AGHT+IE+1Q21VRQG1SU4fBWrNI/9VDHY+XLtW6F1XWRW2cciOp+osnPPdcXN+7Ua8/MZSrV2VK1few== X-Received: by 2002:a05:6871:878b:b0:204:4219:160a with SMTP id td11-20020a056871878b00b002044219160amr12102974oab.50.1703775488125; Thu, 28 Dec 2023 06:58:08 -0800 (PST) Received: from gnu-cfl-3.localdomain ([172.56.169.119]) by smtp.gmail.com with ESMTPSA id u10-20020a63140a000000b005c6e8fa9f24sm13069762pgl.49.2023.12.28.06.58.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Dec 2023 06:58:06 -0800 (PST) Received: from gnu-cfl-3.. (localhost [IPv6:::1]) by gnu-cfl-3.localdomain (Postfix) with ESMTP id D2BCC74065F for ; Thu, 28 Dec 2023 06:58:04 -0800 (PST) From: "H.J. Lu" To: binutils@sourceware.org Subject: [PATCH 3/4] x86-64: Add R_X86_64_CODE_4_GOTTPOFF/R_X86_64_CODE_4_GOTPC32_TLSDESC Date: Thu, 28 Dec 2023 06:58:03 -0800 Message-ID: <20231228145804.658337-4-hjl.tools@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231228145804.658337-1-hjl.tools@gmail.com> References: <20231228145804.658337-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3024.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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 For add name@gottpoff(%rip), %reg mov name@gottpoff(%rip), %reg add # define R_X86_64_CODE_4_GOTTPOFF 44 and for lea name@tlsdesc(%rip), %reg add # define R_X86_64_CODE_4_GOTPC32_TLSDESC 45 if the instruction starts at 4 bytes before the relocation offset. They are similar to R_X86_64_GOTTPOFF and R_X86_64_GOTPC32_TLSDESC, respectively. Linker can covert GOTTPOFF to add $name@tpoff, %reg mov $name@tpoff, %reg and GOTPC32_TLSDESC to mov $name@tpoff, %reg mov name@gottpoff(%rip), %reg if the instruction is encoded with the REX2 prefix when possible. bfd/ * elf64-x86-64.c (x86_64_elf_howto_table): Add R_X86_64_CODE_4_GOTTPOFF and R_X86_64_CODE_4_GOTPC32_TLSDESC. (R_X86_64_standard): Updated. (x86_64_reloc_map): Add BFD_RELOC_X86_64_CODE_4_GOTTPOFF and BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC. (elf_x86_64_check_tls_transition): Handle R_X86_64_CODE_4_GOTTPOFF and R_X86_64_CODE_4_GOTPC32_TLSDESC. (elf_x86_64_tls_transition): Likewise. (elf_x86_64_scan_relocs): Likewise. (elf_x86_64_relocate_section): Likewise. * reloc.c (bfd_reloc_code_real): Add BFD_RELOC_X86_64_CODE_4_GOTTPOFF and BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC. * bfd-in2.h: Regenerated. * libbfd.h: Likewise. gas/ * config/tc-i386.c (tc_i386_fix_adjustable): Handle BFD_RELOC_X86_64_CODE_4_GOTTPOFF and BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC. (md_assemble): Handle BFD_RELOC_X86_64_CODE_4_GOTTPOFF. (output_insn): Don't add empty REX prefix with REX2 prefix. (output_disp): Handle BFD_RELOC_X86_64_CODE_4_GOTTPOFF and BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC. (md_apply_fix): Likewise. (i386_validate_fix): Generate BFD_RELOC_X86_64_CODE_4_GOTTPOFF or BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC if ixp->fx_tcbit3 is set. (tc_gen_reloc): Handle BFD_RELOC_X86_64_CODE_4_GOTTPOFF and BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC. * testsuite/gas/i386/x86-64-gottpoff.d: New file. * testsuite/gas/i386/x86-64-gottpoff.s: Likewise. * testsuite/gas/i386/x86-64-tlsdesc.d: Likewise. * testsuite/gas/i386/x86-64-tlsdesc.s: Likewise. include/ * elf/x86-64.h (elf_x86_64_reloc_type): Add R_X86_64_CODE_4_GOTTPOFF and R_X86_64_CODE_4_GOTPC32_TLSDESC ld/ * testsuite/ld-x86-64/tlsbindesc.d: Updated. * testsuite/ld-x86-64/tlsbindesc.rd: Likewise. * testsuite/ld-x86-64/tlsbindesc.s: Add R_X86_64_CODE_4_GOTTPOFF and R_X86_64_CODE_4_GOTPC32_TLSDESC tests. --- bfd/bfd-in2.h | 2 + bfd/elf64-x86-64.c | 125 ++++++++++++++++++++++- bfd/libbfd.h | 2 + bfd/reloc.c | 4 + gas/config/tc-i386.c | 20 ++++ gas/testsuite/gas/i386/x86-64-gottpoff.d | 19 ++++ gas/testsuite/gas/i386/x86-64-gottpoff.s | 15 +++ gas/testsuite/gas/i386/x86-64-tlsdesc.d | 17 +++ gas/testsuite/gas/i386/x86-64-tlsdesc.s | 13 +++ gas/testsuite/gas/i386/x86-64.exp | 3 + include/elf/x86-64.h | 6 ++ ld/testsuite/ld-x86-64/tlsbindesc.dd | 49 +++++++++ ld/testsuite/ld-x86-64/tlsbindesc.rd | 36 +++---- ld/testsuite/ld-x86-64/tlsbindesc.s | 39 +++++++ 14 files changed, 329 insertions(+), 21 deletions(-) create mode 100644 gas/testsuite/gas/i386/x86-64-gottpoff.d create mode 100644 gas/testsuite/gas/i386/x86-64-gottpoff.s create mode 100644 gas/testsuite/gas/i386/x86-64-tlsdesc.d create mode 100644 gas/testsuite/gas/i386/x86-64-tlsdesc.s diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 96709da9170..550704ae89f 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -3892,6 +3892,8 @@ enum bfd_reloc_code_real BFD_RELOC_X86_64_GOTPCRELX, BFD_RELOC_X86_64_REX_GOTPCRELX, BFD_RELOC_X86_64_CODE_4_GOTPCRELX, + BFD_RELOC_X86_64_CODE_4_GOTTPOFF, + BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC, /* ns32k relocations. */ BFD_RELOC_NS32K_IMM_8, diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index a2d1b6f14b7..3406bc86ec1 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -173,12 +173,18 @@ static reloc_howto_type x86_64_elf_howto_table[] = HOWTO(R_X86_64_CODE_4_GOTPCRELX, 0, 4, 32, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_X86_64_CODE_4_GOTPCRELX", false, 0, 0xffffffff, true), + HOWTO(R_X86_64_CODE_4_GOTTPOFF, 0, 4, 32, true, 0, complain_overflow_signed, + bfd_elf_generic_reloc, "R_X86_64_CODE_4_GOTTPOFF", false, 0, 0xffffffff, + true), + HOWTO(R_X86_64_CODE_4_GOTPC32_TLSDESC, 0, 4, 32, true, 0, + complain_overflow_bitfield, bfd_elf_generic_reloc, + "R_X86_64_CODE_4_GOTPC32_TLSDESC", false, 0, 0xffffffff, true), /* We have a gap in the reloc numbers here. R_X86_64_standard counts the number up to this point, and R_X86_64_vt_offset is the value to subtract from a reloc type of R_X86_64_GNU_VT* to form an index into this table. */ -#define R_X86_64_standard (R_X86_64_CODE_4_GOTPCRELX + 1) +#define R_X86_64_standard (R_X86_64_CODE_4_GOTPC32_TLSDESC + 1) #define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard) /* GNU extension to record C++ vtable hierarchy. */ @@ -248,6 +254,8 @@ static const struct elf_reloc_map x86_64_reloc_map[] = { BFD_RELOC_X86_64_GOTPCRELX, R_X86_64_GOTPCRELX, }, { BFD_RELOC_X86_64_REX_GOTPCRELX, R_X86_64_REX_GOTPCRELX, }, { BFD_RELOC_X86_64_CODE_4_GOTPCRELX, R_X86_64_CODE_4_GOTPCRELX, }, + { BFD_RELOC_X86_64_CODE_4_GOTTPOFF, R_X86_64_CODE_4_GOTTPOFF, }, + { BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC, R_X86_64_CODE_4_GOTPC32_TLSDESC, }, { BFD_RELOC_VTABLE_INHERIT, R_X86_64_GNU_VTINHERIT, }, { BFD_RELOC_VTABLE_ENTRY, R_X86_64_GNU_VTENTRY, }, }; @@ -1262,6 +1270,19 @@ elf_x86_64_check_tls_transition (bfd *abfd, return (r_type == R_X86_64_PC32 || r_type == R_X86_64_PLT32); } + case R_X86_64_CODE_4_GOTTPOFF: + /* Check transition from IE access model: + mov foo@gottpoff(%rip), %reg + add foo@gottpoff(%rip), %reg + where reg is one of r16 to r31. */ + + if (offset < 4 + || (offset + 4) > sec->size + || contents[offset - 4] != 0xd5) + return false; + + goto check_gottpoff; + case R_X86_64_GOTTPOFF: /* Check transition from IE access model: mov foo@gottpoff(%rip), %reg @@ -1288,6 +1309,7 @@ elf_x86_64_check_tls_transition (bfd *abfd, return false; } + check_gottpoff: val = bfd_get_8 (abfd, contents + offset - 2); if (val != 0x8b && val != 0x03) return false; @@ -1295,6 +1317,18 @@ elf_x86_64_check_tls_transition (bfd *abfd, val = bfd_get_8 (abfd, contents + offset - 1); return (val & 0xc7) == 5; + case R_X86_64_CODE_4_GOTPC32_TLSDESC: + /* Check transition from GDesc access model: + lea x@tlsdesc(%rip), %reg + where reg is one of r16 to r31. */ + + if (offset < 4 + || (offset + 4) > sec->size + || contents[offset - 4] != 0xd5) + return false; + + goto check_tlsdesc; + case R_X86_64_GOTPC32_TLSDESC: /* Check transition from GDesc access model: leaq x@tlsdesc(%rip), %rax <--- LP64 mode. @@ -1312,6 +1346,7 @@ elf_x86_64_check_tls_transition (bfd *abfd, if (val != 0x48 && (ABI_64_P (abfd) || val != 0x40)) return false; + check_tlsdesc: if (bfd_get_8 (abfd, contents + offset - 2) != 0x8d) return false; @@ -1378,8 +1413,10 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, { case R_X86_64_TLSGD: case R_X86_64_GOTPC32_TLSDESC: + case R_X86_64_CODE_4_GOTPC32_TLSDESC: case R_X86_64_TLSDESC_CALL: case R_X86_64_GOTTPOFF: + case R_X86_64_CODE_4_GOTTPOFF: if (bfd_link_executable (info)) { if (h == NULL) @@ -1399,6 +1436,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, if (to_type == R_X86_64_TLSGD || to_type == R_X86_64_GOTPC32_TLSDESC + || to_type == R_X86_64_CODE_4_GOTPC32_TLSDESC || to_type == R_X86_64_TLSDESC_CALL) { if (tls_type == GOT_TLS_IE) @@ -1424,7 +1462,9 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, } /* Return TRUE if there is no transition. */ - if (from_type == to_type) + if (from_type == to_type + || (from_type == R_X86_64_CODE_4_GOTTPOFF + && to_type == R_X86_64_GOTTPOFF)) return true; /* Check if the transition can be performed. */ @@ -2132,6 +2172,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, break; case R_X86_64_GOTTPOFF: + case R_X86_64_CODE_4_GOTTPOFF: if (!bfd_link_executable (info)) info->flags |= DF_STATIC_TLS; /* Fall through */ @@ -2146,6 +2187,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, case R_X86_64_GOTPCREL64: case R_X86_64_GOTPLT64: case R_X86_64_GOTPC32_TLSDESC: + case R_X86_64_CODE_4_GOTPC32_TLSDESC: case R_X86_64_TLSDESC_CALL: /* This symbol requires a global offset table entry. */ { @@ -2167,9 +2209,11 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, tls_type = GOT_TLS_GD; break; case R_X86_64_GOTTPOFF: + case R_X86_64_CODE_4_GOTTPOFF: tls_type = GOT_TLS_IE; break; case R_X86_64_GOTPC32_TLSDESC: + case R_X86_64_CODE_4_GOTPC32_TLSDESC: case R_X86_64_TLSDESC_CALL: tls_type = GOT_TLS_GDESC; break; @@ -3518,8 +3562,10 @@ elf_x86_64_relocate_section (bfd *output_bfd, case R_X86_64_TLSGD: case R_X86_64_GOTPC32_TLSDESC: + case R_X86_64_CODE_4_GOTPC32_TLSDESC: case R_X86_64_TLSDESC_CALL: case R_X86_64_GOTTPOFF: + case R_X86_64_CODE_4_GOTTPOFF: tls_type = GOT_UNKNOWN; if (h == NULL && local_got_offsets) tls_type = elf_x86_local_got_tls_type (input_bfd) [r_symndx]; @@ -3660,6 +3706,37 @@ elf_x86_64_relocate_section (bfd *output_bfd, contents + roff); continue; } + else if (r_type == R_X86_64_CODE_4_GOTPC32_TLSDESC) + { + /* GDesc -> LE transition. + It's originally something like: + lea x@tlsdesc(%rip), %reg + + Change it to: + mov $x@tpoff, %reg + where reg is one of r16 to r31. */ + + unsigned int val, rex2; + unsigned int rex2_mask = REX_R | REX_R << 4; + + if (roff < 4) + goto corrupt_input; + rex2 = bfd_get_8 (input_bfd, contents + roff - 3); + val = bfd_get_8 (input_bfd, contents + roff - 1); + /* Move the R bits to the B bits in REX2 payload + byte. */ + bfd_put_8 (output_bfd, + ((rex2 & ~rex2_mask) + | (rex2 & rex2_mask) >> 2), + contents + roff - 3); + bfd_put_8 (output_bfd, 0xc7, contents + roff - 2); + bfd_put_8 (output_bfd, 0xc0 | ((val >> 3) & 7), + contents + roff - 1); + bfd_put_32 (output_bfd, + elf_x86_64_tpoff (info, relocation), + contents + roff); + continue; + } else if (r_type == R_X86_64_TLSDESC_CALL) { /* GDesc -> LE transition. @@ -3799,6 +3876,46 @@ elf_x86_64_relocate_section (bfd *output_bfd, contents + roff); continue; } + else if (r_type == R_X86_64_CODE_4_GOTTPOFF) + { + /* IE->LE transition: + Originally it can be one of: + mov foo@gottpoff(%rip), %reg + add foo@gottpoff(%rip), %reg + We change it into: + mov $foo@tpoff, %reg + add $foo@tpoff, %reg + where reg is one of r16 to r31. */ + + unsigned int rex2, type, reg; + unsigned int rex2_mask = REX_R | REX_R << 4; + + if (roff < 4) + goto corrupt_input; + + rex2 = bfd_get_8 (input_bfd, contents + roff - 3); + type = bfd_get_8 (input_bfd, contents + roff - 2); + reg = bfd_get_8 (input_bfd, contents + roff - 1); + reg >>= 3; + /* Move the R bits to the B bits in REX2 payload + byte. */ + if (type == 0x8b) + type = 0xc7; + else + type = 0x81; + bfd_put_8 (output_bfd, + ((rex2 & ~rex2_mask) + | (rex2 & rex2_mask) >> 2), + contents + roff - 3); + bfd_put_8 (output_bfd, type, + contents + roff - 2); + bfd_put_8 (output_bfd, 0xc0 | reg, + contents + roff - 1); + bfd_put_32 (output_bfd, + elf_x86_64_tpoff (info, relocation), + contents + roff); + continue; + } else BFD_ASSERT (false); } @@ -3905,6 +4022,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, if (r_type_tls == r_type) { if (r_type == R_X86_64_GOTPC32_TLSDESC + || r_type == R_X86_64_CODE_4_GOTPC32_TLSDESC || r_type == R_X86_64_TLSDESC_CALL) relocation = htab->elf.sgotplt->output_section->vma + htab->elf.sgotplt->output_offset @@ -4000,7 +4118,8 @@ elf_x86_64_relocate_section (bfd *output_bfd, wrel++; continue; } - else if (r_type == R_X86_64_GOTPC32_TLSDESC) + else if (r_type == R_X86_64_GOTPC32_TLSDESC + || r_type == R_X86_64_CODE_4_GOTPC32_TLSDESC) { /* GDesc -> IE transition. It's originally something like: diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 8873fafdde9..196e7e55ea6 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1461,6 +1461,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_X86_64_GOTPCRELX", "BFD_RELOC_X86_64_REX_GOTPCRELX", "BFD_RELOC_X86_64_CODE_4_GOTPCRELX", + "BFD_RELOC_X86_64_CODE_4_GOTTPOFF", + "BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC", "BFD_RELOC_NS32K_IMM_8", "BFD_RELOC_NS32K_IMM_16", "BFD_RELOC_NS32K_IMM_32", diff --git a/bfd/reloc.c b/bfd/reloc.c index 56d852d084f..30852b1422f 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2477,6 +2477,10 @@ ENUMX BFD_RELOC_X86_64_REX_GOTPCRELX ENUMX BFD_RELOC_X86_64_CODE_4_GOTPCRELX +ENUMX + BFD_RELOC_X86_64_CODE_4_GOTTPOFF +ENUMX + BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC ENUMDOC x86-64/elf relocations. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 8d76446010b..694c494edec 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -3601,10 +3601,12 @@ tc_i386_fix_adjustable (fixS *fixP) || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32 || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF64 || fixP->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF + || fixP->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTTPOFF || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32 || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF64 || fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64 || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC + || fixP->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC || fixP->fx_r_type == BFD_RELOC_X86_64_TLSDESC_CALL || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) @@ -5632,6 +5634,7 @@ md_assemble (char *line) case BFD_RELOC_386_TLS_GOTIE: case BFD_RELOC_386_TLS_LE_32: case BFD_RELOC_X86_64_GOTTPOFF: + case BFD_RELOC_X86_64_CODE_4_GOTTPOFF: case BFD_RELOC_X86_64_TLSLD: as_bad (_("TLS relocation cannot be used with `%s'"), insn_name (&i.tm)); return; @@ -10477,6 +10480,7 @@ output_insn (const struct last_insn *last_insn) is also needed for lea with R_X86_64_GOTPC32_TLSDESC relocation for GDesc -> IE/LE optimization. */ if (x86_elf_abi == X86_64_X32_ABI + && !is_apx_rex2_encoding () && i.operands == 2 && (i.reloc[0] == BFD_RELOC_X86_64_GOTTPOFF || i.reloc[0] == BFD_RELOC_X86_64_GOTPC32_TLSDESC) @@ -10842,7 +10846,9 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off) case BFD_RELOC_X86_64_TLSGD: case BFD_RELOC_X86_64_TLSLD: case BFD_RELOC_X86_64_GOTTPOFF: + case BFD_RELOC_X86_64_CODE_4_GOTTPOFF: case BFD_RELOC_X86_64_GOTPC32_TLSDESC: + case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC: case BFD_RELOC_X86_64_TLSDESC_CALL: i.has_gotpc_tls_reloc = true; default: @@ -14356,7 +14362,9 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_X86_64_TLSGD: case BFD_RELOC_X86_64_TLSLD: case BFD_RELOC_X86_64_GOTTPOFF: + case BFD_RELOC_X86_64_CODE_4_GOTTPOFF: case BFD_RELOC_X86_64_GOTPC32_TLSDESC: + case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC: value = 0; /* Fully resolved at runtime. No addend. */ /* Fallthrough */ case BFD_RELOC_386_TLS_LE: @@ -15929,6 +15937,14 @@ i386_validate_fix (fixS *fixp) return IS_ELF && fixp->fx_addsy && (!S_IS_DEFINED (fixp->fx_addsy) || S_IS_EXTERNAL (fixp->fx_addsy)); + + if (fixp->fx_tcbit3) + { + if (fixp->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF) + fixp->fx_r_type = BFD_RELOC_X86_64_CODE_4_GOTTPOFF; + else if (fixp->fx_r_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC) + fixp->fx_r_type = BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC; + } #endif if (fixp->fx_subsy) @@ -16073,6 +16089,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) case BFD_RELOC_X86_64_DTPOFF32: case BFD_RELOC_X86_64_DTPOFF64: case BFD_RELOC_X86_64_GOTTPOFF: + case BFD_RELOC_X86_64_CODE_4_GOTTPOFF: case BFD_RELOC_X86_64_TPOFF32: case BFD_RELOC_X86_64_TPOFF64: case BFD_RELOC_X86_64_GOTOFF64: @@ -16083,6 +16100,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) case BFD_RELOC_X86_64_GOTPLT64: case BFD_RELOC_X86_64_PLTOFF64: case BFD_RELOC_X86_64_GOTPC32_TLSDESC: + case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC: case BFD_RELOC_X86_64_TLSDESC_CALL: case BFD_RELOC_RVA: case BFD_RELOC_VTABLE_ENTRY: @@ -16215,7 +16233,9 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) case BFD_RELOC_X86_64_TLSGD: case BFD_RELOC_X86_64_TLSLD: case BFD_RELOC_X86_64_GOTTPOFF: + case BFD_RELOC_X86_64_CODE_4_GOTTPOFF: case BFD_RELOC_X86_64_GOTPC32_TLSDESC: + case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC: case BFD_RELOC_X86_64_TLSDESC_CALL: rel->addend = fixp->fx_offset - fixp->fx_size; break; diff --git a/gas/testsuite/gas/i386/x86-64-gottpoff.d b/gas/testsuite/gas/i386/x86-64-gottpoff.d new file mode 100644 index 00000000000..d42abccc6d9 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-gottpoff.d @@ -0,0 +1,19 @@ +#as: +#objdump: -dwr +#name: x86-64 gottpoff + +.*: +file format .* + + +Disassembly of section .text: + +0+ <_start>: + +[a-f0-9]+: 48 03 05 00 00 00 00 add 0x0\(%rip\),%rax # 7 <_start\+0x7> 3: R_X86_64_GOTTPOFF foo-0x4 + +[a-f0-9]+: 48 8b 05 00 00 00 00 mov 0x0\(%rip\),%rax # e <_start\+0xe> a: R_X86_64_GOTTPOFF foo-0x4 + +[a-f0-9]+: d5 48 03 05 00 00 00 00 add 0x0\(%rip\),%r16 # 16 <_start\+0x16> 12: R_X86_64_CODE_4_GOTTPOFF foo-0x4 + +[a-f0-9]+: d5 48 8b 25 00 00 00 00 mov 0x0\(%rip\),%r20 # 1e <_start\+0x1e> 1a: R_X86_64_CODE_4_GOTTPOFF foo-0x4 + +[a-f0-9]+: 48 03 05 00 00 00 00 add 0x0\(%rip\),%rax # 25 <_start\+0x25> 21: R_X86_64_GOTTPOFF foo-0x4 + +[a-f0-9]+: 48 8b 05 00 00 00 00 mov 0x0\(%rip\),%rax # 2c <_start\+0x2c> 28: R_X86_64_GOTTPOFF foo-0x4 + +[a-f0-9]+: d5 48 03 05 00 00 00 00 add 0x0\(%rip\),%r16 # 34 <_start\+0x34> 30: R_X86_64_CODE_4_GOTTPOFF foo-0x4 + +[a-f0-9]+: d5 48 8b 25 00 00 00 00 mov 0x0\(%rip\),%r20 # 3c <_start\+0x3c> 38: R_X86_64_CODE_4_GOTTPOFF foo-0x4 +#pass diff --git a/gas/testsuite/gas/i386/x86-64-gottpoff.s b/gas/testsuite/gas/i386/x86-64-gottpoff.s new file mode 100644 index 00000000000..6f8f9d1480c --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-gottpoff.s @@ -0,0 +1,15 @@ + .text +_start: + addq foo@GOTTPOFF(%rip), %rax + movq foo@GOTTPOFF(%rip), %rax + + addq foo@GOTTPOFF(%rip), %r16 + movq foo@GOTTPOFF(%rip), %r20 + + .intel_syntax noprefix + + addq rax, QWORD PTR [rip + foo@GOTTPOFF] + movq rax, QWORD PTR [rip + foo@GOTTPOFF] + + addq r16, QWORD PTR [rip + foo@GOTTPOFF] + movq r20, QWORD PTR [rip + foo@GOTTPOFF] diff --git a/gas/testsuite/gas/i386/x86-64-tlsdesc.d b/gas/testsuite/gas/i386/x86-64-tlsdesc.d new file mode 100644 index 00000000000..50c04e1e6b9 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-tlsdesc.d @@ -0,0 +1,17 @@ +#as: +#objdump: -dwr +#name: x86-64 tlsdesc + +.*: +file format .* + + +Disassembly of section .text: + +0+ <_start>: + +[a-f0-9]+: 48 8d 05 00 00 00 00 lea 0x0\(%rip\),%rax # 7 <_start\+0x7> 3: R_X86_64_GOTPC32_TLSDESC foo-0x4 + +[a-f0-9]+: d5 48 8d 05 00 00 00 00 lea 0x0\(%rip\),%r16 # f <_start\+0xf> b: R_X86_64_CODE_4_GOTPC32_TLSDESC foo-0x4 + +[a-f0-9]+: d5 48 8d 25 00 00 00 00 lea 0x0\(%rip\),%r20 # 17 <_start\+0x17> 13: R_X86_64_CODE_4_GOTPC32_TLSDESC foo-0x4 + +[a-f0-9]+: 48 8d 05 00 00 00 00 lea 0x0\(%rip\),%rax # 1e <_start\+0x1e> 1a: R_X86_64_GOTPC32_TLSDESC foo-0x4 + +[a-f0-9]+: d5 48 8d 05 00 00 00 00 lea 0x0\(%rip\),%r16 # 26 <_start\+0x26> 22: R_X86_64_CODE_4_GOTPC32_TLSDESC foo-0x4 + +[a-f0-9]+: d5 48 8d 25 00 00 00 00 lea 0x0\(%rip\),%r20 # 2e <_start\+0x2e> 2a: R_X86_64_CODE_4_GOTPC32_TLSDESC foo-0x4 +#pass diff --git a/gas/testsuite/gas/i386/x86-64-tlsdesc.s b/gas/testsuite/gas/i386/x86-64-tlsdesc.s new file mode 100644 index 00000000000..91f8d23dca4 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-tlsdesc.s @@ -0,0 +1,13 @@ + .text +_start: + leaq foo@TLSDESC(%rip), %rax + + leaq foo@TLSDESC(%rip), %r16 + leaq foo@TLSDESC(%rip), %r20 + + .intel_syntax noprefix + + leaq rax, QWORD PTR [rip + foo@TLSDESC] + + leaq r16, QWORD PTR [rip + foo@TLSDESC] + leaq r20, QWORD PTR [rip + foo@TLSDESC] diff --git a/gas/testsuite/gas/i386/x86-64.exp b/gas/testsuite/gas/i386/x86-64.exp index fa6a1c3c945..cd28846ca8f 100644 --- a/gas/testsuite/gas/i386/x86-64.exp +++ b/gas/testsuite/gas/i386/x86-64.exp @@ -665,6 +665,9 @@ if [is_elf_format] then { run_dump_test "x86-64-gotpcrel-no-relax" run_dump_test "x86-64-gotpcrel-2" + run_dump_test "x86-64-gottpoff" + run_dump_test "x86-64-tlsdesc" + run_dump_test "x86-64-no-got" run_dump_test "x86-64-addend" diff --git a/include/elf/x86-64.h b/include/elf/x86-64.h index 30d1722cb73..bbcf190532e 100644 --- a/include/elf/x86-64.h +++ b/include/elf/x86-64.h @@ -86,6 +86,12 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_type) instruction starts at 4 bytes before the relocation offset, relaxable. */ RELOC_NUMBER (R_X86_64_CODE_4_GOTPCRELX, 43) + /* PC relative offset to IE GOT entry if the instruction starts at + 4 bytes before the relocation offset. */ + RELOC_NUMBER (R_X86_64_CODE_4_GOTTPOFF, 44) + /* 32 bit signed pc relative offset to TLS descriptor in the GOT if + instruction starts at 4 bytes before the relocation offset. */ + RELOC_NUMBER (R_X86_64_CODE_4_GOTPC32_TLSDESC, 45) RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250) /* GNU C++ hack */ RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251) /* GNU C++ hack */ END_RELOC_NUMBERS (R_X86_64_max) diff --git a/ld/testsuite/ld-x86-64/tlsbindesc.dd b/ld/testsuite/ld-x86-64/tlsbindesc.dd index 5bdb659555f..4587cc751b4 100644 --- a/ld/testsuite/ld-x86-64/tlsbindesc.dd +++ b/ld/testsuite/ld-x86-64/tlsbindesc.dd @@ -165,6 +165,55 @@ Disassembly of section .text: +[0-9a-f]+: 90[ ]+nop * +[0-9a-f]+: c9[ ]+leave * +[0-9a-f]+: c3[ ]+ret * +# IE against global var + +[0-9a-f]+: d5 48 03 05 ([0-9a-f]{2} ){3}[ ]+add 0x[0-9a-f]+\(%rip\),%r16 +# [0-9a-f]+ +# -> R_X86_64_TPOFF64 sG2 + +[0-9a-f]+: 00 * +# IE -> LE against global var defined in exec + +[0-9a-f]+: d5 18 81 c1 60 ff ff[ ]+add \$0xf+60,%r17 +# sg1 + +[0-9a-f]+: ff * +# IE -> LE against local var + +[0-9a-f]+: d5 18 81 c2 80 ff ff[ ]+add \$0xf+80,%r18 +# sl1 + +[0-9a-f]+: ff * +# IE -> LE against hidden var + +[0-9a-f]+: d5 18 81 c3 a0 ff ff[ ]+add \$0xf+a0,%r19 +# sh1 + +[0-9a-f]+: ff * +# Direct access through %fs +# IE against global var + +[0-9a-f]+: d5 48 8b 25 ([0-9a-f]{2} ){3}[ ]+mov 0x[0-9a-f]+\(%rip\),%r20 +# [0-9a-f]+ +# -> R_X86_64_TPOFF64 sG5 + +[0-9a-f]+: 00 * +# IE->LE against local var + +[0-9a-f]+: d5 18 c7 c5 90 ff ff[ ]+mov \$0xf+90,%r21 +# sl5 + +[0-9a-f]+: ff * +# IE->LE against hidden var + +[0-9a-f]+: d5 18 c7 c6 b0 ff ff[ ]+mov \$0xf+b0,%r22 + +[0-9a-f]+: ff * +# GD -> IE because variable is not defined in executable + +[0-9a-f]+: d5 48 8b 05 ([0-9a-f]{2} ){3}[ ]+mov 0x[0-9a-f]+\(%rip\),%r16 +# [0-9a-f]+ +# -> R_X86_64_TPOFF64 sG1 + +[0-9a-f]+: 00 * +# GD -> IE because variable is not defined in executable where +# the variable is referenced through IE too + +[0-9a-f]+: d5 48 8b 0d ([0-9a-f]{2} ){3}[ ]+mov 0x[0-9a-f]+\(%rip\),%r17 +# [0-9a-f]+ +# -> R_X86_64_TPOFF64 sG2 + +[0-9a-f]+: 00 * +# GD -> LE with global variable defined in executable + +[0-9a-f]+: d5 18 c7 c2 60 ff ff[ ]+mov \$0xf+60,%r18 +# sg1 + +[0-9a-f]+: ff * +# GD -> LE with local variable defined in executable + +[0-9a-f]+: d5 18 c7 c3 80 ff ff[ ]+mov \$0xf+80,%r19 +# sl1 + +[0-9a-f]+: ff * +# GD -> LE with hidden variable defined in executable + +[0-9a-f]+: d5 18 c7 c4 a0 ff ff[ ]+mov \$0xf+a0,%r20 +# sh1 + +[0-9a-f]+: ff * [0-9a-f]+ <_start>: +[0-9a-f]+: 55[ ]+push %rbp diff --git a/ld/testsuite/ld-x86-64/tlsbindesc.rd b/ld/testsuite/ld-x86-64/tlsbindesc.rd index 682c4a066a2..daaea7a5371 100644 --- a/ld/testsuite/ld-x86-64/tlsbindesc.rd +++ b/ld/testsuite/ld-x86-64/tlsbindesc.rd @@ -15,12 +15,12 @@ Section Headers: +\[[ 0-9]+\] .dynsym +.* +\[[ 0-9]+\] .dynstr +.* +\[[ 0-9]+\] .rela.dyn +.* - +\[[ 0-9]+\] .text +PROGBITS +0+401000 0+1000 0+1fd 00 +AX +0 +0 +4096 - +\[[ 0-9]+\] .tdata +PROGBITS +0+6011fd 0+11fd 0+60 00 WAT +0 +0 +1 - +\[[ 0-9]+\] .tbss +NOBITS +0+60125d 0+125d 0+40 00 WAT +0 +0 +1 - +\[[ 0-9]+\] .dynamic +DYNAMIC +0+601260 0+1260 0+100 10 +WA +4 +0 +8 - +\[[ 0-9]+\] .got +PROGBITS +0+601360 0+1360 0+20 08 +WA +0 +0 +8 - +\[[ 0-9]+\] .got.plt +PROGBITS +0+601380 0+1380 0+18 08 +WA +0 +0 +8 + +\[[ 0-9]+\] .text +PROGBITS +0+401000 0+1000 0+25d 00 +AX +0 +0 +4096 + +\[[ 0-9]+\] .tdata +PROGBITS +0+60125d 0+125d 0+60 00 WAT +0 +0 +1 + +\[[ 0-9]+\] .tbss +NOBITS +0+6012bd 0+12bd 0+40 00 WAT +0 +0 +1 + +\[[ 0-9]+\] .dynamic +DYNAMIC +0+6012c0 0+12c0 0+100 10 +WA +4 +0 +8 + +\[[ 0-9]+\] .got +PROGBITS +0+6013c0 0+13c0 0+20 08 +WA +0 +0 +8 + +\[[ 0-9]+\] .got.plt +PROGBITS +0+6013e0 0+13e0 0+18 08 +WA +0 +0 +8 +\[[ 0-9]+\] .symtab +.* +\[[ 0-9]+\] .strtab +.* +\[[ 0-9]+\] .shstrtab +.* @@ -28,7 +28,7 @@ Key to Flags: #... Elf file type is EXEC \(Executable file\) -Entry point 0x401105 +Entry point 0x401165 There are [0-9]+ program headers, starting at offset [0-9]+ Program Headers: @@ -36,10 +36,10 @@ Program Headers: +PHDR.* +INTERP.* .*Requesting program interpreter.* - +LOAD +0x0+ 0x0+400000 0x0+400000 0x0+11fd 0x0+11fd R E 0x200000 - +LOAD +0x0+11fd 0x0+6011fd 0x0+6011fd 0x0+19b 0x0+19b RW +0x200000 - +DYNAMIC +0x0+1260 0x0+601260 0x0+601260 0x0+100 0x0+100 RW +0x8 - +TLS +0x0+11fd 0x0+6011fd 0x0+6011fd 0x0+60 0x0+a0 R +0x1 + +LOAD +0x0+ 0x0+400000 0x0+400000 0x0+125d 0x0+125d R E 0x200000 + +LOAD +0x0+125d 0x0+60125d 0x0+60125d 0x0+19b 0x0+19b RW +0x200000 + +DYNAMIC +0x0+12c0 0x0+6012c0 0x0+6012c0 0x0+100 0x0+100 RW +0x8 + +TLS +0x0+125d 0x0+60125d 0x0+60125d 0x0+60 0x0+a0 R +0x1 Section to Segment mapping: +Segment Sections... @@ -52,10 +52,10 @@ Program Headers: Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 4 entries: +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend -0+601360 +0+100000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0 -0+601368 +0+200000012 R_X86_64_TPOFF64 +0+ sG2 \+ 0 -0+601370 +0+300000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0 -0+601378 +0+400000012 R_X86_64_TPOFF64 +0+ sG1 \+ 0 +0+6013c0 +0+100000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0 +0+6013c8 +0+200000012 R_X86_64_TPOFF64 +0+ sG2 \+ 0 +0+6013d0 +0+300000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0 +0+6013d8 +0+400000012 R_X86_64_TPOFF64 +0+ sG1 \+ 0 Symbol table '\.dynsym' contains [0-9]+ entries: +Num: +Value +Size +Type +Bind +Vis +Ndx +Name @@ -88,8 +88,8 @@ Symbol table '\.symtab' contains [0-9]+ entries: +[0-9]+: 0+9c +0 +TLS +LOCAL +DEFAULT +8 bl8 .* FILE +LOCAL +DEFAULT +ABS +[0-9]+: 0+a0 +0 +TLS +LOCAL +DEFAULT +7 _TLS_MODULE_BASE_ - +[0-9]+: 0+601260 +0 +OBJECT +LOCAL +DEFAULT +9 _DYNAMIC - +[0-9]+: 0+601380 +0 +OBJECT +LOCAL +DEFAULT +11 _GLOBAL_OFFSET_TABLE_ + +[0-9]+: 0+6012c0 +0 +OBJECT +LOCAL +DEFAULT +9 _DYNAMIC + +[0-9]+: 0+6013e0 +0 +OBJECT +LOCAL +DEFAULT +11 _GLOBAL_OFFSET_TABLE_ +[0-9]+: 0+1c +0 +TLS +GLOBAL +DEFAULT +7 sg8 +[0-9]+: 0+7c +0 +TLS +GLOBAL +DEFAULT +8 bg8 +[0-9]+: 0+74 +0 +TLS +GLOBAL +DEFAULT +8 bg6 @@ -104,7 +104,7 @@ Symbol table '\.symtab' contains [0-9]+ entries: +[0-9]+: 0+58 +0 +TLS +GLOBAL +HIDDEN +7 sh7 +[0-9]+: 0+5c +0 +TLS +GLOBAL +HIDDEN +7 sh8 +[0-9]+: 0+ +0 +TLS +GLOBAL +DEFAULT +7 sg1 - +[0-9]+: 0+401105 +0 +FUNC +GLOBAL +DEFAULT +6 _start + +[0-9]+: 0+401165 +0 +FUNC +GLOBAL +DEFAULT +6 _start +[0-9]+: 0+4c +0 +TLS +GLOBAL +HIDDEN +7 sh4 +[0-9]+: 0+78 +0 +TLS +GLOBAL +DEFAULT +8 bg7 +[0-9]+: 0+50 +0 +TLS +GLOBAL +HIDDEN +7 sh5 diff --git a/ld/testsuite/ld-x86-64/tlsbindesc.s b/ld/testsuite/ld-x86-64/tlsbindesc.s index cbebf02171d..b80e5f192c0 100644 --- a/ld/testsuite/ld-x86-64/tlsbindesc.s +++ b/ld/testsuite/ld-x86-64/tlsbindesc.s @@ -126,3 +126,42 @@ fn2: leave ret + + /* IE against global var */ + addq sG2@gottpoff(%rip), %r16 + + /* IE -> LE against global var defined in exec */ + addq sg1@gottpoff(%rip), %r17 + + /* IE -> LE against local var */ + addq sl1@gottpoff(%rip), %r18 + + /* IE -> LE against hidden var */ + addq sh1@gottpoff(%rip), %r19 + + /* Direct access through %fs */ + + /* IE against global var */ + movq sG5@gottpoff(%rip), %r20 + + /* IE->LE against local var */ + movq sl5@gottpoff(%rip), %r21 + + /* IE->LE against hidden var */ + movq sh5@gottpoff(%rip), %r22 + + /* GD -> IE because variable is not defined in executable */ + leaq sG1@tlsdesc(%rip), %r16 + + /* GD -> IE because variable is not defined in executable where + the variable is referenced through IE too */ + leaq sG2@tlsdesc(%rip), %r17 + + /* GD -> LE with global variable defined in executable */ + leaq sg1@tlsdesc(%rip), %r18 + + /* GD -> LE with local variable defined in executable */ + leaq sl1@tlsdesc(%rip), %r19 + + /* GD -> LE with hidden variable defined in executable */ + leaq sh1@tlsdesc(%rip), %r20 From patchwork Thu Dec 28 14:58:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 82923 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 DC82A3861865 for ; Thu, 28 Dec 2023 15:01:48 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-oi1-x231.google.com (mail-oi1-x231.google.com [IPv6:2607:f8b0:4864:20::231]) by sourceware.org (Postfix) with ESMTPS id 2E098385828F for ; Thu, 28 Dec 2023 14:58:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2E098385828F Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 2E098385828F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::231 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1703775493; cv=none; b=P0dI2DsvYRBS+eYDxxQjL+zwDswhDv1+6hTK68nNrvflTBmoaw8wJiMHK7AEdWKTLDAaYiOzeuR6l9+PYUNPFVCDOBTV6k6kuHNiRhDZK/c8WDunqmT5OgOiWv0MIL7OziRCrnyOtQ7oMBZAcW0w0xntGV0FE9dg/Avy7DEQdiw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1703775493; c=relaxed/simple; bh=ECty1+gef8U3TJPKeJABh0P0hAe3976sXXw7Q+aIROg=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=KTKqWKkiAx2p9kkQwfDSbvZ3d9PLO+wDR+NdJYGuXwEQS53ReC7F8ebHuESL67sPH1bCw87Uq+pj/mfHlr6FuDbm6PjfKi3L7pIcIWQBkHhE4fODPXTBBn6sXQ/gRxz3J1Y+6KeZvmUHXpawhbBMLvLnVAvU5GeytnGciU+7vZU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-oi1-x231.google.com with SMTP id 5614622812f47-3bb53e20a43so4934723b6e.1 for ; Thu, 28 Dec 2023 06:58:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1703775488; x=1704380288; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=LZVtKwxNsQ7MRUffYnm3W35uWz9UJELuSzJ7HRmHj2c=; b=Js2efk+fvOnVrInbqtHbfcW9BZlykBZxgpgPQJzLE0B/kCKidto+uumqctL3/dySVu L9HpYs3bX19Fc6fPz8URSwrlAnrIZPmv1688X6NIZiGSmg1dlvEJiL6U6kfsQwUcGfdJ AgNvJTQVMkdKbCsUfXvzZWPg/AGcY5AXF774UzFheD25Occf7A2MUHk9XjtmX93zRUCN xVqOqc+suDRXJ7MpbsNjXPXXSKl3UbeGFKGtixOx59KuIfYuQR3r6Oa1zaP7WZ3P9n+G gk5/0gu4HZA3VJ4fMyCeobajcsWLELUQtcI3Zhe5lFPqfWtuggonbW1Tuwdac2FKxyVQ yBmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703775488; x=1704380288; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LZVtKwxNsQ7MRUffYnm3W35uWz9UJELuSzJ7HRmHj2c=; b=ZwSZlf2T/qXeUirLOpLePH75tKRo37+C2+pmpTX5dOwFP9rsxxxy7uQQNTqj/F9ilb NGHkWY4OVACn9hmKm2DG/tkrqw/y5gTya0njTaU1NEGS6AvNRM21htOia04s3JUZwmGc Cd9+68WakTO4j/SP+3f52qR0IAZxRLqLXkJ8qjWOxHc8cx3R/711AEZ1ieOJW+tHcZE/ IItKWziQaLGl3FFnQCS0VZP4IAr14qlor+5BQ4uBcBpiE9iJSp1kKu//vcRsQOF2wg7Y VcH063GsGiU1aGFsZKyNQ1Iw9iHxwn1uP7ZgwB6dgZfvbOy7QL0mphH44j2aahUgSLqG Rb5g== X-Gm-Message-State: AOJu0Yy/xfjZ3DVqAnWPgh+gCvJpg9QhomBEfc/MOsDQGAodOeakkiPo AbPVtLWhZYcZSQxeiaoyHczvnm/K46g= X-Google-Smtp-Source: AGHT+IGHX9yS21eVRpVFv+13Ze8ljx/RXprPh1xZqKmIMLp8+AQo5JHAHwhYkVSwQebcs+7DANdD+Q== X-Received: by 2002:a05:6358:3a1b:b0:172:c06c:fce3 with SMTP id g27-20020a0563583a1b00b00172c06cfce3mr5837862rwe.58.1703775487814; Thu, 28 Dec 2023 06:58:07 -0800 (PST) Received: from gnu-cfl-3.localdomain ([172.56.169.119]) by smtp.gmail.com with ESMTPSA id t20-20020a056a0021d400b006da28981d63sm1195998pfj.55.2023.12.28.06.58.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Dec 2023 06:58:06 -0800 (PST) Received: from gnu-cfl-3.. (localhost [IPv6:::1]) by gnu-cfl-3.localdomain (Postfix) with ESMTP id DF0C6740660 for ; Thu, 28 Dec 2023 06:58:04 -0800 (PST) From: "H.J. Lu" To: binutils@sourceware.org Subject: [PATCH 4/4] Gold: Handle R_X86_64_CODE_4_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTTPOFF Date: Thu, 28 Dec 2023 06:58:04 -0800 Message-ID: <20231228145804.658337-5-hjl.tools@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20231228145804.658337-1-hjl.tools@gmail.com> References: <20231228145804.658337-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3024.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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 Handle R_X86_64_CODE_4_GOTTPOFF and R_X86_64_CODE_4_GOTPC32_TLSDESC. Convert add name@gottpoff(%rip), %reg mov name@gottpoff(%rip), %reg to add $name@tpoff, %reg mov $name@tpoff, %reg and lea name@tlsdesc(%rip), %reg to mov $name@tpoff, %reg mov name@gottpoff(%rip), %reg if the instruction is encoded with the REX2 prefix when possible. elfcpp/ * x86_64.h (R_X86_64_CODE_4_GOTTPOFF): New. (R_X86_64_CODE_4_GOTPC32_TLSDESC): Likewise. gold/ * x86_64.cc (Target_x86_64::optimize_tls_reloc): Handle R_X86_64_CODE_4_GOTPC32_TLSDESC and R_X86_64_CODE_4_GOTTPOFF. (Target_x86_64::Scan::get_reference_flags): Likewise. (Target_x86_64::Scan::local): Likewise. (Target_x86_64::Scan::global): Likewise. (Target_x86_64::Relocate::relocate): Likewise. (Target_x86_64::Relocate::relocate_tls): Likewise. (Target_x86_64::Relocate::tls_desc_gd_to_ie): Handle R_X86_64_CODE_4_GOTPC32_TLSDESC. (Target_x86_64::Relocate::tls_desc_gd_to_le): Likewise. (Target_x86_64::Relocate::tls_ie_to_le): Handle. R_X86_64_CODE_4_GOTTPOFF. * testsuite/Makefile.am: Add x86_64_ie_to_le test. * testsuite/Makefile.in: Regenerated. * testsuite/x86_64_gd_to_le.s: Add R_X86_64_CODE_4_GOTPC32_TLSDESC test. * testsuite/x86_64_gd_to_le.sh: Check GDesc to LE conversion. * testsuite/x86_64_ie_to_le.s: New file. * testsuite/x86_64_ie_to_le.sh: Likewise. --- elfcpp/x86_64.h | 8 ++ gold/testsuite/Makefile.am | 11 +++ gold/testsuite/Makefile.in | 17 ++++ gold/testsuite/x86_64_gd_to_le.s | 1 + gold/testsuite/x86_64_gd_to_le.sh | 1 + gold/testsuite/x86_64_ie_to_le.s | 17 ++++ gold/testsuite/x86_64_ie_to_le.sh | 29 ++++++ gold/x86_64.cc | 156 +++++++++++++++++++++++------- 8 files changed, 203 insertions(+), 37 deletions(-) create mode 100644 gold/testsuite/x86_64_ie_to_le.s create mode 100755 gold/testsuite/x86_64_ie_to_le.sh diff --git a/elfcpp/x86_64.h b/elfcpp/x86_64.h index 97a87ae424d..da6ac191734 100644 --- a/elfcpp/x86_64.h +++ b/elfcpp/x86_64.h @@ -102,6 +102,14 @@ enum // GOT if the instruction starts at 4 // bytes before the relocation offset, // relaxable. + R_X86_64_CODE_4_GOTTPOFF = 44, // 32 bit signed PC relative offset to + // GOT entry for IE symbol if the + // instruction starts at 4 bytes before + // the relocation offset. + R_X86_64_CODE_4_GOTPC32_TLSDESC = 45, // 32-bit PC relative to TLS + // descriptor in GOT if the + // instruction starts at 4 bytes + // before the relocation offset. // GNU vtable garbage collection extensions. R_X86_64_GNU_VTINHERIT = 250, R_X86_64_GNU_VTENTRY = 251 diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index df9405c1aac..0685e917d0e 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -1244,6 +1244,17 @@ x86_64_gd_to_le: x86_64_gd_to_le.o gcctestdir/ld x86_64_gd_to_le.stdout: x86_64_gd_to_le $(TEST_OBJDUMP) -dw $< > $@ +check_SCRIPTS += x86_64_ie_to_le.sh +check_DATA += x86_64_ie_to_le.stdout +MOSTLYCLEANFILES += x86_64_ie_to_le + +x86_64_ie_to_le.o: x86_64_ie_to_le.s + $(TEST_AS) --64 -o $@ $< +x86_64_ie_to_le: x86_64_ie_to_le.o gcctestdir/ld + gcctestdir/ld -o $@ $< +x86_64_ie_to_le.stdout: x86_64_ie_to_le + $(TEST_OBJDUMP) -dw $< > $@ + check_SCRIPTS += x86_64_overflow_pc32.sh check_DATA += x86_64_overflow_pc32.err MOSTLYCLEANFILES += x86_64_overflow_pc32.err diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index ab48f07bca4..ffd4821b875 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -296,6 +296,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_31 = x86_64_mov_to_lea.sh \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_indirect_call_to_direct.sh \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_gd_to_le.sh \ +@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_ie_to_le.sh \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_overflow_pc32.sh \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x32_overflow_pc32.sh \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ pr23016_1.sh \ @@ -319,6 +320,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_indirect_call_to_direct1.stdout \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_indirect_jump_to_direct1.stdout \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_gd_to_le.stdout \ +@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_ie_to_le.stdout \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_overflow_pc32.err \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x32_overflow_pc32.err \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ pr23016_1.stdout \ @@ -343,6 +345,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_indirect_call_to_direct1 \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_indirect_jump_to_direct1 \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_gd_to_le \ +@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_ie_to_le \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_overflow_pc32.err \ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x32_overflow_pc32.err @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_34 = pr17704a_test @@ -5747,6 +5750,13 @@ x86_64_gd_to_le.sh.log: x86_64_gd_to_le.sh --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +x86_64_ie_to_le.sh.log: x86_64_ie_to_le.sh + @p='x86_64_ie_to_le.sh'; \ + b='x86_64_ie_to_le.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) x86_64_overflow_pc32.sh.log: x86_64_overflow_pc32.sh @p='x86_64_overflow_pc32.sh'; \ b='x86_64_overflow_pc32.sh'; \ @@ -8485,6 +8495,13 @@ uninstall-am: @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -o $@ $< @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@x86_64_gd_to_le.stdout: x86_64_gd_to_le @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_OBJDUMP) -dw $< > $@ + +@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@x86_64_ie_to_le.o: x86_64_ie_to_le.s +@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AS) --64 -o $@ $< +@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@x86_64_ie_to_le: x86_64_ie_to_le.o gcctestdir/ld +@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -o $@ $< +@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@x86_64_ie_to_le.stdout: x86_64_ie_to_le +@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_OBJDUMP) -dw $< > $@ @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@x86_64_overflow_pc32.o: x86_64_overflow_pc32.s @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AS) -o $@ $< @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@x86_64_overflow_pc32.err: x86_64_overflow_pc32.o gcctestdir/ld diff --git a/gold/testsuite/x86_64_gd_to_le.s b/gold/testsuite/x86_64_gd_to_le.s index dcdd303184d..79f9c48f526 100644 --- a/gold/testsuite/x86_64_gd_to_le.s +++ b/gold/testsuite/x86_64_gd_to_le.s @@ -7,6 +7,7 @@ _start: subq $8, %rsp .cfi_def_cfa_offset 16 leaq foo@TLSDESC(%rip), %r9 + leaq foo@TLSDESC(%rip), %r29 movq %r9, %rax call *foo@TLSCALL(%rax) addq %fs:0, %rax diff --git a/gold/testsuite/x86_64_gd_to_le.sh b/gold/testsuite/x86_64_gd_to_le.sh index 82a6f985b88..5b0a043e0a8 100755 --- a/gold/testsuite/x86_64_gd_to_le.sh +++ b/gold/testsuite/x86_64_gd_to_le.sh @@ -24,3 +24,4 @@ set -e grep -q "mov[ \t]\+\$0x[a-f0-9]\+,%r9" x86_64_gd_to_le.stdout +grep -q "mov[ \t]\+\$0x[a-f0-9]\+,%r29" x86_64_gd_to_le.stdout diff --git a/gold/testsuite/x86_64_ie_to_le.s b/gold/testsuite/x86_64_ie_to_le.s new file mode 100644 index 00000000000..c5752068866 --- /dev/null +++ b/gold/testsuite/x86_64_ie_to_le.s @@ -0,0 +1,17 @@ + .text + .p2align 4 + .globl _start + .type _start, @function +_start: + addq foo@gottpoff(%rip), %r12 + movq foo@gottpoff(%rip), %rax + addq foo@gottpoff(%rip), %r16 + movq foo@gottpoff(%rip), %r20 + .size _start, .-_start + .section .tdata,"awT",@progbits + .align 4 + .type foo, @object + .size foo, 4 +foo: + .long 30 + .section .note.GNU-stack,"",@progbits diff --git a/gold/testsuite/x86_64_ie_to_le.sh b/gold/testsuite/x86_64_ie_to_le.sh new file mode 100755 index 00000000000..417f0bfc636 --- /dev/null +++ b/gold/testsuite/x86_64_ie_to_le.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +# x86_64_ie_to_le.sh -- a test for IE -> LE conversion. + +# Copyright (C) 2023 Free Software Foundation, Inc. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +set -e + +grep -q "add[ \t]\+\$0x[a-f0-9]\+,%r12" x86_64_ie_to_le.stdout +grep -q "mov[ \t]\+\$0x[a-f0-9]\+,%rax" x86_64_ie_to_le.stdout +grep -q "add[ \t]\+\$0x[a-f0-9]\+,%r16" x86_64_ie_to_le.stdout +grep -q "mov[ \t]\+\$0x[a-f0-9]\+,%r20" x86_64_ie_to_le.stdout diff --git a/gold/x86_64.cc b/gold/x86_64.cc index b7be9bf0d48..bc4260db5f3 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -1110,7 +1110,8 @@ class Target_x86_64 : public Sized_target // Adjust TLS relocation type based on the options and whether this // is a local symbol. static tls::Tls_optimization - optimize_tls_reloc(bool is_final, int r_type); + optimize_tls_reloc(bool is_final, int r_type, size_t r_offset, + const unsigned char* reloc_view); // Get the GOT section, creating it if necessary. Output_data_got<64, false>* @@ -2878,11 +2879,13 @@ Target_x86_64::got_mod_index_entry(Symbol_table* symtab, Layout* layout, // Optimize the TLS relocation type based on what we know about the // symbol. IS_FINAL is true if the final address of this symbol is -// known at link time. +// known at link time. RELOC_VIEW points to the relocation offset. template tls::Tls_optimization -Target_x86_64::optimize_tls_reloc(bool is_final, int r_type) +Target_x86_64::optimize_tls_reloc(bool is_final, int r_type, + size_t r_offset, + const unsigned char* reloc_view) { // If we are generating a shared library, then we can't do anything // in the linker. @@ -2891,6 +2894,10 @@ Target_x86_64::optimize_tls_reloc(bool is_final, int r_type) switch (r_type) { + case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC: + if (r_offset <= 4 || *(reloc_view - 4) != 0xd5) + return tls::TLSOPT_NONE; + // Fall through. case elfcpp::R_X86_64_TLSGD: case elfcpp::R_X86_64_GOTPC32_TLSDESC: case elfcpp::R_X86_64_TLSDESC_CALL: @@ -2913,6 +2920,10 @@ Target_x86_64::optimize_tls_reloc(bool is_final, int r_type) // Another Local-Dynamic reloc. return tls::TLSOPT_TO_LE; + case elfcpp::R_X86_64_CODE_4_GOTTPOFF: + if (r_offset <= 4 || *(reloc_view - 4) != 0xd5) + return tls::TLSOPT_NONE; + // Fall through. case elfcpp::R_X86_64_GOTTPOFF: // These are Initial-Exec relocs which get the thread offset // from the GOT. If we know that we are linking against the @@ -2979,11 +2990,13 @@ Target_x86_64::Scan::get_reference_flags(unsigned int r_type) case elfcpp::R_X86_64_TLSGD: // Global-dynamic case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url) + case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC: case elfcpp::R_X86_64_TLSDESC_CALL: case elfcpp::R_X86_64_TLSLD: // Local-dynamic case elfcpp::R_X86_64_DTPOFF32: case elfcpp::R_X86_64_DTPOFF64: case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec + case elfcpp::R_X86_64_CODE_4_GOTTPOFF: case elfcpp::R_X86_64_TPOFF32: // Local-exec return Symbol::TLS_REF; @@ -3148,6 +3161,8 @@ Target_x86_64::Scan::local(Symbol_table* symtab, target->make_local_ifunc_plt_entry(symtab, layout, object, r_sym); } + const unsigned char* reloc_view = NULL; + switch (r_type) { case elfcpp::R_X86_64_NONE: @@ -3345,6 +3360,13 @@ need_got: break; // These are initial tls relocs, which are expected when linking + case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC: + case elfcpp::R_X86_64_CODE_4_GOTTPOFF: + { + section_size_type stype; + reloc_view = object->section_contents(data_shndx, &stype, true); + } + // Fall through. case elfcpp::R_X86_64_TLSGD: // Global-dynamic case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url) case elfcpp::R_X86_64_TLSDESC_CALL: @@ -3355,9 +3377,11 @@ need_got: case elfcpp::R_X86_64_TPOFF32: // Local-exec { bool output_is_shared = parameters->options().shared(); + size_t r_offset = reloc.get_r_offset(); const tls::Tls_optimization optimized_type = Target_x86_64::optimize_tls_reloc(!output_is_shared, - r_type); + r_type, r_offset, + reloc_view + r_offset); switch (r_type) { case elfcpp::R_X86_64_TLSGD: // General-dynamic @@ -3386,6 +3410,7 @@ need_got: break; case elfcpp::R_X86_64_GOTPC32_TLSDESC: + case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC: target->define_tls_base_symbol(symtab, layout); if (optimized_type == tls::TLSOPT_NONE) { @@ -3438,6 +3463,7 @@ need_got: break; case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec + case elfcpp::R_X86_64_CODE_4_GOTTPOFF: layout->set_has_static_tls(); if (optimized_type == tls::TLSOPT_NONE) { @@ -3615,6 +3641,8 @@ Target_x86_64::Scan::global(Symbol_table* symtab, && this->reloc_needs_plt_for_ifunc(object, r_type)) target->make_plt_entry(symtab, layout, gsym); + const unsigned char *reloc_view = NULL; + switch (r_type) { case elfcpp::R_X86_64_NONE: @@ -3872,6 +3900,13 @@ Target_x86_64::Scan::global(Symbol_table* symtab, break; // These are initial tls relocs, which are expected for global() + case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC: + case elfcpp::R_X86_64_CODE_4_GOTTPOFF: + { + section_size_type stype; + reloc_view = object->section_contents(data_shndx, &stype, true); + } + // Fall through. case elfcpp::R_X86_64_TLSGD: // Global-dynamic case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url) case elfcpp::R_X86_64_TLSDESC_CALL: @@ -3884,11 +3919,15 @@ Target_x86_64::Scan::global(Symbol_table* symtab, // For the Initial-Exec model, we can treat undef symbols as final // when building an executable. const bool is_final = (gsym->final_value_is_known() || - (r_type == elfcpp::R_X86_64_GOTTPOFF && + ((r_type == elfcpp::R_X86_64_GOTTPOFF || + r_type == elfcpp::R_X86_64_CODE_4_GOTTPOFF) && gsym->is_undefined() && parameters->options().output_is_executable())); + size_t r_offset = reloc.get_r_offset(); const tls::Tls_optimization optimized_type - = Target_x86_64::optimize_tls_reloc(is_final, r_type); + = Target_x86_64::optimize_tls_reloc(is_final, r_type, + r_offset, + reloc_view + r_offset); switch (r_type) { case elfcpp::R_X86_64_TLSGD: // General-dynamic @@ -3917,6 +3956,7 @@ Target_x86_64::Scan::global(Symbol_table* symtab, break; case elfcpp::R_X86_64_GOTPC32_TLSDESC: + case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC: target->define_tls_base_symbol(symtab, layout); if (optimized_type == tls::TLSOPT_NONE) { @@ -3965,6 +4005,7 @@ Target_x86_64::Scan::global(Symbol_table* symtab, break; case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec + case elfcpp::R_X86_64_CODE_4_GOTTPOFF: layout->set_has_static_tls(); if (optimized_type == tls::TLSOPT_NONE) { @@ -4560,11 +4601,13 @@ Target_x86_64::Relocate::relocate( // These are initial tls relocs, which are expected when linking case elfcpp::R_X86_64_TLSGD: // Global-dynamic case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url) + case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC: case elfcpp::R_X86_64_TLSDESC_CALL: case elfcpp::R_X86_64_TLSLD: // Local-dynamic case elfcpp::R_X86_64_DTPOFF32: case elfcpp::R_X86_64_DTPOFF64: case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec + case elfcpp::R_X86_64_CODE_4_GOTTPOFF: case elfcpp::R_X86_64_TPOFF32: // Local-exec this->relocate_tls(relinfo, target, relnum, rela, r_type, gsym, psymval, view, address, view_size); @@ -4636,8 +4679,10 @@ Target_x86_64::Relocate::relocate_tls( const bool is_final = (gsym == NULL ? !parameters->options().shared() : gsym->final_value_is_known()); + size_t r_offset = rela.get_r_offset(); tls::Tls_optimization optimized_type - = Target_x86_64::optimize_tls_reloc(is_final, r_type); + = Target_x86_64::optimize_tls_reloc(is_final, r_type, + r_offset, view); switch (r_type) { case elfcpp::R_X86_64_TLSGD: // Global-dynamic @@ -4704,6 +4749,7 @@ Target_x86_64::Relocate::relocate_tls( break; case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url) + case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC: case elfcpp::R_X86_64_TLSDESC_CALL: if (!is_executable && optimized_type == tls::TLSOPT_TO_LE) { @@ -4729,7 +4775,8 @@ Target_x86_64::Relocate::relocate_tls( ? GOT_TYPE_TLS_OFFSET : GOT_TYPE_TLS_DESC); unsigned int got_offset = 0; - if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC + if ((r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC + || r_type == elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC) && optimized_type == tls::TLSOPT_NONE) { // We created GOT entries in the .got.tlsdesc portion of @@ -4760,7 +4807,8 @@ Target_x86_64::Relocate::relocate_tls( } else if (optimized_type == tls::TLSOPT_NONE) { - if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC) + if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC + || r_type == elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC) { // Relocate the field with the offset of the pair of GOT // entries. @@ -4845,6 +4893,7 @@ Target_x86_64::Relocate::relocate_tls( break; case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec + case elfcpp::R_X86_64_CODE_4_GOTTPOFF: if (gsym != NULL && gsym->is_undefined() && parameters->options().output_is_executable()) @@ -5051,7 +5100,8 @@ Target_x86_64::Relocate::tls_desc_gd_to_ie( typename elfcpp::Elf_types::Elf_Addr address, section_size_type view_size) { - if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC) + if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC + || r_type == elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC) { // LP64: leaq foo@tlsdesc(%rip), %rax // ==> movq foo@gottpoff(%rip), %rax @@ -5060,7 +5110,8 @@ Target_x86_64::Relocate::tls_desc_gd_to_ie( tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3); tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4); tls::check_tls(relinfo, relnum, rela.get_r_offset(), - (((view[-3] & 0xfb) == 0x48 + ((r_type == elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC + || (view[-3] & 0xfb) == 0x48 || (size == 32 && (view[-3] & 0xfb) == 0x40)) && view[-2] == 0x8d && (view[-1] & 0xc7) == 0x05)); @@ -5132,6 +5183,22 @@ Target_x86_64::Relocate::tls_desc_gd_to_le( value -= tls_segment->memsz(); Relocate_functions::rela32(view, value, 0); } + else if (r_type == elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC) + { + // REX2: lea foo@tlsdesc(%rip), %reg + // ==> mov foo@tpoff, %reg + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3); + tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4); + tls::check_tls(relinfo, relnum, rela.get_r_offset(), + (view[-2] == 0x8d + && (view[-1] & 0xc7) == 0x05)); + unsigned char rex2_mask = 4 | 4 << 4; + view[-3] = (view[-3] & ~rex2_mask) | ((view[-3] & rex2_mask) >> 2); + view[-2] = 0xc7; + view[-1] = 0xc0 | ((view[-1] >> 3) & 7); + value -= tls_segment->memsz(); + Relocate_functions::rela32(view, value, 0); + } else { // LP64: call *foo@tlscall(%rax) @@ -5231,7 +5298,7 @@ Target_x86_64::Relocate::tls_ie_to_le( size_t relnum, Output_segment* tls_segment, const elfcpp::Rela& rela, - unsigned int, + unsigned int r_type, typename elfcpp::Elf_types::Elf_Addr value, unsigned char* view, section_size_type view_size) @@ -5250,35 +5317,50 @@ Target_x86_64::Relocate::tls_ie_to_le( unsigned char op3 = view[-1]; unsigned char reg = op3 >> 3; - if (op2 == 0x8b) + if (r_type == elfcpp::R_X86_64_GOTTPOFF) { - // movq - if (op1 == 0x4c) - view[-3] = 0x49; - else if (size == 32 && op1 == 0x44) - view[-3] = 0x41; - view[-2] = 0xc7; - view[-1] = 0xc0 | reg; - } - else if (reg == 4) - { - // Special handling for %rsp. - if (op1 == 0x4c) - view[-3] = 0x49; - else if (size == 32 && op1 == 0x44) - view[-3] = 0x41; - view[-2] = 0x81; - view[-1] = 0xc0 | reg; + if (op2 == 0x8b) + { + // movq + if (op1 == 0x4c) + view[-3] = 0x49; + else if (size == 32 && op1 == 0x44) + view[-3] = 0x41; + view[-2] = 0xc7; + view[-1] = 0xc0 | reg; + } + else if (reg == 4) + { + // Special handling for %rsp. + if (op1 == 0x4c) + view[-3] = 0x49; + else if (size == 32 && op1 == 0x44) + view[-3] = 0x41; + view[-2] = 0x81; + view[-1] = 0xc0 | reg; + } + else + { + // addq + if (op1 == 0x4c) + view[-3] = 0x4d; + else if (size == 32 && op1 == 0x44) + view[-3] = 0x45; + view[-2] = 0x8d; + view[-1] = 0x80 | reg | (reg << 3); + } } else { - // addq - if (op1 == 0x4c) - view[-3] = 0x4d; - else if (size == 32 && op1 == 0x44) - view[-3] = 0x45; - view[-2] = 0x8d; - view[-1] = 0x80 | reg | (reg << 3); + if (op2 == 0x8b) + op2 = 0xc7; + else + op2 = 0x81; + + unsigned char rex2_mask = 4 | 4 << 4; + view[-3] = (view[-3] & ~rex2_mask) | ((view[-3] & rex2_mask) >> 2); + view[-2] = op2; + view[-1] = 0xc0 | reg; } if (tls_segment != NULL)