Commit 39335d14 by Igor Tsimbalist Committed by Igor Tsimbalist

Fix code generation for buildtin_longjmp with CET.

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.

From-SVN: r255164
parent be025a2d
2017-11-27 Igor Tsimbalist <igor.v.tsimbalist@intel.com>
PR target/83109
* config/i386/i386.md: Add a loop with incssp.
2017-11-27 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/81248
......@@ -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. */
......
2017-11-27 Igor Tsimbalist <igor.v.tsimbalist@intel.com>
PR target/83109
* testsuite/gcc.target/i386/cet-sjlj-1.c: Fix test.
* testsuite/gcc.target/i386/cet-sjlj-4.c: Likewise.
2017-11-27 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/81248
......
......@@ -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. */
......
......@@ -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. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment