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> 2017-11-27 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/81248 PR tree-optimization/81248
...@@ -18394,15 +18394,16 @@ ...@@ -18394,15 +18394,16 @@
"TARGET_SHSTK" "TARGET_SHSTK"
{ {
rtx fp, lab, stack; 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); machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
/* Adjust the shadow stack pointer (ssp) to the value saved in the /* Adjust the shadow stack pointer (ssp) to the value saved in the
jmp_buf. The saving was done in the builtin_setjmp_setup. */ jmp_buf. The saving was done in the builtin_setjmp_setup. */
if (flag_cf_protection & CF_RETURN) if (flag_cf_protection & CF_RETURN)
{ {
/* Get current shadow stack pointer. The code below will check if /* Get the current shadow stack pointer. The code below will check if
SHSTK feature is enabled. If it's not enabled RDSSP instruction SHSTK feature is enabled. If it is not enabled the RDSSP instruction
is a NOP. */ is a NOP. */
reg_ssp = gen_reg_rtx (Pmode); reg_ssp = gen_reg_rtx (Pmode);
emit_insn (gen_rtx_SET (reg_ssp, const0_rtx)); emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
...@@ -18410,40 +18411,84 @@ ...@@ -18410,40 +18411,84 @@
? gen_rdsspsi (reg_ssp, reg_ssp) ? gen_rdsspsi (reg_ssp, reg_ssp)
: gen_rdsspdi (reg_ssp, reg_ssp)); : gen_rdsspdi (reg_ssp, reg_ssp));
mem_buf = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0], 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 /* Compare through substraction the saved and the current ssp to decide
if ssp has to be adjusted. */ if ssp has to be adjusted. */
reg_minus = gen_reg_rtx (Pmode); reg_adj = gen_reg_rtx (Pmode);
tmp = gen_rtx_SET (reg_minus, gen_rtx_MINUS (Pmode, reg_ssp, mem_buf)); 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)); clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob)); tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
emit_insn (tmp); emit_insn (tmp);
/* Jump over adjustment code. */ /* Compare and jump over adjustment code. */
label = gen_label_rtx (); noadj_label = gen_label_rtx ();
tmp = gen_rtx_REG (CCmode, FLAGS_REG); flags = gen_rtx_REG (CCZmode, FLAGS_REG);
tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); tmp = gen_rtx_EQ (VOIDmode, flags, const0_rtx);
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
gen_rtx_LABEL_REF (VOIDmode, label), gen_rtx_LABEL_REF (VOIDmode, noadj_label),
pc_rtx); pc_rtx);
jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)); jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
JUMP_LABEL (jump) = label; JUMP_LABEL (jump) = noadj_label;
/* Adjust the ssp. */ /* Compute the numebr of frames to adjust. */
reg_adj = gen_reg_rtx (Pmode);
tmp = gen_rtx_SET (reg_adj, tmp = gen_rtx_SET (reg_adj,
gen_rtx_LSHIFTRT (Pmode, negate_rtx (Pmode, reg_minus), gen_rtx_LSHIFTRT (Pmode, negate_rtx (Pmode, reg_adj),
GEN_INT (3))); 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)); clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob)); tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
emit_insn (tmp); 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) emit_insn ((Pmode == SImode)
? gen_incsspsi (reg_adj) ? gen_incsspsi (reg_adj)
: gen_incsspdi (reg_adj)); : gen_incsspdi (reg_adj));
emit_label (label); emit_label (noadj_label);
LABEL_NUSES (label) = 1; LABEL_NUSES (noadj_label) = 1;
} }
/* This code is the same as in expand_buildin_longjmp. */ /* 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> 2017-11-27 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/81248 PR tree-optimization/81248
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
/* { dg-final { scan-assembler-times "endbr32" 4 { target ia32 } } } */ /* { dg-final { scan-assembler-times "endbr32" 4 { target ia32 } } } */
/* { dg-final { scan-assembler-times "endbr64" 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 "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. */ /* Based on gcc.dg/setjmp-3.c. */
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
/* { dg-final { scan-assembler-times "endbr32" 3 { target ia32 } } } */ /* { dg-final { scan-assembler-times "endbr32" 3 { target ia32 } } } */
/* { dg-final { scan-assembler-times "endbr64" 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 "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. */ /* 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