Re: [PATCH 2/2] RISC-V: Check for conflicting extensions when the linker merges arch attributes
Nelson Chu via Binutils <[email protected]>
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <CAOvetVBXAbVe47w3wjOe7N8OGw=8yOzPYyDN+uyLKVnNPe5wFw@mail.gmail.com> |
Ummm, I linked a.o with c and b.o with d. It seems this isn't allowed already because we cannot link double-float with soft-float modules. So do we have any case where implicit extensions haven't been added for all input objects, requiring us to call riscv_parse_add_implicit_subsets for the merged string? If yes please also add the testcases. Thanks Nelson On Tue, Jul 7, 2026 at 9:26 AM Nelson Chu <[email protected]> wrote: > Oh, okay, I see the case: inputs with 'c' and inputs with 'd' will need > zcd after merging. Looks reasonable to call > riscv_parse_add_implicit_subsets for merged string, too. > > Thanks > Nelson > > On Tue, Jul 7, 2026 at 9:19 AM Nelson Chu <[email protected]> wrote: > >> >> >> On Mon, Jul 6, 2026 at 7:46 PM Ethan Y. C. Liang <[email protected]> >> wrote: >> >>> 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. >>> --- >>> bfd/elfxx-riscv.c | 8 ++++++++ >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01.d | 5 +++++ >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01.l | 2 ++ >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01a.s | 1 + >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01b.s | 1 + >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02.d | 5 +++++ >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02.l | 2 ++ >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02a.s | 1 + >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02b.s | 1 + >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03.d | 5 +++++ >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03.l | 2 ++ >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03a.s | 1 + >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03b.s | 1 + >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04.d | 5 +++++ >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04.l | 2 ++ >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04a.s | 1 + >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04b.s | 1 + >>> ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp | 4 ++++ >>> 18 files changed, 48 insertions(+) >>> create mode 100644 ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01.d >>> create mode 100644 ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01.l >>> create mode 100644 >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01a.s >>> create mode 100644 >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01b.s >>> create mode 100644 ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02.d >>> create mode 100644 ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02.l >>> create mode 100644 >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02a.s >>> create mode 100644 >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02b.s >>> create mode 100644 ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03.d >>> create mode 100644 ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03.l >>> create mode 100644 >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03a.s >>> create mode 100644 >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03b.s >>> create mode 100644 ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04.d >>> create mode 100644 ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04.l >>> create mode 100644 >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04a.s >>> create mode 100644 >>> ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04b.s >>> >>> diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c >>> index fa2f1759f31..128c0eda8c4 100644 >>> --- a/bfd/elfxx-riscv.c >>> +++ b/bfd/elfxx-riscv.c >>> @@ -3750,6 +3750,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; >>> + >>> >> >> Looks reasonable to call riscv_parse_check_conflicts for the merged >> architecture string. But do we need to call >> riscv_parse_add_implicit_subsets? Since I checked all current >> check_implicit_* functions (always/for_i/for_zcf/for_zcd), I think all >> implicit extensions should be added in the each input object already. >> >> Thanks >> Nelson >> >> >>> /* 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 >>> index 00000000000..f99677cb767 >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01.d >>> @@ -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 >>> index 00000000000..ad6d2630211 >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01.l >>> @@ -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 >>> index 00000000000..8f2a98f95f3 >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01a.s >>> @@ -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 >>> index 00000000000..a44b2a0d346 >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-01b.s >>> @@ -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 >>> index 00000000000..4fb1980c97d >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02.d >>> @@ -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 >>> index 00000000000..930e03123e1 >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02.l >>> @@ -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 >>> index 00000000000..3f79059d5d0 >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02a.s >>> @@ -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 >>> index 00000000000..95bfe1f6d9f >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-02b.s >>> @@ -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 >>> index 00000000000..def49c3fb3f >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03.d >>> @@ -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 >>> index 00000000000..d9075d0c30e >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03.l >>> @@ -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 >>> index 00000000000..f7f9ceb11f6 >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03a.s >>> @@ -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 >>> index 00000000000..f18129dc55d >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-03b.s >>> @@ -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 >>> index 00000000000..5445936df44 >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04.d >>> @@ -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 >>> index 00000000000..930e03123e1 >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04.l >>> @@ -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 >>> index 00000000000..e79c25b7828 >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04a.s >>> @@ -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 >>> index 00000000000..c7468e4e072 >>> --- /dev/null >>> +++ b/ld/testsuite/ld-riscv-elf/attr-merge-arch-failed-04b.s >>> @@ -0,0 +1 @@ >>> + .attribute arch, "rv32id_zcmp" >>> diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp >>> b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp >>> index 8e26ccff10a..57f3139c9f6 100644 >>> --- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp >>> +++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp >>> @@ -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" >>> -- >>> 2.54.0 >>> >>>