Skip to content

Commit 80a6bc7

Browse files
ylzsxtru
authored andcommitted
[lld][LoongArch] Check that the relocation addend is zero before applying relaxation to R_LARCH_GOT_PC_{HI20,LO12} (#151264)
Linker relaxation to R_LARCH_GOT_PC_{HI20,LO12} is only possible when the addend of the relocation is zero. Note: For `ld.bfd`, GOT references with non-zero addends will trigger an assert in LoongArch, but `lld` handles these cases without any errors. ``` ld.bfd: BFD (GNU Binutils) 2.44.0 assertion fail /usr/src/debug/binutils/binutils-gdb/bfd/elfnn-loongarch.c:4248 ``` (cherry picked from commit 4ec8503)
1 parent f207cb4 commit 80a6bc7

File tree

2 files changed

+51
-17
lines changed

2 files changed

+51
-17
lines changed

lld/ELF/Arch/LoongArch.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -809,10 +809,13 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
809809
// address.
810810
// Meanwhile skip undefined, preemptible and STT_GNU_IFUNC symbols, because
811811
// these symbols may be resolve in runtime.
812+
// Moreover, relaxation can only occur if the addends of both relocations are
813+
// zero for GOT references.
812814
if (rHi20.type == R_LARCH_GOT_PC_HI20 &&
813-
(!rHi20.sym->isDefined() || rHi20.sym->isPreemptible ||
814-
rHi20.sym->isGnuIFunc() ||
815-
(ctx.arg.isPic && !cast<Defined>(*rHi20.sym).section)))
815+
(!rHi20.sym || rHi20.sym != rLo12.sym || !rHi20.sym->isDefined() ||
816+
rHi20.sym->isPreemptible || rHi20.sym->isGnuIFunc() ||
817+
(ctx.arg.isPic && !cast<Defined>(*rHi20.sym).section) ||
818+
rHi20.addend != 0 || rLo12.addend != 0))
816819
return;
817820

818821
uint64_t dest = 0;

lld/test/ELF/loongarch-relax-pc-hi20-lo12.s

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
# REQUIRES: loongarch
2+
# RUN: rm -rf %t && split-file %s %t && cd %t
23

3-
# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax %s -o %t.32.o
4-
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s -o %t.64.o
4+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax a.s -o a.32.o
5+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax a.s -o a.64.o
56

6-
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.32.o -o %t.32
7-
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.64.o -o %t.64
8-
# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX %s
9-
# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX %s
7+
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 a.32.o -o a.32
8+
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 a.64.o -o a.64
9+
# RUN: llvm-objdump -td --no-show-raw-insn a.32 | FileCheck --check-prefixes=RELAX %s
10+
# RUN: llvm-objdump -td --no-show-raw-insn a.64 | FileCheck --check-prefixes=RELAX %s
1011

11-
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.32.o -shared -o %t.32s
12-
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.64.o -shared -o %t.64s
13-
# RUN: llvm-objdump -td --no-show-raw-insn %t.32s | FileCheck --check-prefixes=RELAX %s
14-
# RUN: llvm-objdump -td --no-show-raw-insn %t.64s | FileCheck --check-prefixes=RELAX %s
12+
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 a.32.o -shared -o a.32s
13+
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 a.64.o -shared -o a.64s
14+
# RUN: llvm-objdump -td --no-show-raw-insn a.32s | FileCheck --check-prefixes=RELAX %s
15+
# RUN: llvm-objdump -td --no-show-raw-insn a.64s | FileCheck --check-prefixes=RELAX %s
1516

16-
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 %t.32.o -o %t.32o
17-
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 %t.64.o -o %t.64o
18-
# RUN: llvm-objdump -td --no-show-raw-insn %t.32o | FileCheck --check-prefixes=NORELAX32 %s
19-
# RUN: llvm-objdump -td --no-show-raw-insn %t.64o | FileCheck --check-prefixes=NORELAX64 %s
17+
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 a.32.o -o a.32o
18+
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 a.64.o -o a.64o
19+
# RUN: llvm-objdump -td --no-show-raw-insn a.32o | FileCheck --check-prefixes=NORELAX32 %s
20+
# RUN: llvm-objdump -td --no-show-raw-insn a.64o | FileCheck --check-prefixes=NORELAX64 %s
2021

2122
# RELAX-LABEL: <_start>:
2223
## offset = 0x14000 - 0x10000 = 4096<<2
@@ -49,6 +50,25 @@
4950
# NORELAX64-NEXT: pcalau12i $a0, 1024
5051
# NORELAX64-NEXT: ld.d $a0, $a0, 8
5152

53+
54+
## GOT references with non-zero addends. No relaxation.
55+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax nonzero.s -o nonzero.32.o
56+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax nonzero.s -o nonzero.64.o
57+
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 nonzero.32.o -o nonzero.32
58+
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 nonzero.64.o -o nonzero.64
59+
# RUN: llvm-objdump -td --no-show-raw-insn nonzero.32 | FileCheck --check-prefixes=NONZERO32 %s
60+
# RUN: llvm-objdump -td --no-show-raw-insn nonzero.64 | FileCheck --check-prefixes=NONZERO64 %s
61+
62+
# NONZERO32-LABEL: <_start>:
63+
# NONZERO32-NEXT: 10000: pcalau12i $a0, 4
64+
# NONZERO32-NEXT: ld.w $a0, $a0, 8
65+
66+
# NONZERO64-LABEL: <_start>:
67+
# NONZERO64-NEXT: 10000: pcalau12i $a0, 4
68+
# NONZERO64-NEXT: ld.d $a0, $a0, 12
69+
70+
71+
#--- a.s
5272
.section .text
5373
.global _start
5474
_start:
@@ -60,3 +80,14 @@ _start:
6080
.section .data
6181
sym:
6282
.zero 4
83+
84+
85+
#--- nonzero.s
86+
.section .text
87+
.global _start
88+
_start:
89+
la.got $a0, sym+4
90+
91+
.section .data
92+
sym:
93+
.zero 4

0 commit comments

Comments
 (0)