> -----Original Message----- > From: Lu, Hongjiu > Sent: Sunday, April 15, 2018 12:58 PM > To: gcc-patches@gcc.gnu.org > Cc: Uros Bizjak <ubiz...@gmail.com>; Tsimbalist, Igor V > <igor.v.tsimbal...@intel.com> > Subject: [PATCH] i386: Add save_stack_nonlocal and restore_stack_nonlocal > > Define STACK_SAVEAREA_MODE to hold both shadow stack and stack > pointers. > Replace builtin_setjmp_setup and builtin_longjmp with save_stack_nonlocal > and restore_stack_nonlocal to support both builtin setjmp/longjmp as well > as non-local goto in nested functions. > > OK for trunk?
OK. Igor > H.J. > ---- > gcc/ > > PR target/85397 > * config/i386/i386.h (STACK_SAVEAREA_MODE): New. > * config/i386/i386.md (builtin_setjmp_setup): Removed. > (builtin_longjmp): Likewise. > (save_stack_nonlocal): New pattern. > (restore_stack_nonlocal): Likewise. > > gcc/testsuite/ > > PR target/85397 > * gcc.dg/torture/pr85397-1.c: New test. > * gcc.target/i386/cet-sjlj-6a.c: Adjusted. > * gcc.target/i386/cet-sjlj-6b.c: Likewise. > --- > gcc/config/i386/i386.h | 11 +++ > gcc/config/i386/i386.md | 107 +++++++++++++----------- > ---- > gcc/testsuite/gcc.dg/torture/pr85397-1.c | 29 ++++++++ > gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c | 4 +- > gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c | 4 +- > 5 files changed, 92 insertions(+), 63 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/torture/pr85397-1.c > > diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h > index c7f9b4551b3..c45d22cae98 100644 > --- a/gcc/config/i386/i386.h > +++ b/gcc/config/i386/i386.h > @@ -1943,6 +1943,17 @@ do { > \ > between pointers and any other objects of this machine mode. */ > #define Pmode (ix86_pmode == PMODE_DI ? DImode : SImode) > > +/* Supply a definition of STACK_SAVEAREA_MODE for emit_stack_save. > + NONLOCAL needs space to save both shadow stack and stack pointers. > + > + FIXME: We only need to save and restore stack pointer in ptr_mode. > + But expand_builtin_setjmp_setup and expand_builtin_longjmp use Pmode > + to save and restore stack pointer. See > + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84150 > + */ > +#define STACK_SAVEAREA_MODE(LEVEL) \ > + ((LEVEL) == SAVE_NONLOCAL ? (TARGET_64BIT ? TImode : DImode) : > Pmode) > + > /* Specify the machine mode that bounds have. */ > #define BNDmode (ix86_pmode == PMODE_DI ? BND64mode : > BND32mode) > > diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md > index 352212094ec..841d0a77ecc 100644 > --- a/gcc/config/i386/i386.md > +++ b/gcc/config/i386/i386.md > @@ -18485,29 +18485,6 @@ > "* return output_probe_stack_range (operands[0], operands[2]);" > [(set_attr "type" "multi")]) > > -/* Additional processing for builtin_setjmp. Store the shadow stack pointer > - as a forth element in jmpbuf. */ > -(define_expand "builtin_setjmp_setup" > - [(match_operand 0 "address_operand")] > - "TARGET_SHSTK" > -{ > - if (flag_cf_protection & CF_RETURN) > - { > - rtx mem, reg_ssp; > - > - 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 ((word_mode == SImode) > - ? gen_rdsspsi (reg_ssp) > - : gen_rdsspdi (reg_ssp)); > - emit_move_insn (mem, reg_ssp); > - } > - DONE; > -}) > - > (define_expand "builtin_setjmp_receiver" > [(label_ref (match_operand 0))] > "!TARGET_64BIT && flag_pic" > @@ -18528,19 +18505,46 @@ > DONE; > }) > > -(define_expand "builtin_longjmp" > - [(match_operand 0 "address_operand")] > - "TARGET_SHSTK" > +(define_expand "save_stack_nonlocal" > + [(set (match_operand 0 "memory_operand") > + (match_operand 1 "register_operand"))] > + "" > { > - rtx fp, lab, stack; > - 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); > + rtx stack_slot; > + if (TARGET_SHSTK && (flag_cf_protection & CF_RETURN)) > + { > + /* Copy shadow stack pointer to the first slot and stack ppointer > + to the second slot. */ > + rtx ssp_slot = adjust_address (operands[0], word_mode, 0); > + stack_slot = adjust_address (operands[0], Pmode, UNITS_PER_WORD); > + rtx ssp = gen_reg_rtx (word_mode); > + emit_insn ((word_mode == SImode) > + ? gen_rdsspsi (ssp) > + : gen_rdsspdi (ssp)); > + emit_move_insn (ssp_slot, ssp); > + } > + else > + stack_slot = adjust_address (operands[0], Pmode, 0); > + emit_move_insn (stack_slot, operands[1]); > + DONE; > +}) > > - /* 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) > +(define_expand "restore_stack_nonlocal" > + [(set (match_operand 0 "register_operand" "") > + (match_operand 1 "memory_operand" ""))] > + "" > +{ > + rtx stack_slot; > + if (TARGET_SHSTK && (flag_cf_protection & CF_RETURN)) > { > + /* Restore shadow stack pointer from the first slot and stack > + pointer from the second slot. */ > + rtx ssp_slot = adjust_address (operands[1], word_mode, 0); > + stack_slot = adjust_address (operands[1], Pmode, UNITS_PER_WORD); > + > + rtx flags, jump, noadj_label, inc_label, loop_label; > + rtx reg_adj, reg_ssp, tmp, clob; > + > /* 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. */ > @@ -18549,13 +18553,11 @@ > emit_insn ((word_mode == SImode) > ? gen_rdsspsi (reg_ssp) > : gen_rdsspdi (reg_ssp)); > - 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. */ > - tmp = gen_rtx_SET (reg_ssp, gen_rtx_MINUS (word_mode, reg_ssp, > mem_buf)); > + tmp = gen_rtx_SET (reg_ssp, gen_rtx_MINUS (word_mode, reg_ssp, > + ssp_slot)); > clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, > FLAGS_REG)); > tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob)); > emit_insn (tmp); > @@ -18595,14 +18597,17 @@ > jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)); > JUMP_LABEL (jump) = inc_label; > > + rtx reg_255 = gen_reg_rtx (word_mode); > + emit_move_insn (reg_255, GEN_INT (255)); > + > /* Adjust the ssp in a loop. */ > loop_label = gen_label_rtx (); > emit_label (loop_label); > LABEL_NUSES (loop_label) = 1; > > emit_insn ((word_mode == SImode) > - ? gen_incsspsi (reg_ssp) > - : gen_incsspdi (reg_ssp)); > + ? gen_incsspsi (reg_255) > + : gen_incsspdi (reg_255)); > tmp = gen_rtx_SET (reg_adj, gen_rtx_MINUS (ptr_mode, > reg_adj, > GEN_INT (255))); > @@ -18631,26 +18636,10 @@ > emit_label (noadj_label); > LABEL_NUSES (noadj_label) = 1; > } > - > - /* This code is the same as in expand_buildin_longjmp. */ > - 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 (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); > - > - emit_use (hard_frame_pointer_rtx); > - emit_use (stack_pointer_rtx); > - emit_indirect_jump (lab); > + else > + stack_slot = adjust_address (operands[1], Pmode, 0); > + emit_move_insn (operands[0], stack_slot); > + DONE; > }) > > > diff --git a/gcc/testsuite/gcc.dg/torture/pr85397-1.c > b/gcc/testsuite/gcc.dg/torture/pr85397-1.c > new file mode 100644 > index 00000000000..65085240266 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/torture/pr85397-1.c > @@ -0,0 +1,29 @@ > +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ > +/* { dg-require-effective-target cet } */ > +/* { dg-additional-options "-fcf-protection -mcet" } */ > + > +#define DEPTH 1000 > + > +int > +x(int a) > +{ > + __label__ xlab; > + void y(int a) > + { > + if (a==0) > + goto xlab; > + y (a-1); > + } > + y (a); > + xlab:; > + return a; > +} > + > +int > +main () > +{ > + if (x (DEPTH) != DEPTH) > + __builtin_abort (); > + > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c > b/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c > index 8410ff99b47..87fe2e6dc67 100644 > --- a/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c > +++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c > @@ -2,8 +2,8 @@ > /* { 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 "movq\t.*buf\\+8" 1 } } */ > +/* { dg-final { scan-assembler-times "subq\tbuf\\+8" 1 } } */ > /* { dg-final { scan-assembler-times "shrl\t\\\$3," 1 } } */ > /* { dg-final { scan-assembler-times "rdsspq" 2 } } */ > /* { dg-final { scan-assembler-times "incsspq" 2 } } */ > diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c > b/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c > index ce111631ac1..b3866d52946 100644 > --- a/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c > +++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c > @@ -1,8 +1,8 @@ > /* { 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 "movq\t.*buf\\+16" 1 } } */ > +/* { dg-final { scan-assembler-times "subq\tbuf\\+16" 1 } } */ > /* { dg-final { scan-assembler-times "shrl\t\\\$3," 1 } } */ > /* { dg-final { scan-assembler-times "rdsspq" 2 } } */ > /* { dg-final { scan-assembler-times "incsspq" 2 } } */ > -- > 2.14.3