diff mbox series

[i386] PR83109 [CET] improper code generation for builtin_longjmp with -fcf-protection -mcet

Message ID D511F25789BA7F4EBA64C8A63891A00291F602FC@IRSMSX102.ger.corp.intel.com
State New
Headers show
Series [i386] PR83109 [CET] improper code generation for builtin_longjmp with -fcf-protection -mcet | expand

Commit Message

Tsimbalist, Igor V Nov. 26, 2017, 9:56 p.m. UTC
According to the description of  inssp instruction from Intel CET it adusts the shadow stack pointer (ssp) only by value in the range of [0..255]. As a number of adjustment could be greater than 255 there should be a loop generated to adjust ssp.

gcc/
                * config/i386/i386.md: Add a loop with incssp.
                * testsuite/gcc.target/i386/cet-sjlj-1.c: Fix test.
                * testsuite/gcc.target/i386/cet-sjlj-4.c: Likewise.
---
gcc/config/i386/i386.md                    | 81 +++++++++++++++++++++++-------
gcc/testsuite/gcc.target/i386/cet-sjlj-1.c |  2 +-
gcc/testsuite/gcc.target/i386/cet-sjlj-4.c |  2 +-

Ok for trunk?

Igor

Comments

Uros Bizjak Nov. 27, 2017, 8:35 a.m. UTC | #1
On Sun, Nov 26, 2017 at 10:56 PM, Tsimbalist, Igor V
<igor.v.tsimbalist@intel.com> wrote:
> According to the description of  inssp instruction from Intel CET it adusts
> the shadow stack pointer (ssp) only by value in the range of [0..255]. As a
> number of adjustment could be greater than 255 there should be a loop
> generated to adjust ssp.
>
> gcc/
>
>                 * config/i386/i386.md: Add a loop with incssp.
>                 * testsuite/gcc.target/i386/cet-sjlj-1.c: Fix test.
>                 * testsuite/gcc.target/i386/cet-sjlj-4.c: Likewise.

LGTM.

Thanks,
Uros.
diff mbox series

Patch

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index b871590..a14efc8 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -18394,15 +18394,16 @@ 
   "TARGET_SHSTK"
{
   rtx fp, lab, stack;
-  rtx jump, label, reg_adj, reg_ssp, reg_minus, mem_buf, tmp, clob;
+  rtx flags, jump, noadj_label, inc_label, loop_label;
+  rtx reg_adj, reg_ssp, mem_buf, tmp, clob;
   machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
   /* Adjust the shadow stack pointer (ssp) to the value saved in the
      jmp_buf.  The saving was done in the builtin_setjmp_setup.  */
   if (flag_cf_protection & CF_RETURN)
     {
-      /* Get current shadow stack pointer.  The code below will check if
-              SHSTK feature is enabled.  If it's not enabled RDSSP instruction
+      /* 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);
       emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
@@ -18410,40 +18411,84 @@ 
                                ? 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))),
+                                                                                                3 * GET_MODE_SIZE (Pmode)));
       /* Compare through substraction the saved and the current ssp to decide
                if ssp has to be adjusted.  */
-      reg_minus = gen_reg_rtx (Pmode);
-      tmp = gen_rtx_SET (reg_minus, gen_rtx_MINUS (Pmode, reg_ssp, mem_buf));
+      reg_adj = gen_reg_rtx (Pmode);
+      tmp = gen_rtx_SET (reg_adj, gen_rtx_MINUS (Pmode, 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 over adjustment code.  */
-      label = gen_label_rtx ();
-      tmp = gen_rtx_REG (CCmode, FLAGS_REG);
-      tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
+      /* Compare and jump over adjustment code.  */
+      noadj_label = gen_label_rtx ();
+      flags = gen_rtx_REG (CCZmode, FLAGS_REG);
+      tmp = gen_rtx_EQ (VOIDmode, flags, const0_rtx);
       tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
-                                                                gen_rtx_LABEL_REF (VOIDmode, label),
+                                                               gen_rtx_LABEL_REF (VOIDmode, noadj_label),
                                                                 pc_rtx);
       jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
-      JUMP_LABEL (jump) = label;
+      JUMP_LABEL (jump) = noadj_label;
-      /* Adjust the ssp.  */
-      reg_adj = gen_reg_rtx (Pmode);
+      /* Compute the numebr of frames to adjust.  */
       tmp = gen_rtx_SET (reg_adj,
-                                              gen_rtx_LSHIFTRT (Pmode, negate_rtx (Pmode, reg_minus),
-                                                                                 GEN_INT (3)));
+                                             gen_rtx_LSHIFTRT (Pmode, negate_rtx (Pmode, reg_adj),
+                                                                                GEN_INT ((Pmode == SImode)
+                                                                                                 ? 2
+                                                                                                 : 3)));
       clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
       tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
       emit_insn (tmp);
+
+      /* Check if number of frames <= 255 so no loop is needed.  */
+      tmp = gen_rtx_COMPARE (CCmode, reg_adj, GEN_INT (255));
+      flags = gen_rtx_REG (CCmode, FLAGS_REG);
+      emit_insn (gen_rtx_SET (flags, tmp));
+
+      inc_label = gen_label_rtx ();
+      tmp = gen_rtx_LEU (VOIDmode, flags, const0_rtx);
+      tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
+                                                               gen_rtx_LABEL_REF (VOIDmode, inc_label),
+                                                               pc_rtx);
+      jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
+      JUMP_LABEL (jump) = inc_label;
+
+      /* Adjust the ssp in a loop.  */
+      loop_label = gen_label_rtx ();
+      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,
+                                                                                             reg_adj,
+                                                                                             GEN_INT (255)));
+      clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+      tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
+      emit_insn (tmp);
+
+      tmp = gen_rtx_COMPARE (CCmode, reg_adj, GEN_INT (255));
+      flags = gen_rtx_REG (CCmode, FLAGS_REG);
+      emit_insn (gen_rtx_SET (flags, tmp));
+
+      /* Jump to the loop label.  */
+      tmp = gen_rtx_GTU (VOIDmode, flags, const0_rtx);
+      tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
+                                                               gen_rtx_LABEL_REF (VOIDmode, loop_label),
+                                                               pc_rtx);
+      jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
+      JUMP_LABEL (jump) = loop_label;
+
+      emit_label (inc_label);
+      LABEL_NUSES (inc_label) = 1;
       emit_insn ((Pmode == SImode)
                                ? gen_incsspsi (reg_adj)
                                : gen_incsspdi (reg_adj));
-      emit_label (label);
-      LABEL_NUSES (label) = 1;
+      emit_label (noadj_label);
+      LABEL_NUSES (noadj_label) = 1;
     }
   /* This code is the same as in expand_buildin_longjmp.  */
diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-1.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-1.c
index 374d12a..d80ab05 100644
--- a/gcc/testsuite/gcc.target/i386/cet-sjlj-1.c
+++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-1.c
@@ -3,7 +3,7 @@ 
/* { dg-final { scan-assembler-times "endbr32" 4 { target ia32 } } } */
/* { dg-final { scan-assembler-times "endbr64" 4 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-times "rdssp\[dq]" 2 } } */
-/* { dg-final { scan-assembler-times "incssp\[dq]" 1 } } */
+/* { dg-final { scan-assembler-times "incssp\[dq]" 2 } } */
 /* Based on gcc.dg/setjmp-3.c.  */
diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-4.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-4.c
index d41406f..6a57ced 100644
--- a/gcc/testsuite/gcc.target/i386/cet-sjlj-4.c
+++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-4.c
@@ -3,7 +3,7 @@ 
/* { dg-final { scan-assembler-times "endbr32" 3 { target ia32 } } } */
/* { dg-final { scan-assembler-times "endbr64" 3 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-times "rdssp\[dq]" 2 } } */
-/* { dg-final { scan-assembler-times "incssp\[dq]" 1 } } */
+/* { dg-final { scan-assembler-times "incssp\[dq]" 2 } } */
 /* Based on gcc.dg/setjmp-3.c.  */
--
1.8.3.1