[PATCH] POWER10: Add Return-Oriented Programming instructions

Alan Modra amodra@gmail.com
Sat Jan 9 05:04:47 GMT 2021


On Sat, Jan 09, 2021 at 11:10:08AM +1030, Alan Modra wrote:
> On Fri, Jan 08, 2021 at 04:07:12PM -0600, Peter Bergner wrote:
> > +  /* DW offsets must be in the range [-512, -8] and be a multiple of 8.  */
> > +  if (value < -512
> > +      || value > -8
> > +      || (value & 0x7) != 0)
> > +    *errmsg = _("invalid offset: must be in the range [-512, -8] "
> > +		"and be a multiple of 8");
> > +
> > +  return insn | ((value & 0xf8) << 18) | ((value >> 5) & 1);
> 
> value >> 5 is wrong here.

This is what I committed.

opcodes/
	* ppc-opc.c (insert_dw, (extract_dw): New functions.
	(DW, (XRC_MASK): Define.
	(powerpc_opcodes) <hashchk, hashchkp, hashst, haststp>: New mnemonics.
gas/
	* testsuite/gas/ppc/rop-checks.d,
	* testsuite/gas/ppc/rop-checks.l,
	* testsuite/gas/ppc/rop-checks.s,
	* testsuite/gas/ppc/rop.d,
	* testsuite/gas/ppc/rop.s: New tests.
	* testsuite/gas/ppc/ppc.exp: Run them.

diff --git a/gas/testsuite/gas/ppc/ppc.exp b/gas/testsuite/gas/ppc/ppc.exp
index bec3151335..6f61ad09f4 100644
--- a/gas/testsuite/gas/ppc/ppc.exp
+++ b/gas/testsuite/gas/ppc/ppc.exp
@@ -146,5 +146,7 @@ run_dump_test "stringop"
 run_dump_test "xvtlsbb"
 run_dump_test "rightmost"
 run_dump_test "scalarquad"
+run_dump_test "rop"
+run_dump_test "rop-checks"
 
 run_dump_test "dcbt"
diff --git a/gas/testsuite/gas/ppc/rop-checks.d b/gas/testsuite/gas/ppc/rop-checks.d
new file mode 100644
index 0000000000..b7ef25eed2
--- /dev/null
+++ b/gas/testsuite/gas/ppc/rop-checks.d
@@ -0,0 +1,3 @@
+#as: -mpower10
+#name: Test Return-Oriented Programming checks
+#error_output: rop-checks.l
diff --git a/gas/testsuite/gas/ppc/rop-checks.l b/gas/testsuite/gas/ppc/rop-checks.l
new file mode 100644
index 0000000000..83ffbee8ee
--- /dev/null
+++ b/gas/testsuite/gas/ppc/rop-checks.l
@@ -0,0 +1,17 @@
+[^:]*: Assembler messages:
+[^:]*:3: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:4: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:5: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:6: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:7: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:8: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:9: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:10: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:11: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:12: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:13: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:14: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:15: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:16: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:17: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:18: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
diff --git a/gas/testsuite/gas/ppc/rop-checks.s b/gas/testsuite/gas/ppc/rop-checks.s
new file mode 100644
index 0000000000..83ca35a819
--- /dev/null
+++ b/gas/testsuite/gas/ppc/rop-checks.s
@@ -0,0 +1,18 @@
+	.text
+_start:
+	hashst   20,8(1)
+	hashst   21,0(1)
+	hashst   22,-12(1)
+	hashst   23,-520(1)
+	hashchk  20,8(1)
+	hashchk  21,0(1)
+	hashchk  22,-12(1)
+	hashchk  23,-520(1)
+	hashstp  20,8(1)
+	hashstp  21,0(1)
+	hashstp  22,-12(1)
+	hashstp  23,-520(1)
+	hashchkp 20,8(1)
+	hashchkp 21,0(1)
+	hashchkp 22,-12(1)
+	hashchkp 23,-520(1)
diff --git a/gas/testsuite/gas/ppc/rop.d b/gas/testsuite/gas/ppc/rop.d
new file mode 100644
index 0000000000..2671dd6bbd
--- /dev/null
+++ b/gas/testsuite/gas/ppc/rop.d
@@ -0,0 +1,27 @@
+#as: -mpower8
+#objdump: -d -Mpower8
+#name: Return-Oriented Programming tests
+
+.*
+
+
+Disassembly of section \.text:
+
+0+0 <_start>:
+.*:	(7f e1 a5 a5|a5 a5 e1 7f) 	hashst  r20,-8\(r1\)
+.*:	(7f c1 ad a5|a5 ad c1 7f) 	hashst  r21,-16\(r1\)
+.*:	(7c 01 b5 a5|a5 b5 01 7c) 	hashst  r22,-256\(r1\)
+.*:	(7c 01 bd a4|a4 bd 01 7c) 	hashst  r23,-512\(r1\)
+.*:	(7f e1 a5 e5|e5 a5 e1 7f) 	hashchk r20,-8\(r1\)
+.*:	(7f c1 ad e5|e5 ad c1 7f) 	hashchk r21,-16\(r1\)
+.*:	(7c 01 b5 e5|e5 b5 01 7c) 	hashchk r22,-256\(r1\)
+.*:	(7c 01 bd e4|e4 bd 01 7c) 	hashchk r23,-512\(r1\)
+.*:	(7f e1 a5 25|25 a5 e1 7f) 	hashstp r20,-8\(r1\)
+.*:	(7f c1 ad 25|25 ad c1 7f) 	hashstp r21,-16\(r1\)
+.*:	(7c 01 b5 25|25 b5 01 7c) 	hashstp r22,-256\(r1\)
+.*:	(7c 01 bd 24|24 bd 01 7c) 	hashstp r23,-512\(r1\)
+.*:	(7f e1 a5 65|65 a5 e1 7f) 	hashchkp r20,-8\(r1\)
+.*:	(7f c1 ad 65|65 ad c1 7f) 	hashchkp r21,-16\(r1\)
+.*:	(7c 01 b5 65|65 b5 01 7c) 	hashchkp r22,-256\(r1\)
+.*:	(7c 01 bd 64|64 bd 01 7c) 	hashchkp r23,-512\(r1\)
+#pass
diff --git a/gas/testsuite/gas/ppc/rop.s b/gas/testsuite/gas/ppc/rop.s
new file mode 100644
index 0000000000..22e45f49aa
--- /dev/null
+++ b/gas/testsuite/gas/ppc/rop.s
@@ -0,0 +1,21 @@
+# These instructions are new in POWER10, but enabled for POWER8 and
+# later cpus.  On POWER8 and POWER9, these instructions behave as
+# nop's.
+	.text
+_start:
+	hashst   20,-8(1)
+	hashst   21,-16(1)
+	hashst   22,-256(1)
+	hashst   23,-512(1)
+	hashchk  20,-8(1)
+	hashchk  21,-16(1)
+	hashchk  22,-256(1)
+	hashchk  23,-512(1)
+	hashstp  20,-8(1)
+	hashstp  21,-16(1)
+	hashstp  22,-256(1)
+	hashstp  23,-512(1)
+	hashchkp 20,-8(1)
+	hashchkp 21,-16(1)
+	hashchkp 22,-256(1)
+	hashchkp 23,-512(1)
diff --git a/opcodes/ppc-opc.c b/opcodes/ppc-opc.c
index dcff56205d..bbbadffad8 100644
--- a/opcodes/ppc-opc.c
+++ b/opcodes/ppc-opc.c
@@ -558,6 +558,34 @@ extract_dcmxs (uint64_t insn,
   return (insn & 0x40) | ((insn << 3) & 0x20) | ((insn >> 16) & 0x1f);
 }
 
+/* The DW field in a X form instruction when the field is split
+   into separate D and DX fields.  */
+
+static uint64_t
+insert_dw (uint64_t insn,
+	   int64_t value,
+	   ppc_cpu_t dialect ATTRIBUTE_UNUSED,
+	   const char **errmsg ATTRIBUTE_UNUSED)
+{
+  /* DW offsets must be in the range [-512, -8] and be a multiple of 8.  */
+  if (value < -512
+      || value > -8
+      || (value & 0x7) != 0)
+    *errmsg = _("invalid offset: must be in the range [-512, -8] "
+		"and be a multiple of 8");
+
+  return insn | ((value & 0xf8) << 18) | ((value >> 8) & 1);
+}
+
+static int64_t
+extract_dw (uint64_t insn,
+	     ppc_cpu_t dialect ATTRIBUTE_UNUSED,
+	     int *invalid ATTRIBUTE_UNUSED)
+{
+  int64_t dw = ((insn & 1) << 8) | ((insn >> 18) & 0xf8);
+  return dw - 512;
+}
+
 /* The D field in a DX form instruction when the field is split
    into separate D0, D1 and D2 fields.  */
 
@@ -2497,8 +2525,13 @@ const struct powerpc_operand powerpc_operands[] =
 #define BHRBE DUIS
   { 0x3ff, 11, NULL, NULL, 0 },
 
+  /* The split DW field in a X form instruction.  */
+#define DW DUIS + 1
+  { -1, PPC_OPSHIFT_INV, insert_dw, extract_dw,
+    PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED},
+
   /* The split D field in a DX form instruction.  */
-#define DXD DUIS + 1
+#define DXD DW + 1
   { 0xffff, PPC_OPSHIFT_INV, insert_dxd, extract_dxd,
     PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT},
 
@@ -3750,6 +3783,9 @@ const unsigned int num_powerpc_operands = (sizeof (powerpc_operands)
 /* The mask for an X form instruction with the BF bits specified.  */
 #define XBF_MASK (X_MASK | (3 << 21))
 
+/* An X form instruction without the RC field specified.  */
+#define XRC_MASK XRC (0x3f, 0x3ff, 0)
+
 /* An X form wait instruction with everything filled in except the WC
    field.  */
 #define XWC_MASK (XRC (0x3f, 0x3ff, 1) | (7 << 23) | RA_MASK | RB_MASK)
@@ -7656,6 +7692,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
 {"addeo.",	XO(31,138,1,1),	XO_MASK,     PPCCOM,	0,		{RT, RA, RB}},
 {"aeo.",	XO(31,138,1,1),	XO_MASK,     PWRCOM,	0,		{RT, RA, RB}},
 
+{"hashstp",	X(31,658),	XRC_MASK,    POWER8,	0,		{RB, DW, RA0}},
+
 {"mfsrin",	X(31,659),	XRA_MASK,    PPC,	NON32,		{RT, RB}},
 
 {"stdbrx",	X(31,660),	X_MASK, CELL|POWER7|PPCA2, 0,		{RS, RA0, RB}},
@@ -7685,6 +7723,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
 {"tendall.",	XRC(31,686,1)|(1<<25), XRTRARB_MASK, PPCHTM, 0,		{0}},
 {"tend.",	XRC(31,686,1), XRTARARB_MASK, PPCHTM,	0,		{HTM_A}},
 
+{"hashchkp",	X(31,690),	XRC_MASK,    POWER8,	0,		{RB, DW, RA0}},
+
 {"stbcx.",	XRC(31,694,1),	X_MASK,	  POWER8|E6500, 0,		{RS, RA0, RB}},
 
 {"stfsux",	X(31,695),	X_MASK,	     COM,	PPCEFS,		{FRS, RAS, RB}},
@@ -7715,6 +7755,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
 {"addzeo.",	XO(31,202,1,1),	XORB_MASK,   PPCCOM,	0,		{RT, RA}},
 {"azeo.",	XO(31,202,1,1),	XORB_MASK,   PWRCOM,	0,		{RT, RA}},
 
+{"hashst",	X(31,722),	XRC_MASK,    POWER8,	0,		{RB, DW, RA0}},
+
 {"stswi",	X(31,725),	X_MASK,	     PPCCOM,	E500|E500MC,	{RS, RA0, NB}},
 {"stsi",	X(31,725),	X_MASK,	     PWRCOM,	0,		{RS, RA0, NB}},
 
@@ -7761,6 +7803,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
 {"tresume.",	XRCL(31,750,1,1), XRTRARB_MASK,PPCHTM,	0,		{0}},
 {"tsr.",	XRC(31,750,1),	  XRTLRARB_MASK,PPCHTM,	0,		{L}},
 
+{"hashchk",	X(31,754),	XRC_MASK,    POWER8,	0,		{RB, DW, RA0}},
+
 {"darn",	X(31,755),	XLRAND_MASK, POWER9,	0,		{RT, LRAND}},
 
 {"dcba",	X(31,758), XRT_MASK, PPC405|PPC7450|BOOKE|PPCA2|PPC476, 0, {RA0, RB}},


-- 
Alan Modra
Australia Development Lab, IBM


More information about the Binutils mailing list