RISC-V: Don't assume the priv attributes are in order when handling them.
authorNelson Chu <nelson.chu@sifive.com>
Tue, 9 Jun 2020 07:33:08 +0000 (15:33 +0800)
committerNelson Chu <nelson.chu@sifive.com>
Mon, 22 Jun 2020 01:54:02 +0000 (09:54 +0800)
There is no guarantee that the priv attributes should be defined in order.
Therefore, we shouldn't have the order assumption when handling them in the
riscv_merge_attributes.  Set priv_attrs_merged to TRUE if we have handled
all of the priv attributes.

bfd/
* elfnn-riscv.c (riscv_merge_attributes): Once we meet one of the
priv attributes, we will check the conflicts for all of them (major,
minor and revision), and then set the priv_attrs_merged to TRUE to
indicate that we have handled all of the priv attributes.  Remove
the unused boolean priv_may_conflict, in_priv_zero and out_priv_zero.

bfd/ChangeLog
bfd/elfnn-riscv.c

index a77dd705ee064535ca541604e99ff08103818ba5..d9b66b55d347e37b940c5b869e77cec1f4a73dc8 100644 (file)
@@ -1,3 +1,11 @@
+2020-06-22  Nelson Chu  <nelson.chu@sifive.com>
+
+       * elfnn-riscv.c (riscv_merge_attributes): Once we meet one of the
+       priv attributes, we will check the conflicts for all of them (major,
+       minor and revision), and then set the priv_attrs_merged to TRUE to
+       indicate that we have handled all of the priv attributes.  Remove
+       the unused boolean priv_may_conflict, in_priv_zero and out_priv_zero.
+
 2020-06-21  Alan Modra  <amodra@gmail.com>
 
        PR 26132
index 986e717782fc2e5556295bcaca699d6cc7e21c80..280445945dd21bf7821766c33659fd01c803188a 100644 (file)
@@ -2987,9 +2987,7 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
   obj_attribute *in_attr;
   obj_attribute *out_attr;
   bfd_boolean result = TRUE;
-  bfd_boolean priv_may_conflict = FALSE;
-  bfd_boolean in_priv_zero = TRUE;
-  bfd_boolean out_priv_zero = TRUE;
+  bfd_boolean priv_attrs_merged = FALSE;
   const char *sec_name = get_elf_backend_data (ibfd)->obj_attrs_section;
   unsigned int i;
 
@@ -3048,41 +3046,42 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
       case Tag_RISCV_priv_spec:
       case Tag_RISCV_priv_spec_minor:
       case Tag_RISCV_priv_spec_revision:
-       if (in_attr[i].i != 0)
-         in_priv_zero = FALSE;
-       if (out_attr[i].i != 0)
-         out_priv_zero = FALSE;
-       if (out_attr[i].i != in_attr[i].i)
-         priv_may_conflict = TRUE;
-
-       /* We check the priv version conflict when parsing the
-          revision version.  */
-       if (i != Tag_RISCV_priv_spec_revision)
-         break;
-
-       /* Allow to link the object without the priv setting.  */
-       if (out_priv_zero)
-         {
-           out_attr[i].i = in_attr[i].i;
-           out_attr[Tag_RISCV_priv_spec].i =
-               in_attr[Tag_RISCV_priv_spec].i;
-           out_attr[Tag_RISCV_priv_spec_minor].i =
-               in_attr[Tag_RISCV_priv_spec_minor].i;
-         }
-       else if (!in_priv_zero
-                && priv_may_conflict)
+       /* If we have handled the priv attributes, then skip it.  */
+       if (!priv_attrs_merged)
          {
-           _bfd_error_handler
-             (_("error: %pB use privilege spec version %u.%u.%u but "
-                "the output use version %u.%u.%u."),
-              ibfd,
-              in_attr[Tag_RISCV_priv_spec].i,
-              in_attr[Tag_RISCV_priv_spec_minor].i,
-              in_attr[i].i,
-              out_attr[Tag_RISCV_priv_spec].i,
-              out_attr[Tag_RISCV_priv_spec_minor].i,
-              out_attr[i].i);
-           result = FALSE;
+           unsigned int Tag_a = Tag_RISCV_priv_spec;
+           unsigned int Tag_b = Tag_RISCV_priv_spec_minor;
+           unsigned int Tag_c = Tag_RISCV_priv_spec_revision;
+
+           /* Allow to link the object without the priv specs.  */
+           if (out_attr[Tag_a].i == 0
+               && out_attr[Tag_b].i == 0
+               && out_attr[Tag_c].i == 0)
+             {
+               out_attr[Tag_a].i = in_attr[Tag_a].i;
+               out_attr[Tag_b].i = in_attr[Tag_b].i;
+               out_attr[Tag_c].i = in_attr[Tag_c].i;
+             }
+           else if ((in_attr[Tag_a].i != 0
+                     || in_attr[Tag_b].i != 0
+                     || in_attr[Tag_c].i != 0)
+                    && (out_attr[Tag_a].i != in_attr[Tag_a].i
+                        || out_attr[Tag_b].i != in_attr[Tag_b].i
+                        || out_attr[Tag_c].i != in_attr[Tag_c].i))
+             {
+               _bfd_error_handler
+                 (_("error: %pB use privilege spec version %u.%u.%u but "
+                    "the output use version %u.%u.%u."),
+                  ibfd,
+                  in_attr[Tag_a].i,
+                  in_attr[Tag_b].i,
+                  in_attr[Tag_c].i,
+                  out_attr[Tag_a].i,
+                  out_attr[Tag_b].i,
+                  out_attr[Tag_c].i);
+               result = FALSE;
+             }
+           priv_attrs_merged = TRUE;
          }
        break;