From: Jan Beulich Date: Fri, 5 Jun 2026 09:10:28 +0000 (+0200) Subject: RISC-V: error handling for subset parsing X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=11cbe94d245c06313541e4e4c87745f74856d5dd;p=thirdparty%2Fbinutils-gdb.git RISC-V: error handling for subset parsing The parsing of both the argument of -march= and the operand(s) of ".option arch, ..." can fail. In such a case for .option (and equally for .attribute) prior state should continue to be used, while for -march= defaults should be put in place. In particular, extensions conflicting with previously enabled extensions should not suddenly become available. While re-indenting riscv_set_rvc() invocations, leverage that C implies Zca (and hence a check for the latter suffices). Mirror that change to riscv_set_arch() for consistency. Reviewed-by: Jiawei --- diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index 91337013ba3..8e56322b512 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -2768,7 +2768,28 @@ bool riscv_update_subset (riscv_parse_subset_t *rps, const char *str) { - return riscv_update_subset1 (rps, NULL, str); + unsigned int newxlen = *rps->xlen; + riscv_parse_subset_t newrps = { + .subset_list = riscv_copy_subset_list (rps->subset_list), + .error_handler = rps->error_handler, + .xlen = &newxlen, + .isa_spec = rps->isa_spec, + .check_unknown_prefixed_ext = rps->check_unknown_prefixed_ext, + }; + + if (!riscv_update_subset1 (&newrps, NULL, str)) + { + riscv_release_subset_list (newrps.subset_list); + free (newrps.subset_list); + return false; + } + + *rps->xlen = newxlen; + riscv_release_subset_list (rps->subset_list); + *rps->subset_list = *newrps.subset_list; + free (newrps.subset_list); + + return true; } /* Called from .option norvc directives. */ diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index 22d002a3309..be3501930b3 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -350,20 +350,38 @@ riscv_set_arch (const char *s) s = DEFAULT_RISCV_ARCH_WITH_EXT; } - if (riscv_rps_as.subset_list == NULL) + unsigned int newxlen = xlen; + riscv_parse_subset_t newrps = { + .subset_list = XCNEW (riscv_subset_list_t), + .error_handler = as_bad, + .xlen = &newxlen, + .isa_spec = &default_isa_spec, + .check_unknown_prefixed_ext = true, + }; + + if (!riscv_parse_subset (&newrps, s)) { - riscv_rps_as.subset_list = XNEW (riscv_subset_list_t); - riscv_rps_as.subset_list->head = NULL; - riscv_rps_as.subset_list->tail = NULL; - riscv_rps_as.subset_list->arch_str = NULL; + riscv_release_subset_list (newrps.subset_list); + if (file_arch_str != NULL) + { + free (newrps.subset_list); + return; + } + if (!riscv_parse_subset (&newrps, DEFAULT_RISCV_ARCH_WITH_EXT)) + abort (); } - riscv_release_subset_list (riscv_rps_as.subset_list); - riscv_parse_subset (&riscv_rps_as, s); + xlen = newxlen; + if (riscv_rps_as.subset_list != NULL) + { + riscv_release_subset_list (riscv_rps_as.subset_list); + free (riscv_rps_as.subset_list); + } + riscv_rps_as.subset_list = newrps.subset_list; + riscv_arch_str (xlen, riscv_rps_as.subset_list, true/* update */); file_arch_str = xstrdup (riscv_rps_as.subset_list->arch_str); - riscv_set_rvc (riscv_subset_supports (&riscv_rps_as, "c") - || riscv_subset_supports (&riscv_rps_as, "zca")); + riscv_set_rvc (riscv_subset_supports (&riscv_rps_as, "zca")); if (riscv_subset_supports (&riscv_rps_as, "ztso")) riscv_set_tso (); @@ -5037,13 +5055,16 @@ s_riscv_option (int x ATTRIBUTE_UNUSED) if (strcmp (name, "rvc") == 0) { - riscv_update_subset (&riscv_rps_as, "+c"); - riscv_arch_str (xlen, riscv_rps_as.subset_list, true/* update */); - riscv_set_rvc (true); + if (riscv_update_subset (&riscv_rps_as, "+c")) + { + riscv_arch_str (xlen, riscv_rps_as.subset_list, true/* update */); + riscv_set_rvc (true); + } } else if (strcmp (name, "norvc") == 0) { - riscv_update_subset_norvc (&riscv_rps_as); + if (!riscv_update_subset_norvc (&riscv_rps_as)) + abort (); riscv_arch_str (xlen, riscv_rps_as.subset_list, true/* update */); riscv_set_rvc (false); } @@ -5064,14 +5085,15 @@ s_riscv_option (int x ATTRIBUTE_UNUSED) name += 5; if (is_whitespace (*name) && *name != '\0') name++; - riscv_update_subset (&riscv_rps_as, name); - riscv_arch_str (xlen, riscv_rps_as.subset_list, true/* update */); + if (riscv_update_subset (&riscv_rps_as, name)) + { + riscv_arch_str (xlen, riscv_rps_as.subset_list, true/* update */); - riscv_set_rvc (riscv_subset_supports (&riscv_rps_as, "c") - || riscv_subset_supports (&riscv_rps_as, "zca")); + riscv_set_rvc (riscv_subset_supports (&riscv_rps_as, "zca")); - if (riscv_subset_supports (&riscv_rps_as, "ztso")) - riscv_set_tso (); + if (riscv_subset_supports (&riscv_rps_as, "ztso")) + riscv_set_tso (); + } } else if (strcmp (name, "push") == 0) { diff --git a/gas/testsuite/gas/riscv/x-thead-vector-fail.d b/gas/testsuite/gas/riscv/x-thead-vector-fail.d index 35231d983ff..dec068c13ff 100644 --- a/gas/testsuite/gas/riscv/x-thead-vector-fail.d +++ b/gas/testsuite/gas/riscv/x-thead-vector-fail.d @@ -1,3 +1,3 @@ #as: -march=rv64gc_zve32x_xtheadvector -#source: x-thead-vector.s +#source: empty.s #error_output: x-thead-vector-fail.l