From: Igor Tsimbalist Date: Fri, 2 Feb 2018 10:06:39 +0000 (+0100) Subject: PR84066 Wrong shadow stack register size is saved for x32 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e8a5a6f6e2e4e06b8e8d357712277fb54ed71b07;p=gcc.git PR84066 Wrong shadow stack register size is saved for x32 x32 is a 64-bit process with 32-bit software pointer and kernel may place x32 shadow stack above 4GB. We need to save and restore 64-bit shadow stack register for x32. builtin jmp buf size is 5 pointers. We have space to save 64-bit shadow stack pointers: 32-bit SP, 32-bit FP, 32-bit IP, 64-bit SSP for x32. PR target/84066 * gcc/config/i386/i386.md: Replace Pmode with word_mode in builtin_setjmp_setup and builtin_longjmp to support x32. * gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c: New test. * gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c: Likewise. From-SVN: r257326 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c01487b8420..d89236958c9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2018-02-02 Igor Tsimbalist + + PR target/84066 + * config/i386/i386.md: Replace Pmode with word_mode in + builtin_setjmp_setup and builtin_longjmp to support x32. + 2018-02-01 Peter Bergner PR target/56010 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index c08e4f55cff..a4832bf696f 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -18385,13 +18385,14 @@ { rtx mem, reg_ssp; - mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0], - 3 * GET_MODE_SIZE (Pmode))); - reg_ssp = gen_reg_rtx (Pmode); + mem = gen_rtx_MEM (word_mode, + plus_constant (Pmode, operands[0], + 3 * GET_MODE_SIZE (ptr_mode))); + reg_ssp = gen_reg_rtx (word_mode); emit_insn (gen_rtx_SET (reg_ssp, const0_rtx)); - emit_insn ((Pmode == SImode) - ? gen_rdsspsi (reg_ssp, reg_ssp) - : gen_rdsspdi (reg_ssp, reg_ssp)); + emit_insn ((word_mode == SImode) + ? gen_rdsspsi (reg_ssp, reg_ssp) + : gen_rdsspdi (reg_ssp, reg_ssp)); emit_move_insn (mem, reg_ssp); } DONE; @@ -18433,18 +18434,18 @@ /* 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); + reg_ssp = gen_reg_rtx (word_mode); emit_insn (gen_rtx_SET (reg_ssp, const0_rtx)); - emit_insn ((Pmode == SImode) + emit_insn ((word_mode == SImode) ? 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))); + mem_buf = gen_rtx_MEM (word_mode, + plus_constant (Pmode, operands[0], + 3 * GET_MODE_SIZE (ptr_mode))); /* Compare through substraction the saved and the current ssp to decide if ssp has to be adjusted. */ - reg_adj = gen_reg_rtx (Pmode); - tmp = gen_rtx_SET (reg_adj, gen_rtx_MINUS (Pmode, reg_ssp, mem_buf)); + tmp = gen_rtx_SET (reg_ssp, gen_rtx_MINUS (word_mode, 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); @@ -18460,9 +18461,11 @@ JUMP_LABEL (jump) = noadj_label; /* Compute the numebr of frames to adjust. */ + reg_adj = gen_lowpart (ptr_mode, reg_ssp); tmp = gen_rtx_SET (reg_adj, - gen_rtx_LSHIFTRT (Pmode, negate_rtx (Pmode, reg_adj), - GEN_INT ((Pmode == SImode) + gen_rtx_LSHIFTRT (ptr_mode, + negate_rtx (ptr_mode, reg_adj), + GEN_INT ((word_mode == SImode) ? 2 : 3))); clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG)); @@ -18487,10 +18490,10 @@ 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, + emit_insn ((word_mode == SImode) + ? gen_incsspsi (reg_ssp) + : gen_incsspdi (reg_ssp)); + tmp = gen_rtx_SET (reg_adj, gen_rtx_MINUS (ptr_mode, reg_adj, GEN_INT (255))); clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG)); @@ -18511,25 +18514,27 @@ emit_label (inc_label); LABEL_NUSES (inc_label) = 1; - emit_insn ((Pmode == SImode) - ? gen_incsspsi (reg_adj) - : gen_incsspdi (reg_adj)); + emit_insn ((word_mode == SImode) + ? gen_incsspsi (reg_ssp) + : gen_incsspdi (reg_ssp)); emit_label (noadj_label); LABEL_NUSES (noadj_label) = 1; } /* This code is the same as in expand_buildin_longjmp. */ - fp = gen_rtx_MEM (Pmode, operands[0]); - lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0], - GET_MODE_SIZE (Pmode))); + fp = gen_rtx_MEM (ptr_mode, operands[0]); + lab = gen_rtx_MEM (ptr_mode, plus_constant (Pmode, operands[0], + GET_MODE_SIZE (ptr_mode))); stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, operands[0], - 2 * GET_MODE_SIZE (Pmode))); + 2 * GET_MODE_SIZE (ptr_mode))); lab = copy_to_reg (lab); emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))); emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx)); + if (GET_MODE (fp) != Pmode) + fp = convert_to_mode (Pmode, fp, 1); emit_move_insn (hard_frame_pointer_rtx, fp); emit_stack_restore (SAVE_NONLOCAL, stack); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ec87b8bffc2..15c3e06ff63 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-02-02 Igor Tsimbalist + + PR target/84066 + * gcc.target/i386/cet-sjlj-6a.c: New test. + * gcc.target/i386/cet-sjlj-6b.c: Likewise. + 2018-02-01 Marek Polacek PR c++/84125 diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c new file mode 100644 index 00000000000..8410ff99b47 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c @@ -0,0 +1,21 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-require-effective-target maybe_x32 } */ +/* { dg-options "-O -maddress-mode=short -fcf-protection -mcet -mx32" } */ +/* { dg-final { scan-assembler-times "endbr64" 2 } } */ +/* { dg-final { scan-assembler-times "movq\t.*buf\\+12" 1 } } */ +/* { dg-final { scan-assembler-times "subq\tbuf\\+12" 1 } } */ +/* { dg-final { scan-assembler-times "shrl\t\\\$3," 1 } } */ +/* { dg-final { scan-assembler-times "rdsspq" 2 } } */ +/* { dg-final { scan-assembler-times "incsspq" 2 } } */ + +void *buf[5]; + +void raise0(void) +{ + __builtin_longjmp (buf, 1); +} + +void execute(int cmd) +{ + __builtin_setjmp (buf); +} diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c new file mode 100644 index 00000000000..ce111631ac1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O -maddress-mode=long -fcf-protection -mcet -mx32" } */ +/* { dg-final { scan-assembler-times "endbr64" 2 } } */ +/* { dg-final { scan-assembler-times "movq\t.*buf\\+12" 1 } } */ +/* { dg-final { scan-assembler-times "subq\tbuf\\+12" 1 } } */ +/* { dg-final { scan-assembler-times "shrl\t\\\$3," 1 } } */ +/* { dg-final { scan-assembler-times "rdsspq" 2 } } */ +/* { dg-final { scan-assembler-times "incsspq" 2 } } */ + +#include "cet-sjlj-6a.c"