From 39335d1486c5f39182bd0cca6af52a49386319cb Mon Sep 17 00:00:00 2001 From: Igor Tsimbalist Date: Mon, 27 Nov 2017 12:54:17 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 5 ++ gcc/config/i386/i386.md | 81 +++++++++++++++++----- gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/gcc.target/i386/cet-sjlj-1.c | 2 +- gcc/testsuite/gcc.target/i386/cet-sjlj-4.c | 2 +- 5 files changed, 76 insertions(+), 20 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cfb13935d19..eaf26485a13 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2017-11-27 Igor Tsimbalist + + PR target/83109 + * config/i386/i386.md: Add a loop with incssp. + 2017-11-27 Martin Jambor PR tree-optimization/81248 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b8715902c35..a14efc8d0b6 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/ChangeLog b/gcc/testsuite/ChangeLog index 0b0bac7a4d7..04788b63877 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2017-11-27 Igor Tsimbalist + + 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 PR tree-optimization/81248 diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-1.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-1.c index 374d12aa745..d80ab051c37 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 d41406fde1f..6a57cede208 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. */ -- 2.30.2