From patchwork Sat Oct 12 03:43:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: mengqinggang X-Patchwork-Id: 98783 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 E1E2D385AC37 for ; Sat, 12 Oct 2024 03:45:19 +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 46AEA385735B for ; Sat, 12 Oct 2024 03:44:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 46AEA385735B 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 46AEA385735B 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=1728704645; cv=none; b=mRO80L3JxOjcbyxKjzAcRq6Fpqp8xmt4mHf9fKFhCwclDCjPNY6qaBM2a/7KS2Vl5OU9W2gCl0ihjxKM12tIrSINPxw3Wbdhb9SvPitEGZrNBp8gdZs9F6vXqmofkC/DqAItLJ4qu9dbWV/dYaI7H03Po9fiQ7uuiThB5IPRpkc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1728704645; c=relaxed/simple; bh=hwUdWx4ougGfpuocE8a2FPUMdem4CNOJ5iVlC/0iKu0=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=XPW22BcXm8cqqZhmZtOkL8mzYbrJ2JJJNsN4tmVH/JmEBmikbBBkjJBxMmhM8DPE2IDXh/lFqrxUssJh4lDS77Fs6WgmjiAhnBlB/u7AsPFWLcv3BDsQ9GTKx2ztUHIz2jraBw4cuCOFOTqBnOEBSaEwpvJ7AfFmQYXG7Sw0iyw= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from loongson.cn (unknown [10.2.6.5]) by gateway (Coremail) with SMTP id _____8Bx22p_8AlnXXkUAA--.30246S3; Sat, 12 Oct 2024 11:43:59 +0800 (CST) Received: from 5.5.5 (unknown [10.2.6.5]) by front1 (Coremail) with SMTP id qMiowMDx_9d98AlnhqwkAA--.52119S3; Sat, 12 Oct 2024 11:43:59 +0800 (CST) From: mengqinggang To: binutils@sourceware.org Cc: xuchenghua@loongson.cn, chenglulu@loongson.cn, cailulu@loongson.cn, xry111@xry111.site, i.swmail@xen0n.name, maskray@google.com, luweining@loongson.cn, hejinyang@loongson.cn, mengqinggang@loongson.cn Subject: [PATCH 1/2] LoongArch: Optimize the relaxation process Date: Sat, 12 Oct 2024 11:43:55 +0800 Message-Id: <20241012034356.2957334-2-mengqinggang@loongson.cn> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20241012034356.2957334-1-mengqinggang@loongson.cn> References: <20241012034356.2957334-1-mengqinggang@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: qMiowMDx_9d98AlnhqwkAA--.52119S3 X-CM-SenderInfo: 5phqw15lqjwttqj6z05rqj20fqof0/ X-Coremail-Antispam: 1Uk129KBj9fXoW3tr1xXr1ruF45uF47KFWxuFX_yoW8Ww1kKo WrZFWrCr4xWFW2yrZrtwn8JFWfX34rGFWrCwnIvwn0vF40kr15W3yxJF15JrWfXwsrCrW7 CFy5Wa93JFy2gF1Dl-sFpf9Il3svdjkaLaAFLSUrUUUUUb8apTn2vfkv8UJUUUU8wcxFpf 9Il3svdxBIdaVrn0xqx4xG64xvF2IEw4CE5I8CrVC2j2Jv73VFW2AGmfu7bjvjm3AaLaJ3 UjIYCTnIWjp_UUUYb7kC6x804xWl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI 8IcIk0rVWrJVCq3wAFIxvE14AKwVWUGVWUXwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xG Y2AK021l84ACjcxK6xIIjxv20xvE14v26r1I6r4UM28EF7xvwVC0I7IYx2IY6xkF7I0E14 v26r1j6r4UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x0267AK xVW8Jr0_Cr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6xkI12xvs2x26I8E6xACxx 1l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r126r1DMcIj6I8E87Iv 67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41l42xK82IYc2 Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s02 6x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0x vE2Ix0cI8IcVAFwI0_JFI_Gr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r1j6r4UMIIF0xvE 42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87Iv6x kF7I0E14v26r1j6r4UYxBIdaVFxhVjvjDU0xZFpf9x07j1LvtUUUUU= X-Spam-Status: No, score=-12.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org The symbol value is only calculated when the relocation can be relaxed. --- bfd/elfnn-loongarch.c | 281 +++++++++++++++++++++--------------------- 1 file changed, 139 insertions(+), 142 deletions(-) diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index 63c6fdffd6b..d683fd32ff4 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -4073,7 +4073,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, /* For 2G jump, generate pcalau12i, jirl. */ /* If use jirl, turns to R_LARCH_B16. */ uint32_t insn = bfd_get (32, input_bfd, contents + rel->r_offset); - if (LARCH_INSN_JIRL(insn)) + if (LARCH_INSN_JIRL (insn)) { relocation &= 0xfff; /* Signed extend. */ @@ -4853,9 +4853,11 @@ loongarch_tls_perform_trans (bfd *abfd, asection *sec, */ static bool loongarch_relax_tls_le (bfd *abfd, asection *sec, - Elf_Internal_Rela *rel, + asection *sym_sec ATTRIBUTE_UNUSED, + Elf_Internal_Rela *rel, bfd_vma symval, struct bfd_link_info *link_info, - bfd_vma symval) + bool *agin ATTRIBUTE_UNUSED, + bfd_vma max_alignment ATTRIBUTE_UNUSED) { bfd_byte *contents = elf_section_data (sec)->this_hdr.contents; uint32_t insn = bfd_get (32, abfd, contents + rel->r_offset); @@ -4863,7 +4865,7 @@ loongarch_relax_tls_le (bfd *abfd, asection *sec, symval = symval - elf_hash_table (link_info)->tls_sec->vma; /* The old LE instruction sequence can be relaxed when the symbol offset is smaller than the 12-bit range. */ - if (ELFNN_R_TYPE ((rel + 1)->r_info) == R_LARCH_RELAX && (symval <= 0xfff)) + if (symval <= 0xfff) { switch (ELFNN_R_TYPE (rel->r_info)) { @@ -4976,9 +4978,6 @@ loongarch_relax_pcala_addi (bfd *abfd, asection *sec, asection *sym_sec, /* Is pcalau12i + addi.d insns? */ if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_PCALA_LO12) - || (ELFNN_R_TYPE ((rel_lo + 1)->r_info) != R_LARCH_RELAX) - || (ELFNN_R_TYPE ((rel_hi + 1)->r_info) != R_LARCH_RELAX) - || (rel_hi->r_offset + 4 != rel_lo->r_offset) || !LARCH_INSN_ADDI_D(add) /* Is pcalau12i $rd + addi.d $rd,$rd? */ || (LARCH_GET_RD(add) != rd) @@ -5036,10 +5035,8 @@ loongarch_relax_call36 (bfd *abfd, asection *sec, asection *sym_sec, else if (symval < pc) pc += (max_alignment > 4 ? max_alignment : 0); - /* Is pcalau12i + addi.d insns? */ - if ((ELFNN_R_TYPE ((rel + 1)->r_info) != R_LARCH_RELAX) - || !LARCH_INSN_JIRL(jirl) + if (!LARCH_INSN_JIRL (jirl) || ((bfd_signed_vma)(symval - pc) < (bfd_signed_vma)(int32_t)0xf8000000) || ((bfd_signed_vma)(symval - pc) > (bfd_signed_vma)(int32_t)0x7fffffc)) return false; @@ -5065,7 +5062,12 @@ loongarch_relax_call36 (bfd *abfd, asection *sec, asection *sym_sec, /* Relax pcalau12i,ld.d => pcalau12i,addi.d. */ static bool loongarch_relax_pcala_ld (bfd *abfd, asection *sec, - Elf_Internal_Rela *rel_hi) + asection *sym_sec ATTRIBUTE_UNUSED, + Elf_Internal_Rela *rel_hi, + bfd_vma symval ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + bool *again ATTRIBUTE_UNUSED, + bfd_vma max_alignment ATTRIBUTE_UNUSED) { bfd_byte *contents = elf_section_data (sec)->this_hdr.contents; Elf_Internal_Rela *rel_lo = rel_hi + 2; @@ -5075,9 +5077,6 @@ loongarch_relax_pcala_ld (bfd *abfd, asection *sec, uint32_t addi_d = LARCH_OP_ADDI_D; if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_GOT_PC_LO12) - || (ELFNN_R_TYPE ((rel_lo + 1)->r_info) != R_LARCH_RELAX) - || (ELFNN_R_TYPE ((rel_hi + 1)->r_info) != R_LARCH_RELAX) - || (rel_hi->r_offset + 4 != rel_lo->r_offset) || (LARCH_GET_RD(ld) != rd) || (LARCH_GET_RJ(ld) != rd) || !LARCH_INSN_LD_D(ld)) @@ -5107,11 +5106,12 @@ bfd_elfNN_loongarch_set_data_segment_info (struct bfd_link_info *info, /* Implement R_LARCH_ALIGN by deleting excess alignment NOPs. Once we've handled an R_LARCH_ALIGN, we can't relax anything else. */ static bool -loongarch_relax_align (bfd *abfd, asection *sec, - asection *sym_sec, - struct bfd_link_info *link_info, +loongarch_relax_align (bfd *abfd, asection *sec, asection *sym_sec, Elf_Internal_Rela *rel, - bfd_vma symval) + bfd_vma symval ATTRIBUTE_UNUSED, + struct bfd_link_info *link_info, + bool *again ATTRIBUTE_UNUSED, + bfd_vma max_alignment ATTRIBUTE_UNUSED) { bfd_vma addend, max = 0, alignment = 1; @@ -5199,9 +5199,6 @@ loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec, /* Is pcalau12i + addi.d insns? */ if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_GOT_PC_LO12 && ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_TLS_DESC_PC_LO12) - || (ELFNN_R_TYPE ((rel_lo + 1)->r_info) != R_LARCH_RELAX) - || (ELFNN_R_TYPE ((rel_hi + 1)->r_info) != R_LARCH_RELAX) - || (rel_hi->r_offset + 4 != rel_lo->r_offset) || !LARCH_INSN_ADDI_D(add) /* Is pcalau12i $rd + addi.d $rd,$rd? */ || (LARCH_GET_RD(add) != rd) @@ -5258,12 +5255,18 @@ loongarch_get_max_alignment (asection *sec) return (bfd_vma) 1 << max_alignment_power; } +typedef bool (*relax_func_t) (bfd *, asection *, asection *, + Elf_Internal_Rela *, bfd_vma, + struct bfd_link_info *, bool *, + bfd_vma); + static bool loongarch_elf_relax_section (bfd *abfd, asection *sec, struct bfd_link_info *info, bool *again) { *again = false; + if (!is_elf_hash_table (info->hash) || elf_hash_table_id (elf_hash_table (info)) != LARCH_ELF_DATA) return true; @@ -5278,13 +5281,13 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, if (bfd_link_relocatable (info) || sec->sec_flg0 - || (sec->flags & SEC_RELOC) == 0 || sec->reloc_count == 0 + || (sec->flags & SEC_RELOC) == 0 + || (sec->flags & SEC_HAS_CONTENTS) == 0 + /* The exp_seg_relro_adjust is enum phase_enum (0x4). */ + || *(htab->data_segment_phase) == 4 || (info->disable_target_specific_optimizations - && info->relax_pass == 0) - /* The exp_seg_relro_adjust is enum phase_enum (0x4), - and defined in ld/ldexp.h. */ - || *(htab->data_segment_phase) == 4) + && info->relax_pass == 0)) return true; struct bfd_elf_section_data *data = elf_section_data (sec); @@ -5294,11 +5297,14 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, else if (!(relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, info->keep_memory))) return true; + data->relocs = relocs; + /* Read this BFD's contents if we haven't done so already. */ if (!data->this_hdr.contents && !bfd_malloc_and_get_section (abfd, sec, &data->this_hdr.contents)) return true; + /* Read this BFD's symbols if we haven't done so already. */ Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd); if (symtab_hdr->sh_info != 0 && !symtab_hdr->contents @@ -5308,8 +5314,6 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, 0, NULL, NULL, NULL))) return true; - data->relocs = relocs; - /* Estimate the maximum alignment for all output sections once time should be enough. */ bfd_vma max_alignment = htab->max_alignment; @@ -5331,6 +5335,93 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, unsigned long r_type = ELFNN_R_TYPE (rel->r_info); unsigned long r_symndx = ELFNN_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + h = elf_sym_hashes (abfd)[r_symndx - symtab_hdr->sh_info]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + } + + /* If the conditions for tls type transition are met, type + transition is performed instead of relax. + During the transition from DESC->IE/LE, there are 2 situations + depending on the different configurations of the relax/norelax + option. + If the -relax option is used, the extra nops will be removed, + and this transition is performed in pass 0. + If the --no-relax option is used, nop will be retained, and + this transition is performed in pass 1. */ + if (IS_LOONGARCH_TLS_TRANS_RELOC (r_type) + && (i + 1 != sec->reloc_count) + && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX + && rel->r_offset == rel[1].r_offset + && loongarch_can_trans_tls (abfd, info, h, r_symndx, r_type)) + { + loongarch_tls_perform_trans (abfd, sec, rel, h, info); + r_type = ELFNN_R_TYPE (rel->r_info); + } + + relax_func_t relax_func = NULL; + if (info->relax_pass == 0) + { + switch (r_type) + { + case R_LARCH_PCALA_HI20: + relax_func = loongarch_relax_pcala_addi; + break; + case R_LARCH_GOT_PC_HI20: + relax_func = loongarch_relax_pcala_ld; + break; + case R_LARCH_CALL36: + relax_func = loongarch_relax_call36; + break; + case R_LARCH_TLS_LE_HI20_R: + case R_LARCH_TLS_LE_LO12_R: + case R_LARCH_TLS_LE_ADD_R: + case R_LARCH_TLS_LE_HI20: + case R_LARCH_TLS_LE_LO12: + case R_LARCH_TLS_LE64_LO20: + case R_LARCH_TLS_LE64_HI12: + relax_func = loongarch_relax_tls_le; + break; + case R_LARCH_TLS_LD_PC_HI20: + case R_LARCH_TLS_GD_PC_HI20: + case R_LARCH_TLS_DESC_PC_HI20: + relax_func = loongarch_relax_tls_ld_gd_desc; + break; + default: + continue; + } + + /* Only relax this reloc if it is paired with R_RISCV_RELAX. */ + if (r_type == R_LARCH_TLS_LD_PC_HI20 + || r_type == R_LARCH_TLS_GD_PC_HI20 + || r_type == R_LARCH_TLS_DESC_PC_HI20 + || r_type == R_LARCH_PCALA_HI20 + || r_type == R_LARCH_GOT_PC_HI20) + { + if ((i + 2) == sec->reloc_count - 1 + || ELFNN_R_TYPE ((rel + 1)->r_info) != R_LARCH_RELAX + || ELFNN_R_TYPE ((rel + 3)->r_info) != R_LARCH_RELAX + || rel->r_offset != (rel + 1)->r_offset + || (rel + 2)->r_offset != (rel + 3)->r_offset + || rel->r_offset + 4 != (rel + 2)->r_offset) + continue; + } + else + { + if (i == sec->reloc_count - 1 + || ELFNN_R_TYPE ((rel + 1)->r_info) != R_LARCH_RELAX + || rel->r_offset != (rel + 1)->r_offset) + continue; + } + } + else if (info->relax_pass == 1 && r_type == R_LARCH_ALIGN) + relax_func = loongarch_relax_align; + else + continue; + /* Four kind of relocations: Normal: symval is the symbol address. R_LARCH_ALIGN: symval is the address of the last NOP instruction @@ -5343,29 +5434,26 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, { Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents + r_symndx; + if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) continue; /* Only TLS instruction sequences that are accompanied by R_LARCH_RELAX and cannot perform type transition can be relaxed. */ - if (R_LARCH_TLS_LD_PC_HI20 == r_type - || R_LARCH_TLS_GD_PC_HI20 == r_type - || (R_LARCH_TLS_DESC_PC_HI20 == r_type - && (i + 1 != sec->reloc_count) - && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX - && ! loongarch_can_trans_tls (abfd, info, h, - r_symndx, r_type))) + if (r_type == R_LARCH_TLS_LD_PC_HI20 + || r_type == R_LARCH_TLS_GD_PC_HI20 + || r_type == R_LARCH_TLS_DESC_PC_HI20) { sym_sec = htab->elf.sgot; symval = elf_local_got_offsets (abfd)[r_symndx]; char tls_type = _bfd_loongarch_elf_tls_type (abfd, h, r_symndx); - if (R_LARCH_TLS_DESC_PC_HI20 == r_type + if (r_type == R_LARCH_TLS_DESC_PC_HI20 && GOT_TLS_GD_BOTH_P (tls_type)) symval += 2 * GOT_ENTRY_SIZE; } - else if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type) + else if (sym->st_shndx == SHN_UNDEF || r_type == R_LARCH_ALIGN) { sym_sec = sec; symval = rel->r_offset; @@ -5376,35 +5464,25 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, symval = sym->st_value; } symtype = ELF_ST_TYPE (sym->st_info); + is_abs_symbol = sym->st_shndx == SHN_ABS; } else { - r_symndx = ELFNN_R_SYM (rel->r_info) - symtab_hdr->sh_info; - h = elf_sym_hashes (abfd)[r_symndx]; - - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* Disable the relaxation for ifunc. */ if (h != NULL && h->type == STT_GNU_IFUNC) continue; /* The GOT entry of tls symbols must in current execute file or shared object. */ - if (R_LARCH_TLS_LD_PC_HI20 == r_type - || R_LARCH_TLS_GD_PC_HI20 == r_type - || (R_LARCH_TLS_DESC_PC_HI20 == r_type - && (i + 1 != sec->reloc_count) - && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX - && !loongarch_can_trans_tls (abfd, info, h, - r_symndx, r_type))) + if (r_type == R_LARCH_TLS_LD_PC_HI20 + || r_type == R_LARCH_TLS_GD_PC_HI20 + || r_type == R_LARCH_TLS_DESC_PC_HI20) { sym_sec = htab->elf.sgot; symval = h->got.offset; char tls_type = _bfd_loongarch_elf_tls_type (abfd, h, r_symndx); - if (R_LARCH_TLS_DESC_PC_HI20 == r_type + if (r_type == R_LARCH_TLS_DESC_PC_HI20 && GOT_TLS_GD_BOTH_P (tls_type)) symval += 2 * GOT_ENTRY_SIZE; } @@ -5413,12 +5491,13 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, && h->root.u.def.section != NULL && h->root.u.def.section->output_section != NULL) { - symval = h->root.u.def.value; sym_sec = h->root.u.def.section; + symval = h->root.u.def.value; } else continue; + is_abs_symbol = bfd_is_abs_section (h->root.u.def.section); if (h && LARCH_REF_LOCAL (info, h)) local_got = true; symtype = h->type; @@ -5441,7 +5520,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, + (alingmeng - 4). If r_symndx is 0, alignmeng-4 is r_addend. If r_symndx > 0, alignment-4 is 2^(r_addend & 0xff)-4. */ - else if (R_LARCH_ALIGN == r_type) + else if (r_type == R_LARCH_ALIGN) if (r_symndx > 0) symval += ((1 << (rel->r_addend & 0xff)) - 4); else @@ -5451,96 +5530,14 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, symval += sec_addr (sym_sec); - /* If the conditions for tls type transition are met, type - transition is performed instead of relax. - During the transition from DESC->IE/LE, there are 2 situations - depending on the different configurations of the relax/norelax - option. - If the -relax option is used, the extra nops will be removed, - and this transition is performed in pass 0. - If the --no-relax option is used, nop will be retained, and - this transition is performed in pass 1. */ - if (IS_LOONGARCH_TLS_TRANS_RELOC (r_type) - && (i + 1 != sec->reloc_count) - && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX - && loongarch_can_trans_tls (abfd, info, h, r_symndx, r_type)) - { - loongarch_tls_perform_trans (abfd, sec, rel, h, info); - r_type = ELFNN_R_TYPE (rel->r_info); - } - - switch (r_type) - { - case R_LARCH_ALIGN: - if (1 == info->relax_pass) - loongarch_relax_align (abfd, sec, sym_sec, info, rel, symval); - break; + if (r_type == R_LARCH_GOT_PC_HI20 && (!local_got || is_abs_symbol)) + continue; - case R_LARCH_DELETE: - if (1 == info->relax_pass) - { - loongarch_relax_delete_bytes (abfd, sec, rel->r_offset, 4, info); - rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE); - } - break; - case R_LARCH_CALL36: - if (0 == info->relax_pass && (i + 2) <= sec->reloc_count) - loongarch_relax_call36 (abfd, sec, sym_sec, rel, symval, + if (relax_func (abfd, sec, sym_sec, rel, symval, + info, again, max_alignment) + && relax_func == loongarch_relax_pcala_ld) + loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval, info, again, max_alignment); - break; - - case R_LARCH_TLS_LE_HI20_R: - case R_LARCH_TLS_LE_LO12_R: - case R_LARCH_TLS_LE_ADD_R: - case R_LARCH_TLS_LE_HI20: - case R_LARCH_TLS_LE_LO12: - case R_LARCH_TLS_LE64_LO20: - case R_LARCH_TLS_LE64_HI12: - if (0 == info->relax_pass && (i + 2) <= sec->reloc_count) - loongarch_relax_tls_le (abfd, sec, rel, info, symval); - break; - - 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, max_alignment); - break; - - case R_LARCH_GOT_PC_HI20: - if (h) - is_abs_symbol = bfd_is_abs_section(h->root.u.def.section); - else - { - Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents - + ELFNN_R_SYM (rel->r_info); - is_abs_symbol = sym->st_shndx == SHN_ABS; - } - /* If symval is in the range [-2^31, 2^31), we can relax the - pair of instructions from pcalau12i/ld.d to lu12i.w/ori for - abosulte symbol. This is not implemented yet, so we just - remain the r_type which will be needed when relocate for - absolute symbol. */ - if (local_got && 0 == info->relax_pass - && !is_abs_symbol - && (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, max_alignment); - } - break; - - case R_LARCH_TLS_LD_PC_HI20: - case R_LARCH_TLS_GD_PC_HI20: - 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, max_alignment); - break; - - default: - break; - } } return true; From patchwork Sat Oct 12 03:43:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: mengqinggang X-Patchwork-Id: 98784 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 750FC385AC30 for ; Sat, 12 Oct 2024 03:45:23 +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 E52473857C4F for ; Sat, 12 Oct 2024 03:44:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E52473857C4F 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 E52473857C4F 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=1728704648; cv=none; b=jLQT276FWs6N4DUXdWdQMq+/6umfynYxSVPI0T2ZQhdimdKZSMMHHEYqZrmVr19w8DShFtIBDKLX5HjnUVO7LZCMRm95Q0u8EGesAQNTTkZvyttpTWjtHPW7cj26B/Z+kwwdwlzSYE8gwCY7VlUp5i4CIOieMx/iWPXG6VbIdWc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1728704648; c=relaxed/simple; bh=XEwqoJBAOwKdPp6ecUcHzrBm1rpFd/g+0PrtV5sz6Yk=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=NIxFkDTmsl0QdvZTy+kaa5GY7jlw2zBRkJZ1Y0prsolI13AGAYwcaeurf8zJHvzAWCtAxTlH4NtXpjxYimKMsyM+rzR7fj79HicbtfOGHkBz8brmRSVnGn+WoLm+zXBS04GiXa5kTyjAyYFSENpqIcQTCOkAfdH0/6K2iTS9obM= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from loongson.cn (unknown [10.2.6.5]) by gateway (Coremail) with SMTP id _____8DxyrGC8AlnZXkUAA--.30035S3; Sat, 12 Oct 2024 11:44:02 +0800 (CST) Received: from 5.5.5 (unknown [10.2.6.5]) by front1 (Coremail) with SMTP id qMiowMDx_9d98AlnhqwkAA--.52119S4; Sat, 12 Oct 2024 11:44:00 +0800 (CST) From: mengqinggang To: binutils@sourceware.org Cc: xuchenghua@loongson.cn, chenglulu@loongson.cn, cailulu@loongson.cn, xry111@xry111.site, i.swmail@xen0n.name, maskray@google.com, luweining@loongson.cn, hejinyang@loongson.cn, mengqinggang@loongson.cn Subject: [PATCH 2/2] LoongArch: Add more relaxation support for call36 Date: Sat, 12 Oct 2024 11:43:56 +0800 Message-Id: <20241012034356.2957334-3-mengqinggang@loongson.cn> X-Mailer: git-send-email 2.39.3 In-Reply-To: <20241012034356.2957334-1-mengqinggang@loongson.cn> References: <20241012034356.2957334-1-mengqinggang@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: qMiowMDx_9d98AlnhqwkAA--.52119S4 X-CM-SenderInfo: 5phqw15lqjwttqj6z05rqj20fqof0/ X-Coremail-Antispam: 1Uk129KBj93XoW3Xry7Gr15KryrtF1DXr43Jwc_yoWxCF45pr y5Zw1jkF1xJFnrA3Z3GayFgrs0g397KryFv3sFq3yY9r45JrWxXw4jvr4fXa1DJw4vgr1j qr10yw1UWF4vvrcCm3ZEXasCq-sJn29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUkFb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r106r15M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Gr0_Xr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr0_Cr1l84ACjcxK6I8E87Iv67AKxVWxJVW8Jr1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqjxCEc2xF0cIa020Ex4CE44I27w Aqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI8IcVAFwI0_Jw0_WrylYx0Ex4A2jsIE 14v26r4j6F4UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwCF04k20xvY0x 0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E 7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAIcV C0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1lIxAIcVCF 04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7 CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x07jOdb8UUUUU= X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_NUMSUBJECT, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org Add relaxation support for call36 that jump to PLT entry. Add relaxation support for call36 with IFUNC symbol. Add relaxation support for call36 that jump to undefweak symbol. For undefweak symbol, it can always be relaxed if it have no PLT entry. Because we set the address of undefweak symbol without PLT entry to PC like relocate_section. --- bfd/elfnn-loongarch.c | 21 +++- .../ld-loongarch-elf/relax-call36-exe.s | 32 ++++++ .../ld-loongarch-elf/relax-call36-so.s | 35 ++++++ ld/testsuite/ld-loongarch-elf/relax.exp | 105 ++++++++++++++++++ 4 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 ld/testsuite/ld-loongarch-elf/relax-call36-exe.s create mode 100644 ld/testsuite/ld-loongarch-elf/relax-call36-so.s diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index d683fd32ff4..9c3cd6745d6 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -5435,7 +5435,8 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents + r_symndx; - if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) + if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC + && r_type != R_LARCH_CALL36) continue; /* Only TLS instruction sequences that are accompanied by @@ -5468,8 +5469,8 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, } else { - /* Disable the relaxation for ifunc. */ - if (h != NULL && h->type == STT_GNU_IFUNC) + if (h != NULL && h->type == STT_GNU_IFUNC + && r_type != R_LARCH_CALL36) continue; /* The GOT entry of tls symbols must in current execute file or @@ -5486,6 +5487,20 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec, && GOT_TLS_GD_BOTH_P (tls_type)) symval += 2 * GOT_ENTRY_SIZE; } + else if (h->plt.offset != MINUS_ONE) + { + sym_sec = htab->elf.splt ? htab->elf.splt : htab->elf.iplt; + symval = h->plt.offset; + } + /* Like loongarch_elf_relocate_section, set relocation(offset) to 0. + Undefweak for other relocations handing in the future. */ + else if (h->root.type == bfd_link_hash_undefweak + && !h->root.linker_def + && r_type == R_LARCH_CALL36) + { + sym_sec = sec; + symval = rel->r_offset; + } else if ((h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) && h->root.u.def.section != NULL diff --git a/ld/testsuite/ld-loongarch-elf/relax-call36-exe.s b/ld/testsuite/ld-loongarch-elf/relax-call36-exe.s new file mode 100644 index 00000000000..26cff4df5ed --- /dev/null +++ b/ld/testsuite/ld-loongarch-elf/relax-call36-exe.s @@ -0,0 +1,32 @@ +ldd: # local define default +call36 ldd # ldd + +ldh: # local define hidden +.hidden ldh +call36 ldh # ldh + +gdd: +.global gdd # global define default +call36 gdd # gdd@plt + +gdh: +.global gdh # global define hidden +.hidden gdh +call36 gdh # gdh + +wdd: +.weak wdd # weak define default +call36 wdd # wdd@plt + +.weak wud # weak undefine default +call36 wud # wud@plt + +wdh: +.weak wdh # weak define hidden +.hidden wdh +call36 wdh # wdh + +.weak wuh # weak undefine hidden +.hidden wuh +call36 wuh # wuh + diff --git a/ld/testsuite/ld-loongarch-elf/relax-call36-so.s b/ld/testsuite/ld-loongarch-elf/relax-call36-so.s new file mode 100644 index 00000000000..050273b020e --- /dev/null +++ b/ld/testsuite/ld-loongarch-elf/relax-call36-so.s @@ -0,0 +1,35 @@ +ldd: # local define default +call36 ldd # ldd + +ldh: # local define hidden +.hidden ldh +call36 ldh # ldh + +gdd: +.global gdd # global define default +call36 gdd # gdd@plt + +.global gud # global undefine default +call36 gud # gud@plt + +gdh: +.global gdh # global define hidden +.hidden gdh +call36 gdh # gdh + +wdd: +.weak wdd # weak define default +call36 wdd # wdd@plt + +.weak wud # weak undefine default +call36 wud # wud@plt + +wdh: +.weak wdh # weak define hidden +.hidden wdh +call36 wdh # wdh + +.weak wuh # weak undefine hidden +.hidden wuh +call36 wuh # wuh + diff --git a/ld/testsuite/ld-loongarch-elf/relax.exp b/ld/testsuite/ld-loongarch-elf/relax.exp index 4771f1eb429..aef74483dc9 100644 --- a/ld/testsuite/ld-loongarch-elf/relax.exp +++ b/ld/testsuite/ld-loongarch-elf/relax.exp @@ -51,6 +51,111 @@ if [istarget loongarch64-*-*] { run_dump_test "relax-align-ignore-start" run_partial_linking_align_test + run_ld_link_tests \ + [list \ + [list \ + "loongarch relax call36 .so build" \ + "-shared" "" \ + "" \ + {relax-call36-so.s} \ + {} \ + "relax-call36.so" \ + ] \ + ] + + if [file exist "tmpdir/relax-call36.so"] { + set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax-call36.so"] + if { [ regexp "pcaddu18i" $objdump_output] } { + fail "loongarch relax call36 so" + } { + pass "loongarch relax call36 so" + } + } + + run_ld_link_tests \ + [list \ + [list \ + "loongarch relax call36 dyn exe build" \ + "-pie -e 0" "" \ + "" \ + {relax-call36-exe.s} \ + {} \ + "relax-call36-d.exe" \ + ] \ + ] + + if [file exist "tmpdir/relax-call36-d.exe"] { + set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax-call36-d.exe"] + if { [ regexp "pcaddu18i" $objdump_output] } { + fail "loongarch relax call36 dyn exe" + } { + pass "loongarch relax call36 dyn exe" + } + } + + run_ld_link_tests \ + [list \ + [list \ + "loongarch relax call36 dyn-pie exe build" \ + "-pie -e 0" "" \ + "" \ + {relax-call36-exe.s} \ + {} \ + "relax-call36-dp.exe" \ + ] \ + ] + + if [file exist "tmpdir/relax-call36-dp.exe"] { + set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax-call36-dp.exe"] + if { [ regexp "pcaddu18i" $objdump_output] } { + fail "loongarch relax call36 dyn-pie exe" + } { + pass "loongarch relax call36 dyn-pie exe" + } + } + + run_ld_link_tests \ + [list \ + [list \ + "loongarch relax call36 static exe build" \ + "-static -e 0" "" \ + "" \ + {relax-call36-exe.s} \ + {} \ + "relax-call36-s.exe" \ + ] \ + ] + + if [file exist "tmpdir/relax-call36-s.exe"] { + set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax-call36-s.exe"] + if { [ regexp "pcaddu18i" $objdump_output] } { + fail "loongarch relax call36 static exe" + } { + pass "loongarch relax call36 static exe" + } + } + + run_ld_link_tests \ + [list \ + [list \ + "loongarch relax call36 static-pie exe build" \ + "-static -pie --no-dynamic-linker -e 0" "" \ + "" \ + {relax-call36-exe.s} \ + {} \ + "relax-call36-sp.exe" \ + ] \ + ] + + if [file exist "tmpdir/relax-call36-sp.exe"] { + set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax-call36-sp.exe"] + if { [ regexp "pcaddu18i" $objdump_output] } { + fail "loongarch relax call36 static-pie exe" + } { + pass "loongarch relax call36 static-pie exe" + } + } + run_ld_link_tests \ [list \ [list \