[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