From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from xry111.site (xry111.site [89.208.246.23]) by sourceware.org (Postfix) with ESMTPS id A4BBA3858400 for ; Wed, 31 Aug 2022 13:23:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org A4BBA3858400 Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=xry111.site Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=xry111.site DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=xry111.site; s=default; t=1661952218; bh=xHqWV0uW9++1kwZ1GNGyCHE4rEfU7NPbawQ5LdRNZ8s=; h=From:To:Cc:Subject:Date:From; b=iiwot/dAw5tuZRXVQ1s1WcS4Qro7mrL5iyrck4tWdq1DS3H3IvfHrV1FE0bJo3J7j Vd9WrzVHvDaGc/cibZbK6MvpurpdP0MBOW3rAVI0Ccjdim4jAJO/Z/QY5X9HdK2OsU aa9Xsl2h4goKMIp6ceuCm8J4bp4+zL0sldYFX/kI= Received: from xry111-x57s1.. (unknown [IPv6:240e:358:118a:f800:dc73:854d:832e:4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (Client did not present a certificate) (Authenticated sender: xry111@xry111.site) by xry111.site (Postfix) with ESMTPSA id 980C566894; Wed, 31 Aug 2022 09:23:34 -0400 (EDT) From: Xi Ruoyao To: binutils@sourceware.org Cc: liuzhensong , WANG Xuerui , caiyinyu , Xi Ruoyao Subject: [PATCH] LoongArch: Use copy relocation for %pc_lo12 against external symbol Date: Wed, 31 Aug 2022 21:22:59 +0800 Message-Id: <20220831132259.71417-1-xry111@xry111.site> X-Mailer: git-send-email 2.37.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-6.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FROM_SUSPICIOUS_NTLD,FROM_SUSPICIOUS_NTLD_FP,GIT_PATCH_0,LIKELY_SPAM_FROM,PDS_OTHER_BAD_TLD,SPF_HELO_PASS,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 List-Id: We'd like to use PC-relative addressing instead of GOT for external symbols in main executable images. This can improve code locality. Doing so will need to implement copy relocation. Despite there was a comment saying "Glibc does not support copy relocation yet", I've run a very simple test and it seems copy relocation is handled by ld.so without a problem: pcalau12i $a1, %pc_hi20(stdout) ld.d $a1, $a1, %pc_lo12(stdout) pcalau12i $a0, %pc_hi20(msg) addi.d $a0, $a0, %pc_lo12(msg) pcalau12i $ra, %pc_hi20(fputs) jirl $ra, $ra, %pc_lo12(fputs) With this patch, R_LARCH_COPY is correctly emitted for "stdout" in Glibc, and the test program runs and outputs "Hello world" in "msg" successfully. --- bfd/elfnn-loongarch.c | 93 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 9 deletions(-) diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index ed42b8b6770..0cf24bd24d8 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -743,14 +743,26 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, h->non_got_ref = 1; break; - case R_LARCH_PCALA_HI20: + case R_LARCH_PCALA_LO12: if (h != NULL) { - /* For pcalau12i + jirl. */ - h->needs_plt = 1; - if (h->plt.refcount < 0) - h->plt.refcount = 0; - h->plt.refcount++; + /* Check if it's a jirl instruction. */ + bfd_byte *contents = elf_section_data (sec)->this_hdr.contents; + uint32_t insn = 0; + + if (contents || bfd_malloc_and_get_section (abfd, sec, &contents)) + memcpy(&insn, contents + rel->r_offset, sizeof(insn)); + + if ((insn & 0xfc000000) == 0x4c000000) + { + /* For pcalau12i + jirl. */ + h->needs_plt = 1; + if (h->plt.refcount < 0) + h->plt.refcount = 0; + h->plt.refcount++; + } + else + need_dynreloc = 1; h->non_got_ref = 1; h->pointer_equality_needed = 1; @@ -949,7 +961,9 @@ loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h) { struct loongarch_elf_link_hash_table *htab; + struct loongarch_elf_link_hash_entry *hent; bfd *dynobj; + asection *s, *srel; htab = loongarch_elf_hash_table (info); BFD_ASSERT (htab != NULL); @@ -999,9 +1013,52 @@ loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info, return true; } - /* R_LARCH_COPY is not adept glibc, not to generate. */ - /* Can not print anything, because make check ld. */ - return true; + /* If copy relocations is disabled via -z nocopyreloc, or we don't find any + dynamic relocs in read-only sections, avoid the copy reloc. */ + if (info->nocopyreloc || !_bfd_elf_readonly_dynrelocs (h)) + h->non_got_ref = 0; + + if (!h->non_got_ref) + return true; + + /* We must allocate the symbol in our .dynbss section, which will + become part of the .bss section of the executable. There will be + an entry for this symbol in the .dynsym section. The dynamic + object will contain position independent code, so all references + from the dynamic object to this symbol will go through the global + offset table. The dynamic linker will use the .dynsym entry to + determine the address it must put in the global offset table, so + both the dynamic object and the regular object will refer to the + same memory location for the variable. */ + + /* Generate a copy relocation to tell the dynamic linker to copy the + initial value out of the dynamic object and into the runtime process + image. We need to remember the offset into the .rel.bss section we + are going to use. */ + hent = (struct loongarch_elf_link_hash_entry *) h; + if (hent->tls_type & ~GOT_NORMAL) + { + s = htab->sdyntdata; + srel = htab->elf.srelbss; + } + else if (h->root.u.def.section->flags & SEC_READONLY) + { + s = htab->elf.sdynrelro; + srel = htab->elf.sreldynrelro; + } + else + { + s = htab->elf.sdynbss; + srel = htab->elf.srelbss; + } + + if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0) + { + srel->size += sizeof (ElfNN_External_Rela); + h->needs_copy = 1; + } + + return _bfd_elf_adjust_dynamic_copy (info, h, s); } /* Allocate space in .plt, .got and associated reloc sections for @@ -3702,6 +3759,24 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, loongarch_elf_append_rela (output_bfd, srela, &rela); } + if (h->needs_copy) + { + Elf_Internal_Rela rela; + asection *s; + + /* This symbols needs a copy reloc. Set it up. */ + BFD_ASSERT (h->dynindx != -1); + + rela.r_offset = sec_addr (h->root.u.def.section) + h->root.u.def.value; + rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_COPY); + rela.r_addend = 0; + if (h->root.u.def.section == htab->elf.sdynrelro) + s = htab->elf.sreldynrelro; + else + s = htab->elf.srelbss; + loongarch_elf_append_rela (output_bfd, s, &rela); + } + /* Mark some specially defined symbols as absolute. */ if (h == htab->elf.hdynamic || h == htab->elf.hgot || h == htab->elf.hplt) sym->st_shndx = SHN_ABS; -- 2.37.0