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 <CAOvetVBT=ZA_8Zg4cd1k1X_TDqzgvEL5uFrJnOD2NKT3r8Z0YQ@mail.gmail.com>
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
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.