-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[lld][LoongArch] Check that the relocation addend is zero before applying relaxation to R_LARCH_GOT_PC_{HI20,LO12} #151264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
We could relax codes when the addends of both relocations are 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 ```
@llvm/pr-subscribers-backend-loongarch @llvm/pr-subscribers-lld-elf Author: Zhaoxin Yang (ylzsx) ChangesWe could relax codes when the addends of both relocations are zero for R_LARCH_GOT_PC_{HI20,LO12}. Note: For
Full diff: https://github.com/llvm/llvm-project/pull/151264.diff 2 Files Affected:
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 15dcddb13baf7..a14553018fc36 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -809,10 +809,13 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
// address.
// Meanwhile skip undefined, preemptible and STT_GNU_IFUNC symbols, because
// these symbols may be resolve in runtime.
+ // Moreover, relaxation can only occur if the addends of both relocations are
+ // zero for GOT references.
if (rHi20.type == R_LARCH_GOT_PC_HI20 &&
- (!rHi20.sym->isDefined() || rHi20.sym->isPreemptible ||
- rHi20.sym->isGnuIFunc() ||
- (ctx.arg.isPic && !cast<Defined>(*rHi20.sym).section)))
+ (!rHi20.sym || rHi20.sym != rLo12.sym || !rHi20.sym->isDefined() ||
+ rHi20.sym->isPreemptible || rHi20.sym->isGnuIFunc() ||
+ (ctx.arg.isPic && !cast<Defined>(*rHi20.sym).section) ||
+ rHi20.addend != 0 || rLo12.addend != 0))
return;
uint64_t dest = 0;
diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
index a417d89e9fa2e..d5bec595bbfd7 100644
--- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
+++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
@@ -1,12 +1,12 @@
# REQUIRES: loongarch
-# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax %s -o %t.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax --defsym ELF32=1 %s -o %t.32.o
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s -o %t.64.o
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.32.o -o %t.32
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.64.o -o %t.64
-# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX %s
-# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX,RELAX32 %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX,RELAX64 %s
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.32.o -shared -o %t.32s
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.64.o -shared -o %t.64s
@@ -25,6 +25,11 @@
# RELAX-NEXT: pcaddi $a0, 4094
# RELAX-NEXT: pcaddi $a0, 4093
+# RELAX32-NEXT: pcalau12i $a0, 4
+# RELAX32-NEXT: ld.w $a0, $a0, 8
+# RELAX64-NEXT: pcalau12i $a0, 4
+# RELAX64-NEXT: ld.d $a0, $a0, 12
+
# NORELAX32-LABEL: <_start>:
## offset exceed range of pcaddi
## offset = 0x410000 - 0x10000: 0x400 pages, page offset 0
@@ -36,6 +41,8 @@
# NORELAX32-NEXT: addi.w $a0, $a0, 0
# NORELAX32-NEXT: pcalau12i $a0, 1024
# NORELAX32-NEXT: ld.w $a0, $a0, 4
+# NORELAX32-NEXT: pcalau12i $a0, 1024
+# NORELAX32-NEXT: ld.w $a0, $a0, 8
# NORELAX64-LABEL: <_start>:
## offset exceed range of pcaddi
@@ -48,6 +55,16 @@
# NORELAX64-NEXT: addi.d $a0, $a0, 0
# NORELAX64-NEXT: pcalau12i $a0, 1024
# NORELAX64-NEXT: ld.d $a0, $a0, 8
+# NORELAX64-NEXT: pcalau12i $a0, 1024
+# NORELAX64-NEXT: ld.d $a0, $a0, 12
+
+.macro ld dst, src1, src2
+.ifdef ELF32
+ld.w \dst, \src1, \src2
+.else
+ld.d \dst, \src1, \src2
+.endif
+.endm
.section .text
.global _start
@@ -57,6 +74,11 @@ _start:
la.pcrel $a0, sym
la.got $a0, sym
+ pcalau12i $a0, %got_pc_hi20(sym+4)
+ .reloc .-4, R_LARCH_RELAX, 0
+ ld $a0, $a0, %got_pc_lo12(sym+4)
+ .reloc .-4, R_LARCH_RELAX, 0
+
.section .data
sym:
.zero 4
|
@llvm/pr-subscribers-lld Author: Zhaoxin Yang (ylzsx) ChangesWe could relax codes when the addends of both relocations are zero for R_LARCH_GOT_PC_{HI20,LO12}. Note: For
Full diff: https://github.com/llvm/llvm-project/pull/151264.diff 2 Files Affected:
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 15dcddb13baf7..a14553018fc36 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -809,10 +809,13 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
// address.
// Meanwhile skip undefined, preemptible and STT_GNU_IFUNC symbols, because
// these symbols may be resolve in runtime.
+ // Moreover, relaxation can only occur if the addends of both relocations are
+ // zero for GOT references.
if (rHi20.type == R_LARCH_GOT_PC_HI20 &&
- (!rHi20.sym->isDefined() || rHi20.sym->isPreemptible ||
- rHi20.sym->isGnuIFunc() ||
- (ctx.arg.isPic && !cast<Defined>(*rHi20.sym).section)))
+ (!rHi20.sym || rHi20.sym != rLo12.sym || !rHi20.sym->isDefined() ||
+ rHi20.sym->isPreemptible || rHi20.sym->isGnuIFunc() ||
+ (ctx.arg.isPic && !cast<Defined>(*rHi20.sym).section) ||
+ rHi20.addend != 0 || rLo12.addend != 0))
return;
uint64_t dest = 0;
diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
index a417d89e9fa2e..d5bec595bbfd7 100644
--- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
+++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
@@ -1,12 +1,12 @@
# REQUIRES: loongarch
-# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax %s -o %t.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax --defsym ELF32=1 %s -o %t.32.o
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s -o %t.64.o
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.32.o -o %t.32
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.64.o -o %t.64
-# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX %s
-# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX,RELAX32 %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX,RELAX64 %s
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.32.o -shared -o %t.32s
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.64.o -shared -o %t.64s
@@ -25,6 +25,11 @@
# RELAX-NEXT: pcaddi $a0, 4094
# RELAX-NEXT: pcaddi $a0, 4093
+# RELAX32-NEXT: pcalau12i $a0, 4
+# RELAX32-NEXT: ld.w $a0, $a0, 8
+# RELAX64-NEXT: pcalau12i $a0, 4
+# RELAX64-NEXT: ld.d $a0, $a0, 12
+
# NORELAX32-LABEL: <_start>:
## offset exceed range of pcaddi
## offset = 0x410000 - 0x10000: 0x400 pages, page offset 0
@@ -36,6 +41,8 @@
# NORELAX32-NEXT: addi.w $a0, $a0, 0
# NORELAX32-NEXT: pcalau12i $a0, 1024
# NORELAX32-NEXT: ld.w $a0, $a0, 4
+# NORELAX32-NEXT: pcalau12i $a0, 1024
+# NORELAX32-NEXT: ld.w $a0, $a0, 8
# NORELAX64-LABEL: <_start>:
## offset exceed range of pcaddi
@@ -48,6 +55,16 @@
# NORELAX64-NEXT: addi.d $a0, $a0, 0
# NORELAX64-NEXT: pcalau12i $a0, 1024
# NORELAX64-NEXT: ld.d $a0, $a0, 8
+# NORELAX64-NEXT: pcalau12i $a0, 1024
+# NORELAX64-NEXT: ld.d $a0, $a0, 12
+
+.macro ld dst, src1, src2
+.ifdef ELF32
+ld.w \dst, \src1, \src2
+.else
+ld.d \dst, \src1, \src2
+.endif
+.endm
.section .text
.global _start
@@ -57,6 +74,11 @@ _start:
la.pcrel $a0, sym
la.got $a0, sym
+ pcalau12i $a0, %got_pc_hi20(sym+4)
+ .reloc .-4, R_LARCH_RELAX, 0
+ ld $a0, $a0, %got_pc_lo12(sym+4)
+ .reloc .-4, R_LARCH_RELAX, 0
+
.section .data
sym:
.zero 4
|
/cherry-pick 4ec8503 |
Error: Command failed due to missing milestone. |
/cherry-pick 4ec8503 |
/pull-request #151470 |
…ying relaxation to R_LARCH_GOT_PC_{HI20,LO12} (llvm#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)
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, butlld
handles these cases without any errors.