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;