From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7803) id 09C613882175; Fri, 28 Jun 2024 05:51:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 09C613882175 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1719553883; bh=tbM636xt2O1/EhiXsAVNEcQXshPuFj0DUugfritGMPA=; h=From:To:Subject:Date:From; b=nzRFPPmS8S1cOxK0rldC4wkgRwxVA5mi07sDxR7g+9UZbn65QyyF7pPW7/wwpT9ms Xq1JVpyFEkMdf1EVlgugNM9Vk8bCZW7jbL6yEwsYPik9qccCj9ZNrU9ykGk2FNe3R5 dS/5AlQ936M1g4VG4IEiRblNR/VdkG5G9epyahk0= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Nelson Chu To: binutils-cvs@sourceware.org Subject: [binutils-gdb] RISC-V: PR27180, Update relocation for riscv_zero_pcrel_hi_reloc. X-Act-Checkin: binutils-gdb X-Git-Author: Nelson Chu X-Git-Refname: refs/heads/master X-Git-Oldrev: 805df5e4a8de619aec6d6a808158c302307478e7 X-Git-Newrev: 81c353cb9cbba572b73ea4a3949571c44282b0df Message-Id: <20240628055123.09C613882175@sourceware.org> Date: Fri, 28 Jun 2024 05:51:22 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D81c353cb9cbb= a572b73ea4a3949571c44282b0df commit 81c353cb9cbba572b73ea4a3949571c44282b0df Author: Nelson Chu Date: Tue Jun 11 16:35:58 2024 +0800 RISC-V: PR27180, Update relocation for riscv_zero_pcrel_hi_reloc. =20 When pcrel access overflow, the riscv_zero_pcrel_hi_reloc may convert p= crel relocation to absolutly access if possible at the relocate stage. We u= sed to encode the target address into r_sym of R_RISCV_HI20 if it is converted= from R_RISCV_PCREL_HI20. But that may cause segfault if --emit-relocs is se= t, since r_sym becomes an address rather than a symbol index. Although the relocate result is correct, it does not meet the definition, so may cau= se unexpected behaviors. =20 This patch encodes the target address into r_addend, rather than r_sym,= if riscv_zero_pcrel_hi_reloc converts the relocation. Besdies, since the corresponding pcrel_lo relocation are also changed to absolutly access, we should also update them to R_RISCV_LO12_I/S. =20 bfd/ PR 27180 * elfnn-riscv.c (riscv_pcrel_hi_reloc): New boolean `absolute',= to inform corresponding pcrel_lo that the pcrel_hi relocation was = already converted to hi20 relocation. (riscv_record_pcrel_hi_reloc): Likewise, record `absolute'. (riscv_pcrel_lo_reloc): Removed `const' for Elf_Internal_Rela *= reloc, since we may need to convert it from pcrel_lo to lo relocation. (riscv_record_pcrel_lo_reloc): Likewise. Convert pcrel_lo to lo relocation if corresponding pcrel_hi was converted to hi reloca= tion. (riscv_zero_pcrel_hi_reloc): Encode target absolute address into r_addend rather than r_sym. Clear the `addr' to avoid duplicate relocate in the perform_relocation. (riscv_elf_relocate_section): Updated. ld/ PR 27180 * testsuite/ld-riscv-elf/pcrel-lo-addend-3a-emit-relocs.d: New = testcase. Segfault without applying this patch. * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Updated. Diff: --- bfd/elfnn-riscv.c | 52 +++++++++++++++++-= ---- ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp | 1 + .../ld-riscv-elf/pcrel-lo-addend-3a-emit-relocs.d | 26 +++++++++++ 3 files changed, 67 insertions(+), 12 deletions(-) diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index 7591968ca9c..90ecc276f31 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -1969,6 +1969,8 @@ typedef struct bfd_vma value; /* Original reloc type. */ int type; + /* True if changed to R_RISCV_HI20. */ + bool absolute; } riscv_pcrel_hi_reloc; =20 typedef struct riscv_pcrel_lo_reloc @@ -1976,7 +1978,7 @@ typedef struct riscv_pcrel_lo_reloc /* PC value of auipc. */ bfd_vma address; /* Internal relocation. */ - const Elf_Internal_Rela *reloc; + Elf_Internal_Rela *reloc; /* Record the following information helps to resolve the %pcrel which cross different input section. For now we build a hash for pcrel at the start of riscv_elf_relocate_section, and then @@ -2043,7 +2045,7 @@ static bool riscv_zero_pcrel_hi_reloc (Elf_Internal_Rela *rel, struct bfd_link_info *info, bfd_vma pc, - bfd_vma addr, + bfd_vma *addr, bfd_byte *contents, const reloc_howto_type *howto) { @@ -2059,17 +2061,22 @@ riscv_zero_pcrel_hi_reloc (Elf_Internal_Rela *rel, =20 /* If it's possible to reference the symbol using auipc we do so, as tha= t's more in the spirit of the PC-relative relocations we're processing. = */ - bfd_vma offset =3D addr - pc; + bfd_vma offset =3D *addr - pc; if (ARCH_SIZE =3D=3D 32 || VALID_UTYPE_IMM (RISCV_CONST_HIGH_PART (offse= t))) return false; =20 /* If it's impossible to reference this with a LUI-based offset then don= 't bother to convert it at all so users still see the PC-relative reloca= tion in the truncation message. */ - if (ARCH_SIZE > 32 && !VALID_UTYPE_IMM (RISCV_CONST_HIGH_PART (addr))) + if (ARCH_SIZE > 32 && !VALID_UTYPE_IMM (RISCV_CONST_HIGH_PART (*addr))) return false; =20 - rel->r_info =3D ELFNN_R_INFO (addr, R_RISCV_HI20); + /* PR27180, encode target absolute address into r_addend rather than + r_sym. Clear the ADDR to avoid duplicate relocate in the + perform_relocation. */ + rel->r_info =3D ELFNN_R_INFO (0, R_RISCV_HI20); + rel->r_addend +=3D *addr; + *addr =3D 0; =20 bfd_vma insn =3D riscv_get_insn (howto->bitsize, contents + rel->r_offse= t); insn =3D (insn & ~MASK_AUIPC) | MATCH_LUI; @@ -2085,7 +2092,7 @@ riscv_record_pcrel_hi_reloc (riscv_pcrel_relocs *p, bool absolute) { bfd_vma offset =3D absolute ? value : value - addr; - riscv_pcrel_hi_reloc entry =3D {addr, offset, type}; + riscv_pcrel_hi_reloc entry =3D {addr, offset, type, absolute}; riscv_pcrel_hi_reloc **slot =3D (riscv_pcrel_hi_reloc **) htab_find_slot (p->hi_relocs, &entry, INSERT= ); =20 @@ -2100,7 +2107,7 @@ riscv_record_pcrel_hi_reloc (riscv_pcrel_relocs *p, static bool riscv_record_pcrel_lo_reloc (riscv_pcrel_relocs *p, bfd_vma addr, - const Elf_Internal_Rela *reloc, + Elf_Internal_Rela *reloc, asection *input_section, struct bfd_link_info *info, reloc_howto_type *howto, @@ -2125,7 +2132,7 @@ riscv_resolve_pcrel_lo_relocs (riscv_pcrel_relocs *p) { bfd *input_bfd =3D r->input_section->owner; =20 - riscv_pcrel_hi_reloc search =3D {r->address, 0, 0}; + riscv_pcrel_hi_reloc search =3D {r->address, 0, 0, 0}; riscv_pcrel_hi_reloc *entry =3D htab_find (p->hi_relocs, &search); /* There may be a risk if the %pcrel_lo with addend refers to an IFUNC symbol. The %pcrel_hi has been relocated to plt, @@ -2160,6 +2167,27 @@ riscv_resolve_pcrel_lo_relocs (riscv_pcrel_relocs *p) =20 perform_relocation (r->howto, r->reloc, entry->value, r->input_secti= on, input_bfd, r->contents); + + /* The corresponding R_RISCV_GOT_PCREL_HI20 and R_RISCV_PCREL_HI20 a= re + converted to R_RISCV_HI20, so try to convert R_RISCV_PCREL_LO12_I/S + to R_RISCV_LO12_I/S. */ + if (entry->absolute) + { + switch (ELFNN_R_TYPE (r->reloc->r_info)) + { + case R_RISCV_PCREL_LO12_I: + r->reloc->r_info =3D ELFNN_R_INFO (0, R_RISCV_LO12_I); + r->reloc->r_addend +=3D entry->value; + break; + case R_RISCV_PCREL_LO12_S: + r->reloc->r_info =3D ELFNN_R_INFO (0, R_RISCV_LO12_S); + r->reloc->r_addend +=3D entry->value; + break; + default: + /* This shouldn't happen, so just skip it. */ + break; + } + } } =20 return true; @@ -2698,7 +2726,7 @@ riscv_elf_relocate_section (bfd *output_bfd, /* Address of got entry. */ relocation =3D sec_addr (htab->elf.sgot) + off; absolute =3D riscv_zero_pcrel_hi_reloc (rel, info, pc, - relocation, contents, + &relocation, contents, howto); /* Update howto if relocation is changed. */ howto =3D riscv_elf_rtype_to_howto (input_bfd, @@ -2706,8 +2734,8 @@ riscv_elf_relocate_section (bfd *output_bfd, if (howto =3D=3D NULL) r =3D bfd_reloc_notsupported; else if (!riscv_record_pcrel_hi_reloc (&pcrel_relocs, pc, - relocation, r_type, - absolute)) + relocation + rel->r_addend, + r_type, absolute)) r =3D bfd_reloc_overflow; } break; @@ -2849,7 +2877,7 @@ riscv_elf_relocate_section (bfd *output_bfd, } =20 case R_RISCV_PCREL_HI20: - absolute =3D riscv_zero_pcrel_hi_reloc (rel, info, pc, relocation, + absolute =3D riscv_zero_pcrel_hi_reloc (rel, info, pc, &relocation, contents, howto); /* Update howto if relocation is changed. */ howto =3D riscv_elf_rtype_to_howto (input_bfd, diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-r= iscv-elf/ld-riscv-elf.exp index 669ac5d506d..0ee20255551 100644 --- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp +++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp @@ -131,6 +131,7 @@ if [istarget "riscv*-*-*"] { run_dump_test "pcrel-lo-addend-2a" run_dump_test "pcrel-lo-addend-2b" run_dump_test "pcrel-lo-addend-3a" + run_dump_test "pcrel-lo-addend-3a-emit-relocs" run_dump_test "pcrel-lo-addend-3b" run_dump_test "pcrel-lo-addend-3c" run_dump_test "code-model-medlow-01" diff --git a/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-3a-emit-relocs.d b/l= d/testsuite/ld-riscv-elf/pcrel-lo-addend-3a-emit-relocs.d new file mode 100644 index 00000000000..d5a667c3279 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/pcrel-lo-addend-3a-emit-relocs.d @@ -0,0 +1,26 @@ +#source: pcrel-lo-addend-3a.s +#as: -march=3Drv64i -mabi=3Dlp64 -mno-relax +#ld: -m[riscv_choose_lp64_emul] -Tpcrel-lo-addend-3.ld --emit-relocs +#objdump: -dr + +#... +Disassembly of section .text: + +0+900000000 <_start>: +.*:[ ]+[0-9a-f]+[ ]+lui[ ]+a5,0x2 +.*:[ ]+R_RISCV_HI20[ ]+\*ABS\*\+0x2000 +.*:[ ]+[0-9a-f]+[ ]+ld[ ]+a0,0\(a5\) # 2000 +.*:[ ]+R_RISCV_LO12_I[ ]+\*ABS\*\+0x2000 +.*:[ ]+[0-9a-f]+[ ]+ld[ ]+a0,4\(a5\) +.*:[ ]+R_RISCV_LO12_I[ ]+\*ABS\*\+0x2004 +.*:[ ]+[0-9a-f]+[ ]+lui[ ]+a5,0x2 +.*:[ ]+R_RISCV_HI20[ ]+\*ABS\*\+0x2004 +.*:[ ]+[0-9a-f]+[ ]+ld[ ]+a0,4\(a5\) # 2004 +.*:[ ]+R_RISCV_LO12_I[ ]+\*ABS\*\+0x2004 +.*:[ ]+[0-9a-f]+[ ]+ld[ ]+a0,8\(a5\) +.*:[ ]+R_RISCV_LO12_I[ ]+\*ABS\*\+0x2008 +.*:[ ]+[0-9a-f]+[ ]+lui[ ]+a5,0x1 +.*:[ ]+R_RISCV_HI20[ ]+\*ABS\*\+0x1008 +.*:[ ]+[0-9a-f]+[ ]+ld[ ]+a0,8\(a5\) # 1008 <_GLOBAL_OFFSET_TABLE_\+0x8> +.*:[ ]+R_RISCV_LO12_I[ ]+\*ABS\*\+0x1008 +#pass