[binutils-gdb/binutils-2_42-branch] LoongArch: Adapt R_LARCH_{PCALA, GOT, TLS_IE, TLS_DESC}64_* handling per psABI v2.30

liu & zhensong liuzhensong@sourceware.org
Thu Jan 18 11:56:16 GMT 2024


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1939e195eb1301ca36ee3f9478168dfe3a70f998

commit 1939e195eb1301ca36ee3f9478168dfe3a70f998
Author: Xi Ruoyao <xry111@xry111.site>
Date:   Tue Jan 16 15:00:16 2024 +0800

    LoongArch: Adapt R_LARCH_{PCALA,GOT,TLS_IE,TLS_DESC}64_* handling per psABI v2.30
    
    In LoongArch psABI v2.30, an offset (-8 for LO20 and -12 for HI12)
    should be applied on PC for these reloc types to avoid wrong relocation
    when the instruction sequence crosses a page boundary.
    
    The lld linker has already adapted the change.  Make it for the bfd
    linker too.
    
    Link: https://github.com/loongson/la-abi-specs/releases/v2.30
    Link: https://github.com/loongson-community/discussions/issues/17
    Link: https://github.com/llvm/llvm-project/pull/73387
    Signed-off-by: Xi Ruoyao <xry111@xry111.site>

Diff:
---
 bfd/elfnn-loongarch.c                              | 31 +++++++++++++---------
 ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp |  1 +
 ld/testsuite/ld-loongarch-elf/pcala64.d            | 15 +++++++++++
 ld/testsuite/ld-loongarch-elf/pcala64.s            |  8 ++++++
 4 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 7905cdf7564..64ccc559952 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -2529,7 +2529,7 @@ loongarch_reloc_is_fatal (struct bfd_link_info *info,
   ({							\
     bfd_vma __lo = (relocation & (bfd_vma)0xfff);	\
     relocation = (relocation & ~(bfd_vma)0xfff)		\
-		  - (pc & ~(bfd_vma)0xfff);		\
+		  - ((pc) & ~(bfd_vma)0xfff);		\
     if (__lo > 0x7ff)					\
 	relocation += (0x1000 - 0x100000000);		\
     if (relocation & 0x80000000)			\
@@ -3534,14 +3534,16 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	    }
 	  break;
 
-	case R_LARCH_PCALA64_LO20:
 	case R_LARCH_PCALA64_HI12:
+	  pc -= 4;
+	  /* Fall through.  */
+	case R_LARCH_PCALA64_LO20:
 	  if (h && h->plt.offset != MINUS_ONE)
 	    relocation = sec_addr (plt) + h->plt.offset;
 	  else
 	    relocation += rel->r_addend;
 
-	  RELOCATE_CALC_PC64_HI32 (relocation, pc);
+	  RELOCATE_CALC_PC64_HI32 (relocation, pc - 8);
 
 	  break;
 
@@ -3668,9 +3670,10 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	      relocation = got_off + sec_addr (got);
 	    }
 
-	  if (r_type == R_LARCH_GOT64_PC_HI12
-	      || r_type == R_LARCH_GOT64_PC_LO20)
-	    RELOCATE_CALC_PC64_HI32 (relocation, pc);
+	  if (r_type == R_LARCH_GOT64_PC_HI12)
+	    RELOCATE_CALC_PC64_HI32 (relocation, pc - 12);
+	  else if (r_type == R_LARCH_GOT64_PC_LO20)
+	    RELOCATE_CALC_PC64_HI32 (relocation, pc - 8);
 
 	  break;
 
@@ -3871,13 +3874,14 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	    /* Use both TLS_GD and TLS_DESC.  */
 	    if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_GDESC))
 	      relocation += 2 * GOT_ENTRY_SIZE;
-	  }
 
-	    if (r_type == R_LARCH_TLS_DESC64_PC_LO20
-		|| r_type == R_LARCH_TLS_DESC64_PC_HI12)
-	      RELOCATE_CALC_PC64_HI32 (relocation, pc);
+	    if (r_type == R_LARCH_TLS_DESC64_PC_LO20)
+	      RELOCATE_CALC_PC64_HI32 (relocation, pc - 8);
+	    else if (r_type == R_LARCH_TLS_DESC64_PC_HI12)
+	      RELOCATE_CALC_PC64_HI32 (relocation, pc - 12);
 
 	    break;
+	  }
 
 	case R_LARCH_TLS_DESC_LD:
 	case R_LARCH_TLS_DESC_CALL:
@@ -3906,9 +3910,10 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	  else if (GOT_TLS_GD_ANY_P (tls_type) && (tls_type & GOT_TLS_IE))
 	    relocation += 2 * GOT_ENTRY_SIZE;
 
-	  if (r_type == R_LARCH_TLS_IE64_PC_LO20
-	      || r_type == R_LARCH_TLS_IE64_PC_HI12)
-	    RELOCATE_CALC_PC64_HI32 (relocation, pc);
+	  if (r_type == R_LARCH_TLS_IE64_PC_LO20)
+	    RELOCATE_CALC_PC64_HI32 (relocation, pc - 8);
+	  else if (r_type == R_LARCH_TLS_IE64_PC_HI12)
+	    RELOCATE_CALC_PC64_HI32 (relocation, pc - 12);
 
 	  break;
 
diff --git a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
index 29560073abb..1b5994c7d84 100644
--- a/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
+++ b/ld/testsuite/ld-loongarch-elf/ld-loongarch-elf.exp
@@ -33,6 +33,7 @@ if [istarget "loongarch64-*-*"] {
     run_dump_test "disas-jirl"
     run_dump_test "local-ifunc-reloc"
     run_dump_test "anno-sym"
+    run_dump_test "pcala64"
 }
 
 if [istarget "loongarch32-*-*"] {
diff --git a/ld/testsuite/ld-loongarch-elf/pcala64.d b/ld/testsuite/ld-loongarch-elf/pcala64.d
new file mode 100644
index 00000000000..e0e9819d387
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/pcala64.d
@@ -0,0 +1,15 @@
+#ld: -Ttext=0x180000ff8 -Tdata=0x1000000000
+#objdump: -d
+
+.*:[    ]+file format .*
+
+
+Disassembly of section .text:
+
+0000000180000ff8 <_start>:
+[ 	]+180000ff8:[ 	]+1b000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+-524288
+[ 	]+180000ffc:[ 	]+02c0000c[ 	]+li.d[ 	]+\$t0,[ 	]+0
+[ 	]+180001000:[ 	]+160001ec[ 	]+lu32i.d[ 	]+\$t0,[ 	]+15
+[ 	]+180001004:[ 	]+0300018c[ 	]+lu52i.d[ 	]+\$t0,[ 	]+\$t0,[ 	]+0
+[ 	]+180001008:[ 	]+0010b084[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$t0
+[ 	]+18000100c:[ 	]+4c000020[ 	]+ret
diff --git a/ld/testsuite/ld-loongarch-elf/pcala64.s b/ld/testsuite/ld-loongarch-elf/pcala64.s
new file mode 100644
index 00000000000..dfef0e2b7b7
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/pcala64.s
@@ -0,0 +1,8 @@
+.text
+.globl _start
+_start:
+	la.pcrel $a0, $t0, sym
+	jr $ra
+.data
+sym:
+	.dword 0


More information about the Binutils-cvs mailing list