From patchwork Mon Jan 8 08:47:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: mengqinggang X-Patchwork-Id: 185845 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:37c1:b0:101:2151:f287 with SMTP id y1csp898243dyq; Mon, 8 Jan 2024 00:47:28 -0800 (PST) X-Google-Smtp-Source: AGHT+IFfYKJnBm2ufADZLdLwXfBQmdB9c4Co5OHKKVGnpSm0NORD+rcy9F4Po55NvmrRFEWnz738 X-Received: by 2002:ad4:4e2a:0:b0:680:fa9f:93c5 with SMTP id dm10-20020ad44e2a000000b00680fa9f93c5mr1610463qvb.39.1704703648261; Mon, 08 Jan 2024 00:47:28 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1704703648; cv=pass; d=google.com; s=arc-20160816; b=ywLCw2hcc+9FrpGQ2zDp2d2S3CSykuybSZqiGHkc9gNIGWpUMq8ufof5iA9LyXSh3f O17LNzb2gXTqqNZkJWKwmqbP+xM0hB/XTe9KF94LNflwXMt6grVg8VE4feK4bWzrH4LI vr2JsUgsMmUxFchmtAbKMMty67UbmjsXQ2KopbsPCZ0I2z33O2ja+AJmVhJ6QtKJpdBv MXg9hgSAwadmFzZxLIUS7Ro2KPRO0E2xRRiRQkIIjVKGhuarHANICNsQJ+4y1lP0z+GN zelvXJDjAXrry3JgCJMXAZy1Ckors7ahDpWHvMuO4AGuwSK4sGVSJyuUg7uU00RTnqia QGeA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:arc-filter :dmarc-filter:delivered-to; bh=djwIba++A57AyzUzdH3asrII7FqGzJv13SmttN7ERPo=; fh=IjBrBzj0HafC7UFRTZLmdEImc4JDKXFiCrZAu8bdkFw=; b=NwH+xWAY3X6w/Z4djg3ifazGDbfLjptusa0hE7SMV7JIvo+XgyxiMR4Ixd6LXnt+ku +aLKfwyEbusIZElIeDlYFUByxyRoTDEU4SJIIZ3Zsjh59d2+FUKefCLwS79yVbipned+ 2CZT3cdr2czsd64t/CzF81B/L/8wGZxIU1FzQNAsjs5c6Vwk14buU4afIdz03ulfJOOv Hl+Ru8FwUkjCuurHLoANILxQLUMX57jsnoiR+VmpNC6uAZg83Z9aUl1ToU1W9oCD/x7z VsJIOIYq27zYPXX6zO3Il8pIZjq/nm0CtvnfshtPhxw0V1M8xZBiktjHzewQzjH8jJZZ +HOQ== ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1); spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org" Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id k12-20020a0cabcc000000b0067abb363a4bsi7342086qvb.231.2024.01.08.00.47.28 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jan 2024 00:47:28 -0800 (PST) Received-SPF: pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; arc=pass (i=1); spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org" Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EAF983858281 for ; Mon, 8 Jan 2024 08:47:27 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by sourceware.org (Postfix) with ESMTP id 05BFA3858D35 for ; Mon, 8 Jan 2024 08:47:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 05BFA3858D35 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=loongson.cn ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 05BFA3858D35 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1704703639; cv=none; b=WlpgrtCRMv8FPErEKI8zmiB5bnkU32x2vaXg5Uem65LUApQPnqI3aSTEkTB0e7sMmJKWnzgBC5rWoh1uyAiSOvIX9NhlDqePj9A7uGxSwg0SkltoGOVA0q9k+VQkzhdEn1hc//AYd8Uwb0iqzW1nky87OKfAzfW4l6fZov0wym0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1704703639; c=relaxed/simple; bh=ER8Vi56+LLtUk0P0psoEMI1JqlbAcO8ExlkZ2fx3law=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=nE1c6TtDxDmWddi9PeyucQuVFp/UzHltZxX1lvXABxuQE+SUGUpbNk9EBp51vrbhzGleKcDUu8bfhrGl437uAnPRZl3mB2hwbn4bvSoQDqA1qN8F6NXEYNoQuCCmtqU8r8kyhWx6/aybnLiP/VF9JfVs3E9pe9o6zJaAje4p1fY= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from loongson.cn (unknown [10.2.6.5]) by gateway (Coremail) with SMTP id _____8CxLOuOtptl1hIDAA--.10058S3; Mon, 08 Jan 2024 16:47:11 +0800 (CST) Received: from 5.5.5 (unknown [10.2.6.5]) by localhost.localdomain (Coremail) with SMTP id AQAAf8Cxid2OtptlLkEHAA--.18834S2; Mon, 08 Jan 2024 16:47:10 +0800 (CST) From: mengqinggang To: binutils@sourceware.org Cc: xuchenghua@loongson.cn, chenglulu@loongson.cn, liuzhensong@loongson.cn, cailulu@loongson.cn, xry111@xry111.site, i.swmail@xen0n.name, maskray@google.com, luweining@loongson.cn, wanglei@loongson.cn, hejinyang@loongson.cn, mengqinggang Subject: [PATCH] LoongArch: Fix relaxation overflow caused by section alignment Date: Mon, 8 Jan 2024 16:47:09 +0800 Message-Id: <20240108084709.558270-1-mengqinggang@loongson.cn> X-Mailer: git-send-email 2.39.3 MIME-Version: 1.0 X-CM-TRANSID: AQAAf8Cxid2OtptlLkEHAA--.18834S2 X-CM-SenderInfo: 5phqw15lqjwttqj6z05rqj20fqof0/ X-Coremail-Antispam: 1Uk129KBj93XoWxtw47KF15GryftFWrJFWDtrc_yoWfJFW3pF y3urZ5GF48ZF1DWwnFy3y8uF4Yq3yxGryfta43t34Ikr47XFyfXF40yry7WFWDGw18Cr12 vw18KayUZF1fAwcCm3ZEXasCq-sJn29KB7ZKAUJUUUUr529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUU9Fb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Gr0_Xr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr0_Cr1l84ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVCY1x0267AK xVW8Jr0_Cr1UM2kKe7AKxVWUXVWUAwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07 AIYIkI8VC2zVCFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWU XVWUAwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7V AKI48JMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMxCIbckI1I0E14v2 6r1Y6r17MI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17 CEb7AF67AKxVWUtVW8ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF 0xvE2Ix0cI8IcVCY1x0267AKxVWUJVW8JwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIx AIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2 KfnxnUUI43ZEXa7IU88Ma5UUUUU== X-Spam-Status: No, score=-12.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, 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+ouuuleilei=gmail.com@sourceware.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1787511332670906814 X-GMAIL-MSGID: 1787511332670906814 When deleting NOP instructions addend by .align at second pass, this may cause the PC decrease but the symbol address to remain unchanged due to section alignment. To solve this question, we subtract a maximux alignment of all sections like RISC-V. --- bfd/elfnn-loongarch.c | 79 +++++++++++++------ .../relax-section-align-overflow.s | 25 ++++++ ld/testsuite/ld-loongarch-elf/relax.exp | 26 ++++-- 3 files changed, 101 insertions(+), 29 deletions(-) create mode 100644 ld/testsuite/ld-loongarch-elf/relax-section-align-overflow.s diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index 0987628098e..7905cdf7564 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -4195,8 +4195,9 @@ loongarch_relax_tls_le (bfd *abfd, asection *sec, /* Relax pcalau12i,addi.d => pcaddi. */ static bool loongarch_relax_pcala_addi (bfd *abfd, asection *sec, asection *sym_sec, - Elf_Internal_Rela *rel_hi, bfd_vma symval, - struct bfd_link_info *info, bool *again) + Elf_Internal_Rela *rel_hi, bfd_vma symval, + struct bfd_link_info *info, bool *again, + bfd_vma max_alignment) { bfd_byte *contents = elf_section_data (sec)->this_hdr.contents; Elf_Internal_Rela *rel_lo = rel_hi + 2; @@ -4212,14 +4213,22 @@ loongarch_relax_pcala_addi (bfd *abfd, asection *sec, asection *sym_sec, bfd_vma pc = sec_addr (sec) + rel_hi->r_offset; /* If pc and symbol not in the same segment, add/sub segment alignment. - FIXME: if there are multiple readonly segments? */ + FIXME: if there are multiple readonly segments? How to determine if + two sections are in the same segment. */ if (!(sym_sec->flags & SEC_READONLY)) { + max_alignment = info->maxpagesize > max_alignment ? info->maxpagesize + : max_alignment; if (symval > pc) - pc -= info->maxpagesize; + pc -= max_alignment; else if (symval < pc) - pc += info->maxpagesize; + pc += max_alignment; } + else + if (symval > pc) + pc -= max_alignment; + else if (symval < pc) + pc += max_alignment; const uint32_t addi_d = 0x02c00000; const uint32_t pcaddi = 0x18000000; @@ -4359,8 +4368,9 @@ loongarch_relax_align (bfd *abfd, asection *sec, /* Relax pcalau12i + addi.d of TLS LD/GD/DESC to pcaddi. */ static bool loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec, - Elf_Internal_Rela *rel_hi, bfd_vma symval, - struct bfd_link_info *info, bool *again) + Elf_Internal_Rela *rel_hi, bfd_vma symval, + struct bfd_link_info *info, bool *again, + bfd_vma max_alignment) { bfd_byte *contents = elf_section_data (sec)->this_hdr.contents; Elf_Internal_Rela *rel_lo = rel_hi + 2; @@ -4379,11 +4389,18 @@ loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec, FIXME: if there are multiple readonly segments? */ if (!(sym_sec->flags & SEC_READONLY)) { + max_alignment = info->maxpagesize > max_alignment ? info->maxpagesize + : max_alignment; if (symval > pc) - pc -= info->maxpagesize; + pc -= max_alignment; else if (symval < pc) - pc += info->maxpagesize; + pc += max_alignment; } + else + if (symval > pc) + pc -= max_alignment; + else if (symval < pc) + pc += max_alignment; const uint32_t addi_d = 0x02c00000; const uint32_t pcaddi = 0x18000000; @@ -4435,6 +4452,21 @@ loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec, return true; } +/* Traverse all output sections and return the max alignment. */ + +static bfd_vma +loongarch_get_max_alignment (asection *sec) +{ + asection *o; + unsigned int max_alignment_power = 0; + + for (o = sec->output_section->owner->sections; o != NULL; o = o->next) + if (o->alignment_power > max_alignment_power) + max_alignment_power = o->alignment_power; + + return (bfd_vma) 1 << max_alignment_power; +} + static bool loongarch_elf_relax_section (bfd *abfd, asection *sec, struct bfd_link_info *info, @@ -4445,6 +4477,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd); Elf_Internal_Rela *relocs; *again = false; + bfd_vma max_alignment = 0; if (bfd_link_relocatable (info) || sec->sec_flg0 @@ -4477,6 +4510,15 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, data->relocs = relocs; + /* Estimate the maximum alignment for all output sections once time + should be enough. */ + max_alignment = htab->max_alignment; + if (max_alignment == (bfd_vma) -1) + { + max_alignment = loongarch_get_max_alignment (sec); + htab->max_alignment = max_alignment; + } + for (unsigned int i = 0; i < sec->reloc_count; i++) { char symtype; @@ -4613,6 +4655,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, if (1 == info->relax_pass) loongarch_relax_align (abfd, sec, sym_sec, info, rel, symval); break; + case R_LARCH_DELETE: if (1 == info->relax_pass) { @@ -4620,6 +4663,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE); } break; + case R_LARCH_TLS_LE_HI20_R: case R_LARCH_TLS_LE_LO12_R: case R_LARCH_TLS_LE_ADD_R: @@ -4630,34 +4674,25 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, case R_LARCH_PCALA_HI20: if (0 == info->relax_pass && (i + 4) <= sec->reloc_count) loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval, - info, again); + info, again, max_alignment); break; + case R_LARCH_GOT_PC_HI20: if (local_got && 0 == info->relax_pass && (i + 4) <= sec->reloc_count) { if (loongarch_relax_pcala_ld (abfd, sec, rel)) loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval, - info, again); + info, again, max_alignment); } break; case R_LARCH_TLS_LD_PC_HI20: - if (0 == info->relax_pass && (i + 4) <= sec->reloc_count) - loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval, - info, again); - break; - case R_LARCH_TLS_GD_PC_HI20: - if (0 == info->relax_pass && (i + 4) <= sec->reloc_count) - loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval, - info, again); - break; - case R_LARCH_TLS_DESC_PC_HI20: if (0 == info->relax_pass && (i + 4) <= sec->reloc_count) loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval, - info, again); + info, again, max_alignment); break; default: diff --git a/ld/testsuite/ld-loongarch-elf/relax-section-align-overflow.s b/ld/testsuite/ld-loongarch-elf/relax-section-align-overflow.s new file mode 100644 index 00000000000..c341a8bbfc0 --- /dev/null +++ b/ld/testsuite/ld-loongarch-elf/relax-section-align-overflow.s @@ -0,0 +1,25 @@ +# relocation overflow because .align +.text + addi.d $t0, $t1, 0 + addi.d $t0, $t1, 0 + # Add one NOP instruction + .align 3 + addi.d $t0, $t1, 0 + +.section ".t.a", "ax" + addi.d $t0, $t1, 0 + # In one try: + # first pass, la.local can be relaxed (0x120200010 - 0x120000014 = 0x1ffffc) + # second pass, the NOP addend by .align be deleted and pc decrease 4, + # but .L1 not decrease because section alignment. + # (0x120200010 - 0x120000010 = 0x200000) + la.local $t0, .L1 + .fill 0x1ffff0 + +.section ".t.b", "ax" +.L1: + addi.d $t0, $t1, 0 + # To make section address not change when first .align 3 delete NOP + .align 4 + addi.d $t0, $t1, 0 + diff --git a/ld/testsuite/ld-loongarch-elf/relax.exp b/ld/testsuite/ld-loongarch-elf/relax.exp index 548a0dbac91..a7c775889bc 100644 --- a/ld/testsuite/ld-loongarch-elf/relax.exp +++ b/ld/testsuite/ld-loongarch-elf/relax.exp @@ -164,14 +164,14 @@ if [istarget loongarch64-*-*] { ] } - if [file exist "tmpdir/relax-so"] { - set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax-so"] - if { [ regexp ".*pcaddi.*" $objdump_output] } { - pass "loongarch relax .so" - } { - fail "loongarch relax .so" - } + if [file exist "tmpdir/relax-so"] { + set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax-so"] + if { [ regexp ".*pcaddi.*" $objdump_output] } { + pass "loongarch relax .so" + } { + fail "loongarch relax .so" } + } # If symbol in data segment, offset need to sub segment align to prevent # overflow. @@ -201,6 +201,18 @@ if [istarget loongarch64-*-*] { ] } + run_ld_link_tests \ + [list \ + [list \ + "loongarch relax section align overflow" \ + "-e0 -Ttext 0x120000000" "" \ + "" \ + {relax-section-align-overflow.s} \ + {} \ + "relax-section-align-overflow" \ + ] \ + ] + if [file exist "tmpdir/relax-tls-le"] { set objdump_output1 [run_host_cmd "objdump" "-d tmpdir/relax-tls-le"] if { [ regexp ".addi.*st.*" $objdump_output1] } {