[binutils-gdb/binutils-2_47-branch] [v2] LoongArch: only insert align section for ld -r if an input has R_LARCH_ALIGN or R_LARCH_RELAX
Nick Clifton via Binutils-cvs <[email protected]> Thu, 16 Jul 2026 08:34:20 +0000 (GMT)
| Newsgroups | gmane.comp.gnu.binutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e644656548fcaf27a01d4f9e59fb1116323730b0 commit e644656548fcaf27a01d4f9e59fb1116323730b0 Author: Xi Ruoyao <[email protected]> Date: Thu Jul 16 09:33:07 2026 +0100 [v2] LoongArch: only insert align section for ld -r if an input has R_LARCH_ALIGN or R_LARCH_RELAX Commit 8bf4b69718d4 ("LoongArch: Fix relaxation alignment with ld -r (PR 33236)") has broken the kernel modules on Debian sid. The expectation of the kernel is all the source files which would be linked into a module are compiled with -mno-relax so the module should not contain R_LARCH_ALIGN, thus the module loader rejects any module containing R_LARCH_ALIGN. To restore the correctness of the expectation, only insert the align section if an input has R_LARCH_ALIGN or R_LARCH_ALIGN (i.e. bytes may be removed from that input). Regardless of the kernel modules, it also does not make too much sense to bloat the output with NOPs and R_LARCH_ALIGN if no input ever contains R_LARCH_ALIGN and R_LARCH_ALIGN anyway. Diff: --- bfd/elfnn-loongarch.c | 31 ++++++++++++++++++++-- .../ld-loongarch-elf/relax-align-ld-r-norelax.d | 9 +++++++ ld/testsuite/ld-loongarch-elf/relax.exp | 1 + 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c index 03b0eb40ac7..4bdc3f26285 100644 --- a/bfd/elfnn-loongarch.c +++ b/bfd/elfnn-loongarch.c @@ -139,6 +139,10 @@ struct loongarch_elf_link_hash_table /* Pending relaxation (byte deletion) operations meant for roughly sequential access. */ splay_tree pending_delete_ops; + + /* If any input contains a reloc potentially removing bytes, i.e. + R_LARCH_ALIGN or R_LARCH_RELAX. */ + bool reloc_may_remove_bytes; }; struct loongarch_elf_section_data @@ -1109,10 +1113,26 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, const Elf_Internal_Rela *rel; asection *sreloc = NULL; + htab = loongarch_elf_hash_table (info); + if (bfd_link_relocatable (info)) - return true; + { + if (!htab->reloc_may_remove_bytes) + for (rel = relocs; rel < relocs + sec->reloc_count; rel++) + switch (ELFNN_R_TYPE (rel->r_info)) + { + case R_LARCH_ALIGN: + case R_LARCH_RELAX: + htab->reloc_may_remove_bytes = true; + return true; + default: + continue; + } + + /* No need for more checks with ld -r. */ + return true; + } - htab = loongarch_elf_hash_table (info); symtab_hdr = &elf_symtab_hdr (abfd); sym_hashes = elf_sym_hashes (abfd); @@ -7098,7 +7118,14 @@ elfNN_loongarch_size_aligns (bfd *output_bfd, (const char *, asection *), void (*layout_sections_again) (void)) { + + struct loongarch_elf_link_hash_table *htab; bool need_laying_out = false; + + htab = loongarch_elf_hash_table (info); + if (!htab->reloc_may_remove_bytes) + return true; + for (bfd *input_bfd = info->input_bfds; input_bfd != NULL; input_bfd = input_bfd->link.next) { diff --git a/ld/testsuite/ld-loongarch-elf/relax-align-ld-r-norelax.d b/ld/testsuite/ld-loongarch-elf/relax-align-ld-r-norelax.d new file mode 100644 index 00000000000..5f33b8b4d89 --- /dev/null +++ b/ld/testsuite/ld-loongarch-elf/relax-align-ld-r-norelax.d @@ -0,0 +1,9 @@ +#source: relax-align-ld-r.s +#as: -mno-relax +#ld: -r +#objdump: -Dr + +#failif +#... +.*R_LARCH_ALIGN.* +#... diff --git a/ld/testsuite/ld-loongarch-elf/relax.exp b/ld/testsuite/ld-loongarch-elf/relax.exp index bb8429ab515..bf4955f4c62 100644 --- a/ld/testsuite/ld-loongarch-elf/relax.exp +++ b/ld/testsuite/ld-loongarch-elf/relax.exp @@ -49,6 +49,7 @@ proc run_partial_linking_align_test {} { if [istarget loongarch*-*-*] { run_dump_test "relax-align-1" run_dump_test "relax-align-ld-r" + run_dump_test "relax-align-ld-r-norelax" } if [istarget loongarch64-*-*] {