* [i386] PR83109 [CET] improper code generation for builtin_longjmp with -fcf-protection -mcet
@ 2017-11-27 3:55 Tsimbalist, Igor V
2017-11-27 8:41 ` Uros Bizjak
0 siblings, 1 reply; 2+ messages in thread
From: Tsimbalist, Igor V @ 2017-11-27 3:55 UTC (permalink / raw)
To: gcc-patches; +Cc: Uros Bizjak, Tsimbalist, Igor V
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 +-
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
Ok for trunk?
Igor
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [i386] PR83109 [CET] improper code generation for builtin_longjmp with -fcf-protection -mcet
2017-11-27 3:55 [i386] PR83109 [CET] improper code generation for builtin_longjmp with -fcf-protection -mcet Tsimbalist, Igor V
@ 2017-11-27 8:41 ` Uros Bizjak
0 siblings, 0 replies; 2+ messages in thread
From: Uros Bizjak @ 2017-11-27 8:41 UTC (permalink / raw)
To: Tsimbalist, Igor V; +Cc: gcc-patches
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.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2017-11-27 8:35 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-27 3:55 [i386] PR83109 [CET] improper code generation for builtin_longjmp with -fcf-protection -mcet Tsimbalist, Igor V
2017-11-27 8:41 ` Uros Bizjak
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).