[PATCH 2/2] RISC-V: Check for conflicting extensions when the linker merges arch attributes

Ethan Y. C. Liang ycl669@andestech.com
Thu Jul 9 03:26:39 GMT 2026


Thanks for your commit!

Ethan


On Thu, Jul 09, 2026 at 09:10:24AM +0800, Nelson Chu wrote:
> Sorry, forgot to commit.  Committed, thanks.
> 
> Nelson
> 
> On Wed, Jul 8, 2026 at 11:07 AM Nelson Chu <nelson.chu@sifive.com<mailto:nelson.chu@sifive.com>> wrote:
> 
> 
> On Tue, Jul 7, 2026 at 10:05 AM Ethan Y. C. Liang <ycl669@andestech.com<mailto:ycl669@andestech.com>> wrote:
> I think you can try testing it with the soft-float ABI to avoid the linker error you ran into.
> 
> I meant if we already got an error, then why not just call check confflict without calling riscv_parse_add_implicit_subsets, since adding implicits may waste link time, but whatever...
> 
> 
> You can also refer to the attr-merge-arch-failed-04 test case that I added.
> 
> Okay, the attr-merge-arch-failed-04 looks reasonable since we only check if zcmp and zcd exist for now, without the riscv_parse_add_implicit_subsets, zcd won't be added so the testcase won't be expected failed.
> 
> Thanks
> Nelson
> 
> Ethan
> 
> On Tue, Jul 07, 2026 at 09:51:22AM +0800, Nelson Chu wrote:
> > 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 <nelson.chu@sifive.com<mailto:nelson.chu@sifive.com><mailto:nelson.chu@sifive.com<mailto:nelson.chu@sifive.com>>> 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 <nelson.chu@sifive.com<mailto:nelson.chu@sifive.com><mailto:nelson.chu@sifive.com<mailto:nelson.chu@sifive.com>>> wrote:
> >
> >
> > On Mon, Jul 6, 2026 at 7:46 PM Ethan Y. C. Liang <ycl669@andestech.com<mailto:ycl669@andestech.com><mailto:ycl669@andestech.com<mailto:ycl669@andestech.com>>> 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
> >


More information about the Binutils mailing list