[ELF] -r: Don't let a weaker offset-0 R_RISCV_ALIGN suppress ALIGN synthesis - #198147
Conversation
…nthesis PR llvm#151639 skipped synthesizing the section-start R_RISCV_ALIGN whenever any R_RISCV_ALIGN existed at offset 0, regardless of its alignment. This works with newer LLVM integrated assembler (llvm#150816). However, older MC and GNU Assembler as of today (https://sourceware.org/bugzilla/show_bug.cgi?id=33236) can carry a weak offset-0 R_RISCV_ALIGN (addend 2 => align 4) while its real alignment requirement comes from a `.option norelax` .balign, which emits no relocation. Fix the condition to not suppress synthesis. Link: https://sourceware.org/bugzilla/show_bug.cgi?id=33236#c4
|
@llvm/pr-subscribers-backend-risc-v @llvm/pr-subscribers-lld-elf Author: Fangrui Song (MaskRay) ChangesPR #151639 skipped synthesizing the section-start R_RISCV_ALIGN whenever However, older MC and GNU Assembler as of today Fix the condition to not suppress synthesis. Link: https://sourceware.org/bugzilla/show_bug.cgi?id=33236#c4 Full diff: https://github.com/llvm/llvm-project/pull/198147.diff 4 Files Affected:
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 4c9ea3deece2d..7de21a56cf297 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -980,12 +980,19 @@ bool LoongArch::synthesizeAlignForInput(uint64_t &dot, InputSection *sec,
}
}
} else if (sec->addralign > 4) {
- // If the alignment is > 4 and the section does not start with an ALIGN
- // relocation, synthesize one.
- bool hasAlignRel = llvm::any_of(rels, [](const RelTy &rel) {
- return rel.r_offset == 0 && rel.getType(false) == R_LARCH_ALIGN;
+ // If the alignment is > 4, synthesize an ALIGN unless an ALIGN relocation
+ // at offset 0 already guarantees `addralign`. Note: A weaker ALIGN at
+ // offset 0 from older assemblers do not suppress synthesis (e.g.
+ // `.p2align 2; .option norelax; nop; .p2align 3` does not suppress
+ // synthesized `.p2align 3`).
+ bool covered = llvm::any_of(rels, [&](const RelTy &rel) {
+ if (rel.r_offset != 0 || rel.getType(false) != R_LARCH_ALIGN)
+ return false;
+ if constexpr (RelTy::HasAddend)
+ return uint64_t(rel.r_addend) >= sec->addralign - 4;
+ return false;
});
- if (!hasAlignRel) {
+ if (!covered) {
synthesizedAligns.emplace_back(dot - baseSec->getVA(),
sec->addralign - 4);
dot += sec->addralign - 4;
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 0ded3bb859a37..94bab7a8e348f 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1133,12 +1133,19 @@ bool RISCV::synthesizeAlignForInput(uint64_t &dot, InputSection *sec,
}
}
} else if (sec->addralign >= 4) {
- // If the alignment is >= 4 and the section does not start with an ALIGN
- // relocation, synthesize one.
- bool hasAlignRel = llvm::any_of(rels, [](const RelTy &rel) {
- return rel.r_offset == 0 && rel.getType(false) == R_RISCV_ALIGN;
+ // If the alignment is > 4, synthesize an ALIGN unless an ALIGN relocation
+ // at offset 0 already guarantees `addralign`. Note: A weaker ALIGN at
+ // offset 0 from older assemblers do not suppress synthesis (e.g.
+ // `.p2align 2; .option norelax; nop; .p2align 3` does not suppress
+ // synthesized `.p2align 3`).
+ bool covered = llvm::any_of(rels, [&](const RelTy &rel) {
+ if (rel.r_offset != 0 || rel.getType(false) != R_RISCV_ALIGN)
+ return false;
+ if constexpr (RelTy::HasAddend)
+ return uint64_t(rel.r_addend) >= sec->addralign - 2;
+ return false;
});
- if (!hasAlignRel) {
+ if (!covered) {
synthesizedAligns.emplace_back(dot - baseSec->getVA(),
sec->addralign - 2);
dot += sec->addralign - 2;
diff --git a/lld/test/ELF/loongarch-relocatable-align.s b/lld/test/ELF/loongarch-relocatable-align.s
index c02007f9f719b..1147ee88d594d 100644
--- a/lld/test/ELF/loongarch-relocatable-align.s
+++ b/lld/test/ELF/loongarch-relocatable-align.s
@@ -92,6 +92,17 @@
# CHECKC-NEXT: <b0>:
# CHECKC-NEXT: c: addi.d $a0, $a1, 1
+## A weaker offset-0 ALIGN must not suppress synthesizing the stronger ALIGN required
+## by the subsequent .option norelax .balign 16 (which emits no relocation).
+## https://sourceware.org/bugzilla/show_bug.cgi?id=33236#c4
+# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax e.s -o e.o
+# RUN: ld.lld -r a.o e.o -o ae.ro
+# RUN: llvm-readelf -r ae.ro | FileCheck %s --check-prefix=CHECK3-REL
+
+# CHECK3-REL: Relocation section '.rela.text' {{.*}} contains 6 entries:
+# CHECK3-REL: R_LARCH_ALIGN{{ +}}c
+# CHECK3-REL-NEXT: R_LARCH_ALIGN{{ +}}4
+
#--- a.s
.globl _start
_start:
@@ -145,3 +156,17 @@ c0:
.balign 8
d0:
addi.d $a0, $a1, 5
+
+#--- e.s
+## Mimick `.balign 8` that generates a NOP padding associated with
+## R_LARCH_ALIGN (addend 4 => align 8) when assembled by an assembler
+## without the redundant-ALIGN optimization.
+.reloc ., R_LARCH_ALIGN, 4
+nop
+
+.option push
+.option norelax
+.balign 16
+e0:
+ .word 0x3a393837
+.option pop
diff --git a/lld/test/ELF/riscv-relocatable-align.s b/lld/test/ELF/riscv-relocatable-align.s
index 9cd59e96a7196..24b5b108a4790 100644
--- a/lld/test/ELF/riscv-relocatable-align.s
+++ b/lld/test/ELF/riscv-relocatable-align.s
@@ -93,6 +93,17 @@
# CHECK2-NEXT: <b0>:
# CHECK2-NEXT: e: 00158513 addi a0, a1, 0x1
+## A weaker offset-0 ALIGN must not suppress synthesizing the stronger ALIGN required
+## by the subsequent .option norelax .balign 8 (which emits no relocation).
+## https://sourceware.org/bugzilla/show_bug.cgi?id=33236#c4
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+c,+relax e.s -o ec.o
+# RUN: ld.lld -r ac.o ec.o -o ae.ro
+# RUN: llvm-readelf -r ae.ro | FileCheck %s --check-prefix=CHECK3-REL
+
+# CHECK3-REL: Relocation section '.rela.text' {{.*}} contains 4 entries:
+# CHECK3-REL: R_RISCV_ALIGN{{ +}}6
+# CHECK3-REL-NEXT: R_RISCV_ALIGN{{ +}}2
+
#--- a.s
.globl _start
_start:
@@ -138,3 +149,16 @@ c0:
.balign 4
d0:
addi a0, a1, 2
+
+#--- e.s
+## Mimick `.balign 4` that generates 2 NOP padding bytes associated with
+## R_RISCV_ALIGN (addend 2) when assembled by old MC.
+.reloc ., R_RISCV_ALIGN, 2
+c.nop
+
+.option push
+.option norelax
+.balign 8
+e0:
+ .word 0x3a393837
+.option pop
|
|
@llvm/pr-subscribers-lld Author: Fangrui Song (MaskRay) ChangesPR #151639 skipped synthesizing the section-start R_RISCV_ALIGN whenever However, older MC and GNU Assembler as of today Fix the condition to not suppress synthesis. Link: https://sourceware.org/bugzilla/show_bug.cgi?id=33236#c4 Full diff: https://github.com/llvm/llvm-project/pull/198147.diff 4 Files Affected:
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 4c9ea3deece2d..7de21a56cf297 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -980,12 +980,19 @@ bool LoongArch::synthesizeAlignForInput(uint64_t &dot, InputSection *sec,
}
}
} else if (sec->addralign > 4) {
- // If the alignment is > 4 and the section does not start with an ALIGN
- // relocation, synthesize one.
- bool hasAlignRel = llvm::any_of(rels, [](const RelTy &rel) {
- return rel.r_offset == 0 && rel.getType(false) == R_LARCH_ALIGN;
+ // If the alignment is > 4, synthesize an ALIGN unless an ALIGN relocation
+ // at offset 0 already guarantees `addralign`. Note: A weaker ALIGN at
+ // offset 0 from older assemblers do not suppress synthesis (e.g.
+ // `.p2align 2; .option norelax; nop; .p2align 3` does not suppress
+ // synthesized `.p2align 3`).
+ bool covered = llvm::any_of(rels, [&](const RelTy &rel) {
+ if (rel.r_offset != 0 || rel.getType(false) != R_LARCH_ALIGN)
+ return false;
+ if constexpr (RelTy::HasAddend)
+ return uint64_t(rel.r_addend) >= sec->addralign - 4;
+ return false;
});
- if (!hasAlignRel) {
+ if (!covered) {
synthesizedAligns.emplace_back(dot - baseSec->getVA(),
sec->addralign - 4);
dot += sec->addralign - 4;
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 0ded3bb859a37..94bab7a8e348f 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1133,12 +1133,19 @@ bool RISCV::synthesizeAlignForInput(uint64_t &dot, InputSection *sec,
}
}
} else if (sec->addralign >= 4) {
- // If the alignment is >= 4 and the section does not start with an ALIGN
- // relocation, synthesize one.
- bool hasAlignRel = llvm::any_of(rels, [](const RelTy &rel) {
- return rel.r_offset == 0 && rel.getType(false) == R_RISCV_ALIGN;
+ // If the alignment is > 4, synthesize an ALIGN unless an ALIGN relocation
+ // at offset 0 already guarantees `addralign`. Note: A weaker ALIGN at
+ // offset 0 from older assemblers do not suppress synthesis (e.g.
+ // `.p2align 2; .option norelax; nop; .p2align 3` does not suppress
+ // synthesized `.p2align 3`).
+ bool covered = llvm::any_of(rels, [&](const RelTy &rel) {
+ if (rel.r_offset != 0 || rel.getType(false) != R_RISCV_ALIGN)
+ return false;
+ if constexpr (RelTy::HasAddend)
+ return uint64_t(rel.r_addend) >= sec->addralign - 2;
+ return false;
});
- if (!hasAlignRel) {
+ if (!covered) {
synthesizedAligns.emplace_back(dot - baseSec->getVA(),
sec->addralign - 2);
dot += sec->addralign - 2;
diff --git a/lld/test/ELF/loongarch-relocatable-align.s b/lld/test/ELF/loongarch-relocatable-align.s
index c02007f9f719b..1147ee88d594d 100644
--- a/lld/test/ELF/loongarch-relocatable-align.s
+++ b/lld/test/ELF/loongarch-relocatable-align.s
@@ -92,6 +92,17 @@
# CHECKC-NEXT: <b0>:
# CHECKC-NEXT: c: addi.d $a0, $a1, 1
+## A weaker offset-0 ALIGN must not suppress synthesizing the stronger ALIGN required
+## by the subsequent .option norelax .balign 16 (which emits no relocation).
+## https://sourceware.org/bugzilla/show_bug.cgi?id=33236#c4
+# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax e.s -o e.o
+# RUN: ld.lld -r a.o e.o -o ae.ro
+# RUN: llvm-readelf -r ae.ro | FileCheck %s --check-prefix=CHECK3-REL
+
+# CHECK3-REL: Relocation section '.rela.text' {{.*}} contains 6 entries:
+# CHECK3-REL: R_LARCH_ALIGN{{ +}}c
+# CHECK3-REL-NEXT: R_LARCH_ALIGN{{ +}}4
+
#--- a.s
.globl _start
_start:
@@ -145,3 +156,17 @@ c0:
.balign 8
d0:
addi.d $a0, $a1, 5
+
+#--- e.s
+## Mimick `.balign 8` that generates a NOP padding associated with
+## R_LARCH_ALIGN (addend 4 => align 8) when assembled by an assembler
+## without the redundant-ALIGN optimization.
+.reloc ., R_LARCH_ALIGN, 4
+nop
+
+.option push
+.option norelax
+.balign 16
+e0:
+ .word 0x3a393837
+.option pop
diff --git a/lld/test/ELF/riscv-relocatable-align.s b/lld/test/ELF/riscv-relocatable-align.s
index 9cd59e96a7196..24b5b108a4790 100644
--- a/lld/test/ELF/riscv-relocatable-align.s
+++ b/lld/test/ELF/riscv-relocatable-align.s
@@ -93,6 +93,17 @@
# CHECK2-NEXT: <b0>:
# CHECK2-NEXT: e: 00158513 addi a0, a1, 0x1
+## A weaker offset-0 ALIGN must not suppress synthesizing the stronger ALIGN required
+## by the subsequent .option norelax .balign 8 (which emits no relocation).
+## https://sourceware.org/bugzilla/show_bug.cgi?id=33236#c4
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+c,+relax e.s -o ec.o
+# RUN: ld.lld -r ac.o ec.o -o ae.ro
+# RUN: llvm-readelf -r ae.ro | FileCheck %s --check-prefix=CHECK3-REL
+
+# CHECK3-REL: Relocation section '.rela.text' {{.*}} contains 4 entries:
+# CHECK3-REL: R_RISCV_ALIGN{{ +}}6
+# CHECK3-REL-NEXT: R_RISCV_ALIGN{{ +}}2
+
#--- a.s
.globl _start
_start:
@@ -138,3 +149,16 @@ c0:
.balign 4
d0:
addi a0, a1, 2
+
+#--- e.s
+## Mimick `.balign 4` that generates 2 NOP padding bytes associated with
+## R_RISCV_ALIGN (addend 2) when assembled by old MC.
+.reloc ., R_RISCV_ALIGN, 2
+c.nop
+
+.option push
+.option norelax
+.balign 8
+e0:
+ .word 0x3a393837
+.option pop
|
wangleiat
left a comment
There was a problem hiding this comment.
LGTM from the LoongArch side, thanks.
LoongArch has the same issue as RISC-V for PR 33236 [1]. Section alignment can't be adjusted for objects generated by ld -r. If previous sections are relaxed, the subsequent section maybe misaligned. To fix this, add an align section and an align relocation before each section when ld -r. And change the section alignment to 4 to disable the default section start address calculation. ld.lld has fixed this issue in the following two patches [2] [3]. [1] https://sourceware.org/bugzilla/show_bug.cgi?id=33236 [2] llvm/llvm-project#151639 [3] llvm/llvm-project#198147
PR #151639 skipped synthesizing the section-start R_RISCV_ALIGN whenever
any R_RISCV_ALIGN existed at offset 0, regardless of its alignment. This
works with newer LLVM integrated assembler (#150816).
However, older MC and GNU Assembler as of today
(https://sourceware.org/bugzilla/show_bug.cgi?id=33236) can carry a weak
offset-0 R_RISCV_ALIGN (addend 2 => align 4) while its real alignment
requirement comes from a
.option norelax.balign, which emits norelocation.
Fix the condition to not suppress synthesis.
Link: https://sourceware.org/bugzilla/show_bug.cgi?id=33236#c4