]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
RISC-V: error handling for subset parsing
authorJan Beulich <jbeulich@suse.com>
Fri, 5 Jun 2026 09:10:28 +0000 (11:10 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 5 Jun 2026 09:10:28 +0000 (11:10 +0200)
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 <jiawei@iscas.ac.cn>
bfd/elfxx-riscv.c
gas/config/tc-riscv.c
gas/testsuite/gas/riscv/x-thead-vector-fail.d

index 91337013ba388ea18b7295f115b712c46b6af13b..8e56322b512d4de9bf7406f33c2d1e6d6d2e83ee 100644 (file)
@@ -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.  */
index 22d002a330963afed2d441d8248933ca815f520f..be3501930b3caa1d698758569c4f5960bebb8afb 100644 (file)
@@ -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)
     {
index 35231d983ff976f913c7dc55a021dd071b9072aa..dec068c13ff76ba209edb111bab4cb312429c7f0 100644 (file)
@@ -1,3 +1,3 @@
 #as: -march=rv64gc_zve32x_xtheadvector
-#source: x-thead-vector.s
+#source: empty.s
 #error_output: x-thead-vector-fail.l