]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
aarch64: Fix scbnds validation
authorAlex Coplan <alex.coplan@arm.com>
Thu, 11 Nov 2021 16:57:22 +0000 (16:57 +0000)
committerAlex Coplan <alex.coplan@arm.com>
Thu, 11 Nov 2021 16:57:22 +0000 (16:57 +0000)
Prior to this patch, we were failing to validate scbnds instructions
properly in multiple ways. The code in tc-aarch64.c:parse_operands
failed to check if the expression parsing code actually returned a
constant (O_constant) immediate. For sufficiently large immediates this
would result in O_big instead and this was not handled.

Moreover, the code to coerce the immediate form into the immediate +
shift form of the instruction was buggy in multiple ways: using the
wrong mask to check if the lower bits were set and checking the wrong
variable.

Finally, the code in operand_general_constraint_met_p was only checking
if the immediate is in range for the shifted case: it should be checking
this in both cases.

As well as fixing these issues, this patch improves the error messages
in a couple of cases and adds tests for various valid and invalid cases.

gas/ChangeLog:

2021-11-11  Alex Coplan  <alex.coplan@arm.com>

* config/tc-aarch64.c (parse_shift): Improve error message for
O_big expressions.
(parse_operands): In AARCH64_OPND_A64C_IMM6_EXT case, handle
parse_shifter_operand_imm returning non-O_constant
expressions; fix logic for coercion to the shifted form.
* testsuite/gas/aarch64/scbnds-immed.d: New test.
* testsuite/gas/aarch64/scbnds-immed.s: Assembly thereof.
* testsuite/gas/aarch64/scbnds-invalid.d: New test.
* testsuite/gas/aarch64/scbnds-invalid.l: Error output thereof.
* testsuite/gas/aarch64/scbnds-invalid.s: Assembly thereof.

opcodes/ChangeLog:

2021-11-11  Alex Coplan  <alex.coplan@arm.com>

* aarch64-opc.c (operand_general_constraint_met_p): Always check
if the immediate is in range for AARCH64_OPND_A64C_IMM6_EXT.

gas/ChangeLog
gas/config/tc-aarch64.c
gas/testsuite/gas/aarch64/scbnds-immed.d [new file with mode: 0644]
gas/testsuite/gas/aarch64/scbnds-immed.s [new file with mode: 0644]
gas/testsuite/gas/aarch64/scbnds-invalid.d [new file with mode: 0644]
gas/testsuite/gas/aarch64/scbnds-invalid.l [new file with mode: 0644]
gas/testsuite/gas/aarch64/scbnds-invalid.s [new file with mode: 0644]
opcodes/ChangeLog
opcodes/aarch64-opc.c

index 1bd68680e141a33de1cc338212e4aaffc00fc801..32a63b59a720d2d985af1ed15ec434a42c3d1e93 100644 (file)
@@ -1,3 +1,16 @@
+2021-11-11  Alex Coplan  <alex.coplan@arm.com>
+
+       * config/tc-aarch64.c (parse_shift): Improve error message for
+       O_big expressions.
+       (parse_operands): In AARCH64_OPND_A64C_IMM6_EXT case, handle
+       parse_shifter_operand_imm returning non-O_constant
+       expressions; fix logic for coercion to the shifted form.
+       * testsuite/gas/aarch64/scbnds-immed.d: New test.
+       * testsuite/gas/aarch64/scbnds-immed.s: Assembly thereof.
+       * testsuite/gas/aarch64/scbnds-invalid.d: New test.
+       * testsuite/gas/aarch64/scbnds-invalid.l: Error output thereof.
+       * testsuite/gas/aarch64/scbnds-invalid.s: Assembly thereof.
+
 2021-09-24  Alex Coplan  <alex.coplan@arm.com>
 
        * config/tc-aarch64.c (md_begin): Set the ELF header flag
index e1762df395efbbb9898784c5ee5b0dae4457a260..ba0a46227a717d7c1aa3879e4d725a08c3b315f6 100644 (file)
@@ -3394,6 +3394,11 @@ parse_shift (char **str, aarch64_opnd_info *operand, enum parse_shift_mode mode)
        }
       operand->shifter.amount = 0;
     }
+  else if (exp.X_op == O_big)
+    {
+      set_fatal_syntax_error (_("shift amount out of range"));
+      return FALSE;
+    }
   else if (exp.X_op != O_constant)
     {
       set_syntax_error (_("constant shift amount required"));
@@ -6438,10 +6443,19 @@ parse_operands (char *str, const aarch64_opcode *opcode)
          po_misc_or_fail (parse_shifter_operand_imm (&str, info,
                                                      SHIFTED_ARITH_IMM));
 
+         if (inst.reloc.exp.X_op != O_constant)
+           {
+             set_fatal_syntax_error (_(inst.reloc.exp.X_op == O_big
+                                       ? "immediate out of range"
+                                       : "expected constant expression"));
+             goto failure;
+           }
+
          /* Try to coerce into shifted form if the immediate is out of
             range.  */
-         if (inst.reloc.exp.X_add_number > 63 && (info->imm.value & 16) == 0
-             && (inst.reloc.exp.X_add_number >> 4) <= 64
+         if (inst.reloc.exp.X_add_number > 63
+             && (inst.reloc.exp.X_add_number & 0xf) == 0
+             && (inst.reloc.exp.X_add_number >> 4) <= 63
              && info->shifter.amount == 0)
            {
              info->shifter.amount = 4;
diff --git a/gas/testsuite/gas/aarch64/scbnds-immed.d b/gas/testsuite/gas/aarch64/scbnds-immed.d
new file mode 100644 (file)
index 0000000..d11aac4
--- /dev/null
@@ -0,0 +1,16 @@
+#name: test valid scbnds immediates
+#as: -march=morello
+#objdump: -dr
+
+.*:     file format .*
+
+
+Disassembly of section \.text:
+
+.* <\.text>:
+.*:    c2c03820        scbnds  c0, c1, #0x0
+.*:    c2d03820        scbnds  c0, c1, #0x20
+.*:    c2dfb820        scbnds  c0, c1, #0x3f
+.*:    c2c27820        scbnds  c0, c1, #0x4, lsl #4
+.*:    c2c2f820        scbnds  c0, c1, #0x5, lsl #4
+.*:    c2dff820        scbnds  c0, c1, #0x3f, lsl #4
diff --git a/gas/testsuite/gas/aarch64/scbnds-immed.s b/gas/testsuite/gas/aarch64/scbnds-immed.s
new file mode 100644 (file)
index 0000000..f45ea66
--- /dev/null
@@ -0,0 +1,6 @@
+scbnds c0, c1, #0
+scbnds c0, c1, #32
+scbnds c0, c1, #63
+scbnds c0, c1, #64
+scbnds c0, c1, #80
+scbnds c0, c1, #1008
diff --git a/gas/testsuite/gas/aarch64/scbnds-invalid.d b/gas/testsuite/gas/aarch64/scbnds-invalid.d
new file mode 100644 (file)
index 0000000..bdd0ce3
--- /dev/null
@@ -0,0 +1,4 @@
+#name: invalid scbnds instructions
+#as: -march=morello
+#source: scbnds-invalid.s
+#error_output: scbnds-invalid.l
diff --git a/gas/testsuite/gas/aarch64/scbnds-invalid.l b/gas/testsuite/gas/aarch64/scbnds-invalid.l
new file mode 100644 (file)
index 0000000..a204c0a
--- /dev/null
@@ -0,0 +1,30 @@
+.*: Assembler messages:
+.*: Error: operand 2 must be a Capability register or a capability stack pointer register -- `scbnds c0,czr,#1'
+.*: Error: operand 1 must be a Capability register or a capability stack pointer register -- `scbnds czr,c0,#1'
+.*: Error: operand 1 must be a Capability register or a capability stack pointer register -- `scbnds czr,czr,#1'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#-1'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#65'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#66'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#67'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#68'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#69'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#70'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#71'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#72'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#73'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#74'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#75'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#76'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#77'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#78'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#79'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#81'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#1009'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#1024'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#1000000000000000000000001'
+.*: Error: shift amount out of range 0 to 63 at operand 3 -- `scbnds c0,c1,#1,lsl#-1'
+.*: Error: shift amount must be 4 at operand 3 -- `scbnds c0,c1,#1,lsl#2'
+.*: Error: shift amount must be 4 at operand 3 -- `scbnds c0,c1,#1,lsl#3'
+.*: Error: shift amount must be 4 at operand 3 -- `scbnds c0,c1,#1,lsl#5'
+.*: Error: shift amount out of range at operand 3 -- `scbnds c0,c1,#1,lsl#10000000000000000000000001'
+.*: Error: immediate out of range at operand 3 -- `scbnds c0,c1,#64,lsl#4'
diff --git a/gas/testsuite/gas/aarch64/scbnds-invalid.s b/gas/testsuite/gas/aarch64/scbnds-invalid.s
new file mode 100644 (file)
index 0000000..4c1fab8
--- /dev/null
@@ -0,0 +1,29 @@
+scbnds c0, czr, #1
+scbnds czr, c0, #1
+scbnds czr, czr, #1
+scbnds c0, c1, #-1
+scbnds c0, c1, #65
+scbnds c0, c1, #66
+scbnds c0, c1, #67
+scbnds c0, c1, #68
+scbnds c0, c1, #69
+scbnds c0, c1, #70
+scbnds c0, c1, #71
+scbnds c0, c1, #72
+scbnds c0, c1, #73
+scbnds c0, c1, #74
+scbnds c0, c1, #75
+scbnds c0, c1, #76
+scbnds c0, c1, #77
+scbnds c0, c1, #78
+scbnds c0, c1, #79
+scbnds c0, c1, #81
+scbnds c0, c1, #1009
+scbnds c0, c1, #1024
+scbnds c0, c1, #1000000000000000000000001
+scbnds c0, c1, #1, lsl #-1
+scbnds c0, c1, #1, lsl #2
+scbnds c0, c1, #1, lsl #3
+scbnds c0, c1, #1, lsl #5
+scbnds c0, c1, #1, lsl #10000000000000000000000001
+scbnds c0, c1, #64, lsl #4
index d868c6d471d925c66666ec29a6a8446e51fc48b8..ca6742d00d9157051afa680fc154e43745803f1f 100644 (file)
@@ -1,3 +1,8 @@
+2021-11-11  Alex Coplan  <alex.coplan@arm.com>
+
+       * aarch64-opc.c (operand_general_constraint_met_p): Always check
+       if the immediate is in range for AARCH64_OPND_A64C_IMM6_EXT.
+
 2021-09-24  Alex Coplan  <alex.coplan@arm.com>
 
        * aarch64-tbl.h (aarch64_opcode_table): Update A64C_INSNs
index a13ff33ce4380479346ba1c10641583c69b334f9..c4c5841746add74e72a4b9d898ad1094d5dab4b4 100644 (file)
@@ -2239,13 +2239,13 @@ operand_general_constraint_met_p (aarch64_feature_set features,
                                   _("shift amount must be 4"));
                  return 0;
                }
-             if (!value_fit_unsigned_field_p (opnd->imm.value, 6))
-               {
-                 set_other_error (mismatch_detail, idx,
-                                  _("immediate out of range"));
-                 return 0;
-               }
            }
+           if (!value_fit_unsigned_field_p (opnd->imm.value, 6))
+             {
+               set_other_error (mismatch_detail, idx,
+                                _("immediate out of range"));
+               return 0;
+             }
          break;
 
        case AARCH64_OPND_AIMM: