[PATCH v1] LoongArch: Fix linker relaxation alignment
Xi Ruoyao
xry111@xry111.site
Sun Jun 21 04:40:13 GMT 2026
On Thu, 2026-06-18 at 14:29 +0800, mengqinggang wrote:
> When linking multiple objects, relaxation can cause alignment issues.
> Input section's output_offset is updated in relaxation without considering
> section alignment. Update section output_offset by align_opwer.
I can confirm this fixes the insufficient alignment of
trampoline_code_table in libffi.
Reviewed-by: Xi Ruoyao <xry111@xry111.site>
> ---
> bfd/elfnn-loongarch.c | 24 +++----------------
> ld/testsuite/ld-loongarch-elf/relax-align-1.d | 13 ++++++++++
> .../ld-loongarch-elf/relax-align-1a.s | 5 ++++
> .../ld-loongarch-elf/relax-align-1b.s | 3 +++
> ld/testsuite/ld-loongarch-elf/relax.exp | 4 ++++
> 5 files changed, 28 insertions(+), 21 deletions(-)
> create mode 100644 ld/testsuite/ld-loongarch-elf/relax-align-1.d
> create mode 100644 ld/testsuite/ld-loongarch-elf/relax-align-1a.s
> create mode 100644 ld/testsuite/ld-loongarch-elf/relax-align-1b.s
>
> 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..30b7c4cb293
> --- /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
> +
> +#...
> +.*[0|8]: 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"
--
Xi Ruoyao <xry111@xry111.site>
More information about the Binutils
mailing list