PR84066 Wrong shadow stack register size is saved for x32
authorIgor Tsimbalist <igor.v.tsimbalist@intel.com>
Fri, 2 Feb 2018 10:06:39 +0000 (11:06 +0100)
committerIgor Tsimbalist <itsimbal@gcc.gnu.org>
Fri, 2 Feb 2018 10:06:39 +0000 (11:06 +0100)
x32 is a 64-bit process with 32-bit software pointer and kernel may
place x32 shadow stack above 4GB.  We need to save and restore 64-bit
shadow stack register for x32. builtin jmp buf size is 5 pointers.  We
have space to save 64-bit shadow stack pointers: 32-bit SP, 32-bit FP,
32-bit IP, 64-bit SSP for x32.

PR target/84066
* gcc/config/i386/i386.md: Replace Pmode with word_mode in
builtin_setjmp_setup and builtin_longjmp to support x32.
* gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c: New test.
* gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c: Likewise.

From-SVN: r257326

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c [new file with mode: 0644]

index c01487b8420afca4aaea34e4aada40389308f41e..d89236958c9ce7404ec2dbcd36abae3ba8438d6c 100644 (file)
@@ -1,3 +1,9 @@
+2018-02-02  Igor Tsimbalist  <igor.v.tsimbalist@intel.com>
+
+       PR target/84066
+       * config/i386/i386.md: Replace Pmode with word_mode in
+       builtin_setjmp_setup and builtin_longjmp to support x32.
+
 2018-02-01  Peter Bergner  <bergner@vnet.ibm.com>
 
        PR target/56010
index c08e4f55cff7f988e25cc9aa12346aa78c0e82f9..a4832bf696f321e8ee5aad71fa946ca198d9d689 100644 (file)
     {
       rtx mem, reg_ssp;
 
-      mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
-                                              3 * GET_MODE_SIZE (Pmode)));
-      reg_ssp = gen_reg_rtx (Pmode);
+      mem = gen_rtx_MEM (word_mode,
+                        plus_constant (Pmode, operands[0],
+                                       3 * GET_MODE_SIZE (ptr_mode)));
+      reg_ssp = gen_reg_rtx (word_mode);
       emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
-      emit_insn ((Pmode == SImode)
-                 ? gen_rdsspsi (reg_ssp, reg_ssp)
-                 : gen_rdsspdi (reg_ssp, reg_ssp));
+      emit_insn ((word_mode == SImode)
+                ? gen_rdsspsi (reg_ssp, reg_ssp)
+                : gen_rdsspdi (reg_ssp, reg_ssp));
       emit_move_insn (mem, reg_ssp);
     }
   DONE;
       /* Get the current shadow stack pointer.  The code below will check if
         SHSTK feature is enabled.  If it is not enabled the RDSSP instruction
         is a NOP.  */
-      reg_ssp = gen_reg_rtx (Pmode);
+      reg_ssp = gen_reg_rtx (word_mode);
       emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
-      emit_insn ((Pmode == SImode)
+      emit_insn ((word_mode == SImode)
                 ? gen_rdsspsi (reg_ssp, reg_ssp)
                 : gen_rdsspdi (reg_ssp, reg_ssp));
-      mem_buf = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
-                                                  3 * GET_MODE_SIZE (Pmode)));
+      mem_buf = gen_rtx_MEM (word_mode,
+                            plus_constant (Pmode, operands[0],
+                                           3 * GET_MODE_SIZE (ptr_mode)));
 
       /* Compare through substraction the saved and the current ssp to decide
         if ssp has to be adjusted.  */
-      reg_adj = gen_reg_rtx (Pmode);
-      tmp = gen_rtx_SET (reg_adj, gen_rtx_MINUS (Pmode, reg_ssp, mem_buf));
+      tmp = gen_rtx_SET (reg_ssp, gen_rtx_MINUS (word_mode, reg_ssp, mem_buf));
       clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
       tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
       emit_insn (tmp);
       JUMP_LABEL (jump) = noadj_label;
 
       /* Compute the numebr of frames to adjust.  */
+      reg_adj = gen_lowpart (ptr_mode, reg_ssp);
       tmp = gen_rtx_SET (reg_adj,
-                        gen_rtx_LSHIFTRT (Pmode, negate_rtx (Pmode, reg_adj),
-                                          GEN_INT ((Pmode == SImode)
+                        gen_rtx_LSHIFTRT (ptr_mode,
+                                          negate_rtx (ptr_mode, reg_adj),
+                                          GEN_INT ((word_mode == SImode)
                                                    ? 2
                                                    : 3)));
       clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
       emit_label (loop_label);
       LABEL_NUSES (loop_label) = 1;
 
-      emit_insn ((Pmode == SImode)
-                ? gen_incsspsi (reg_adj)
-                : gen_incsspdi (reg_adj));
-      tmp = gen_rtx_SET (reg_adj, gen_rtx_MINUS (Pmode,
+      emit_insn ((word_mode == SImode)
+                ? gen_incsspsi (reg_ssp)
+                : gen_incsspdi (reg_ssp));
+      tmp = gen_rtx_SET (reg_adj, gen_rtx_MINUS (ptr_mode,
                                                 reg_adj,
                                                 GEN_INT (255)));
       clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
 
       emit_label (inc_label);
       LABEL_NUSES (inc_label) = 1;
-      emit_insn ((Pmode == SImode)
-                ? gen_incsspsi (reg_adj)
-                : gen_incsspdi (reg_adj));
+      emit_insn ((word_mode == SImode)
+                ? gen_incsspsi (reg_ssp)
+                : gen_incsspdi (reg_ssp));
 
       emit_label (noadj_label);
       LABEL_NUSES (noadj_label) = 1;
     }
 
   /* This code is the same as in expand_buildin_longjmp.  */
-  fp = gen_rtx_MEM (Pmode, operands[0]);
-  lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
-                                          GET_MODE_SIZE (Pmode)));
+  fp = gen_rtx_MEM (ptr_mode, operands[0]);
+  lab = gen_rtx_MEM (ptr_mode, plus_constant (Pmode, operands[0],
+                                             GET_MODE_SIZE (ptr_mode)));
   stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, operands[0],
-                                              2 * GET_MODE_SIZE (Pmode)));
+                                              2 * GET_MODE_SIZE (ptr_mode)));
   lab = copy_to_reg (lab);
 
   emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
   emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
 
+  if (GET_MODE (fp) != Pmode)
+    fp = convert_to_mode (Pmode, fp, 1);
   emit_move_insn (hard_frame_pointer_rtx, fp);
   emit_stack_restore (SAVE_NONLOCAL, stack);
 
index ec87b8bffc2ba5c16b6d4606242b15f626962ff2..15c3e06ff630d4da012eb3e83efa1811496e675b 100644 (file)
@@ -1,3 +1,9 @@
+2018-02-02  Igor Tsimbalist  <igor.v.tsimbalist@intel.com>
+
+       PR target/84066
+       * gcc.target/i386/cet-sjlj-6a.c: New test.
+       * gcc.target/i386/cet-sjlj-6b.c: Likewise.
+
 2018-02-01  Marek Polacek  <polacek@redhat.com>
 
        PR c++/84125
diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c
new file mode 100644 (file)
index 0000000..8410ff9
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-O -maddress-mode=short -fcf-protection -mcet -mx32" } */
+/* { dg-final { scan-assembler-times "endbr64" 2 } } */
+/* { dg-final { scan-assembler-times "movq\t.*buf\\+12" 1 } } */
+/* { dg-final { scan-assembler-times "subq\tbuf\\+12" 1 } } */
+/* { dg-final { scan-assembler-times "shrl\t\\\$3," 1 } } */
+/* { dg-final { scan-assembler-times "rdsspq" 2 } } */
+/* { dg-final { scan-assembler-times "incsspq" 2 } } */
+
+void *buf[5];
+
+void raise0(void)
+{
+  __builtin_longjmp (buf, 1);
+}
+
+void execute(int cmd)
+{
+  __builtin_setjmp (buf);
+}
diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c
new file mode 100644 (file)
index 0000000..ce11163
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O -maddress-mode=long -fcf-protection -mcet -mx32" } */
+/* { dg-final { scan-assembler-times "endbr64" 2 } } */
+/* { dg-final { scan-assembler-times "movq\t.*buf\\+12" 1 } } */
+/* { dg-final { scan-assembler-times "subq\tbuf\\+12" 1 } } */
+/* { dg-final { scan-assembler-times "shrl\t\\\$3," 1 } } */
+/* { dg-final { scan-assembler-times "rdsspq" 2 } } */
+/* { dg-final { scan-assembler-times "incsspq" 2 } } */
+
+#include "cet-sjlj-6a.c"