[binutils-gdb] LoongArch: Fix linker relaxation alignment
liu zhensong
liuzhensong@sourceware.org
Mon Jul 6 06:13:04 GMT 2026
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7858cadd335b3ffbc8e0250c0c180253d9f09489
commit 7858cadd335b3ffbc8e0250c0c180253d9f09489
Author: mengqinggang <mengqinggang@loongson.cn>
Date: Tue Jun 16 19:10:26 2026 +0800
LoongArch: Fix linker relaxation alignment
When linking multiple objects, relaxation can cause alignment issues.
Input section's output_offset is updated in relaxation without considering
alignment. Update section output_offset by align_opwer.
Diff:
---
bfd/elfnn-loongarch.c | 24 +++---------------------
ld/testsuite/ld-loongarch-elf/relax-align-1.d | 13 +++++++++++++
ld/testsuite/ld-loongarch-elf/relax-align-1a.s | 5 +++++
ld/testsuite/ld-loongarch-elf/relax-align-1b.s | 3 +++
ld/testsuite/ld-loongarch-elf/relax.exp | 4 ++++
5 files changed, 28 insertions(+), 21 deletions(-)
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 9d9c68664bb..b7af2041238 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -5725,11 +5725,6 @@ loongarch_relax_pcala_addi (bfd *abfd, asection *sec, asection *sym_sec,
uint32_t add = bfd_get (32, abfd, contents + rel_lo->r_offset);
uint32_t rd = LARCH_GET_RD (pca);
- /* This section's output_offset need to subtract the bytes of instructions
- relaxed by the previous sections, so it needs to be updated beforehand.
- size_input_section already took care of updating it after relaxation,
- so we additionally update once here. */
- sec->output_offset = sec->output_section->size;
bfd_vma pc = sec_addr (sec)
+ loongarch_calc_relaxed_addr (info, rel_hi->r_offset);
if (sym_sec == sec)
@@ -5790,11 +5785,6 @@ loongarch_relax_call36 (bfd *abfd, asection *sec, asection *sym_sec,
uint32_t jirl = bfd_get (32, abfd, contents + rel->r_offset + 4);
uint32_t rd = LARCH_GET_RD (jirl);
- /* This section's output_offset need to subtract the bytes of instructions
- relaxed by the previous sections, so it needs to be updated beforehand.
- size_input_section already took care of updating it after relaxation,
- so we additionally update once here. */
- sec->output_offset = sec->output_section->size;
bfd_vma pc = sec_addr (sec)
+ loongarch_calc_relaxed_addr (info, rel->r_offset);
if (sym_sec == sec)
@@ -5851,11 +5841,6 @@ loongarch_relax_pcala_ld (bfd *abfd, asection *sec,
bool *again ATTRIBUTE_UNUSED,
bfd_vma max_alignment)
{
- /* This section's output_offset need to subtract the bytes of instructions
- relaxed by the previous sections, so it needs to be updated beforehand.
- size_input_section already took care of updating it after relaxation,
- so we additionally update once here. */
- sec->output_offset = sec->output_section->size;
bfd_vma pc = sec_addr (sec)
+ loongarch_calc_relaxed_addr (info, rel_hi->r_offset);
if (sym_sec == sec)
@@ -6008,11 +5993,6 @@ loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec,
uint32_t add = bfd_get (32, abfd, contents + rel_lo->r_offset);
uint32_t rd = LARCH_GET_RD (pca);
- /* This section's output_offset need to subtract the bytes of instructions
- relaxed by the previous sections, so it needs to be updated beforehand.
- size_input_section already took care of updating it after relaxation,
- so we additionally update once here. */
- sec->output_offset = sec->output_section->size;
bfd_vma pc = sec_addr (sec)
+ loongarch_calc_relaxed_addr (info, rel_hi->r_offset);
if (sym_sec == sec)
@@ -6187,7 +6167,9 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
so we additionally update once here. */
/* update before tls trans and relax, or may cause same pcadd_hi20 address. */
- sec->output_offset = sec->output_section->size;
+
+ sec->output_offset = align_power (sec->output_section->size,
+ sec->alignment_power);
for (unsigned int i = 0; i < sec->reloc_count; i++)
{
diff --git a/ld/testsuite/ld-loongarch-elf/relax-align-1.d b/ld/testsuite/ld-loongarch-elf/relax-align-1.d
new file mode 100644
index 00000000000..5681efb16d1
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-align-1.d
@@ -0,0 +1,13 @@
+#source: relax-align-1a.s
+#source: relax-align-1b.s
+#ld: -e0
+#objdump: -d
+
+#...
+.*: 54000400 bl 4.*<f>
+#...
+.*[0|8]: 02c001ac addi.d \$t0, \$t1, 0
+#...
+.*0: 02c005ac addi.d \$t0, \$t1, 1
+#...
+.*0: 02c005ac addi.d \$t0, \$t1, 1
diff --git a/ld/testsuite/ld-loongarch-elf/relax-align-1a.s b/ld/testsuite/ld-loongarch-elf/relax-align-1a.s
new file mode 100644
index 00000000000..2b7f3ecb6be
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-align-1a.s
@@ -0,0 +1,5 @@
+.text
+ call f
+f:
+ .align 3
+ addi.d $t0, $t1, 0
diff --git a/ld/testsuite/ld-loongarch-elf/relax-align-1b.s b/ld/testsuite/ld-loongarch-elf/relax-align-1b.s
new file mode 100644
index 00000000000..2ed480a6c1b
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-align-1b.s
@@ -0,0 +1,3 @@
+addi.d $t0, $t1, 1
+.align 4
+addi.d $t0, $t1, 1
diff --git a/ld/testsuite/ld-loongarch-elf/relax.exp b/ld/testsuite/ld-loongarch-elf/relax.exp
index 7c32a65244c..31787a93967 100644
--- a/ld/testsuite/ld-loongarch-elf/relax.exp
+++ b/ld/testsuite/ld-loongarch-elf/relax.exp
@@ -46,6 +46,10 @@ proc run_partial_linking_align_test {} {
}
}
+if [istarget loongarch*-*-*] {
+ run_dump_test "relax-align-1"
+}
+
if [istarget loongarch64-*-*] {
if [isbuild loongarch64-*-*] {
run_dump_test "relax-align-ignore-start"
More information about the Binutils-cvs
mailing list