[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
nickc@sourceware.org
Thu Jul 16 08:34:20 GMT 2026
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e644656548fcaf27a01d4f9e59fb1116323730b0
commit e644656548fcaf27a01d4f9e59fb1116323730b0
Author: Xi Ruoyao <xry111@xry111.site>
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-*-*] {
More information about the Binutils-cvs
mailing list