156 lines
5.3 KiB
Diff
156 lines
5.3 KiB
Diff
From 2a9dd993a723726ccc6f5cfb4119ab6c8637c0d0 Mon Sep 17 00:00:00 2001
|
|
From: Xi Ruoyao <xry111@xry111.site>
|
|
Date: Tue, 16 Jan 2024 15:00:16 +0800
|
|
Subject: [PATCH 044/123] 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>
|
|
---
|
|
bfd/elfnn-loongarch.c | 31 +++++++++++--------
|
|
.../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(-)
|
|
create mode 100644 ld/testsuite/ld-loongarch-elf/pcala64.d
|
|
create mode 100644 ld/testsuite/ld-loongarch-elf/pcala64.s
|
|
|
|
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
|
|
index 8b71e836..b0ebe89e 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) \
|
|
@@ -3527,14 +3527,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;
|
|
|
|
@@ -3661,9 +3663,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;
|
|
|
|
@@ -3864,13 +3867,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:
|
|
@@ -3899,9 +3903,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 64e644d3..c81f20af 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 00000000..e0e9819d
|
|
--- /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 00000000..dfef0e2b
|
|
--- /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
|
|
--
|
|
2.33.0
|
|
|