From: Xi Ruoyao Date: Tue, 14 Jul 2026 15:51:32 +0000 (+0800) Subject: LoongArch: only insert align section for ld -r if an input has R_LARCH_ALIGN or R_LAR... X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a4481c8ff808e7237b99815d84b0d4c06ded6124;p=thirdparty%2Fbinutils-gdb.git 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. Signed-off-by: Xi Ruoyao --- 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-*-*] {