]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
RISC-V: Check for conflicting extensions when the linker merges arch attributes
authorEthan Y. C. Liang <ycl669@andestech.com>
Mon, 6 Jul 2026 11:44:28 +0000 (19:44 +0800)
committerNelson Chu <nelson.chu@sifive.com>
Thu, 9 Jul 2026 00:56:46 +0000 (08:56 +0800)
The linker validates the arch of each input when parsing it, but never
checks the merged arch as a whole, so conflicting extensions could
silently slip through.  The merge can even imply extensions that
neither input implies alone, e.g. `c' from one input and `d' from
another imply `zcd', which conflicts with `zcmp'.

After merging the input archs, add the implicit extensions to the
merged arch, then run the conflict checks on it and reject the merge
if any conflict is found.  Add tests for such merges.

18 files changed:
bfd/elfxx-riscv.c
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01.d [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01.l [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01a.s [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01b.s [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02.d [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02.l [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02a.s [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02b.s [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03.d [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03.l [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03a.s [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03b.s [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04.d [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04.l [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04a.s [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04b.s [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp

index 8fc4e1408f9a09ed1fc56b7f8aa857a4e5723235..c3cb4197ba800e99bb841605df14a12d9e2966d7 100644 (file)
@@ -3814,6 +3814,14 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch,
       goto cleanup;
     }
 
+  /* Add the implicit subsets implied by the merged subset list, then
+     check if the result is conflicting.  */
+  riscv_parse_subset_t riscv_rps_ld_merged =
+    {&merged_subsets, _bfd_error_handler, &xlen_in, NULL, false};
+  riscv_parse_add_implicit_subsets (&riscv_rps_ld_merged);
+  if (!riscv_parse_check_conflicts (&riscv_rps_ld_merged))
+    goto cleanup;
+
   /* Free the previous merged_arch_str which called xmalloc.  */
   free (merged_arch_str);
 
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01.d b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01.d
new file mode 100644 (file)
index 0000000..f99677c
--- /dev/null
@@ -0,0 +1,5 @@
+#source: attr-merge-arch-failed-01a.s
+#source: attr-merge-arch-failed-01b.s
+#as: -mabi=ilp32
+#ld: -r -m[riscv_choose_ilp32_emul]
+#error_output: attr-merge-arch-failed-01.l
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01.l b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01.l
new file mode 100644 (file)
index 0000000..ad6d263
--- /dev/null
@@ -0,0 +1,2 @@
+.*: `zfinx' conflicts with the `f/d/q/zfh/zfhmin' extension
+.*: failed to merge target specific data of file .*
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01a.s b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01a.s
new file mode 100644 (file)
index 0000000..8f2a98f
--- /dev/null
@@ -0,0 +1 @@
+       .attribute arch, "rv32i_zfinx"
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01b.s b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01b.s
new file mode 100644 (file)
index 0000000..a44b2a0
--- /dev/null
@@ -0,0 +1 @@
+       .attribute arch, "rv32if"
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02.d b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02.d
new file mode 100644 (file)
index 0000000..4fb1980
--- /dev/null
@@ -0,0 +1,5 @@
+#source: attr-merge-arch-failed-02a.s
+#source: attr-merge-arch-failed-02b.s
+#as: -mabi=ilp32
+#ld: -r -m[riscv_choose_ilp32_emul]
+#error_output: attr-merge-arch-failed-02.l
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02.l b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02.l
new file mode 100644 (file)
index 0000000..930e031
--- /dev/null
@@ -0,0 +1,2 @@
+.*: zcmp' is incompatible with `d' and `c', or `zcd' extension
+.*: failed to merge target specific data of file .*
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02a.s b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02a.s
new file mode 100644 (file)
index 0000000..3f79059
--- /dev/null
@@ -0,0 +1 @@
+       .attribute arch, "rv32i_zcmp"
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02b.s b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02b.s
new file mode 100644 (file)
index 0000000..95bfe1f
--- /dev/null
@@ -0,0 +1 @@
+       .attribute arch, "rv32i_zcd"
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03.d b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03.d
new file mode 100644 (file)
index 0000000..def49c3
--- /dev/null
@@ -0,0 +1,5 @@
+#source: attr-merge-arch-failed-03a.s
+#source: attr-merge-arch-failed-03b.s
+#as: -mabi=ilp32
+#ld: -r -m[riscv_choose_ilp32_emul]
+#error_output: attr-merge-arch-failed-03.l
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03.l b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03.l
new file mode 100644 (file)
index 0000000..d9075d0
--- /dev/null
@@ -0,0 +1,2 @@
+.*: `zclsd' conflicts with the `c\+f'/`zcf' extension
+.*: failed to merge target specific data of file .*
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03a.s b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03a.s
new file mode 100644 (file)
index 0000000..f7f9ceb
--- /dev/null
@@ -0,0 +1 @@
+       .attribute arch, "rv32i_zclsd"
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03b.s b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03b.s
new file mode 100644 (file)
index 0000000..f18129d
--- /dev/null
@@ -0,0 +1 @@
+       .attribute arch, "rv32i_zcf"
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04.d b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04.d
new file mode 100644 (file)
index 0000000..5445936
--- /dev/null
@@ -0,0 +1,5 @@
+#source: attr-merge-arch-failed-04a.s
+#source: attr-merge-arch-failed-04b.s
+#as: -mabi=ilp32
+#ld: -r -m[riscv_choose_ilp32_emul]
+#error_output: attr-merge-arch-failed-04.l
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04.l b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04.l
new file mode 100644 (file)
index 0000000..930e031
--- /dev/null
@@ -0,0 +1,2 @@
+.*: zcmp' is incompatible with `d' and `c', or `zcd' extension
+.*: failed to merge target specific data of file .*
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04a.s b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04a.s
new file mode 100644 (file)
index 0000000..e79c25b
--- /dev/null
@@ -0,0 +1 @@
+       .attribute arch, "rv32ic"
diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04b.s b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04b.s
new file mode 100644 (file)
index 0000000..c7468e4
--- /dev/null
@@ -0,0 +1 @@
+       .attribute arch, "rv32id_zcmp"
index 8e26ccff10a2523187c5bb32fb36eb68ebf23dbb..57f3139c9f64a228793dbc0daf9cb9ccffac4083 100644 (file)
@@ -157,6 +157,10 @@ if [istarget "riscv*-*-*"] {
     run_dump_test "attr-merge-arch-01"
     run_dump_test "attr-merge-arch-02"
     run_dump_test "attr-merge-arch-03"
+    run_dump_test "attr-merge-arch-failed-01"
+    run_dump_test "attr-merge-arch-failed-02"
+    run_dump_test "attr-merge-arch-failed-03"
+    run_dump_test "attr-merge-arch-failed-04"
     run_dump_test "attr-merge-strict-align-01"
     run_dump_test "attr-merge-strict-align-02"
     run_dump_test "attr-merge-strict-align-03"