Commit 5e1e91c4 by H.J. Lu Committed by H.J. Lu

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.

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.

From-SVN: r259500
parent 2130a2af
2018-04-19 H.J. Lu <hongjiu.lu@intel.com> 2018-04-19 H.J. Lu <hongjiu.lu@intel.com>
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.
2018-04-19 H.J. Lu <hongjiu.lu@intel.com>
PR target/85404 PR target/85404
* config/i386/cet.c (file_end_indicate_exec_stack_and_cet): * config/i386/cet.c (file_end_indicate_exec_stack_and_cet):
Replace ASM_OUTPUT_LABEL with fprintf. Replace ASM_OUTPUT_LABEL with fprintf.
......
...@@ -1948,6 +1948,17 @@ do { \ ...@@ -1948,6 +1948,17 @@ do { \
between pointers and any other objects of this machine mode. */ between pointers and any other objects of this machine mode. */
#define Pmode (ix86_pmode == PMODE_DI ? DImode : SImode) #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. */ /* Specify the machine mode that bounds have. */
#define BNDmode (ix86_pmode == PMODE_DI ? BND64mode : BND32mode) #define BNDmode (ix86_pmode == PMODE_DI ? BND64mode : BND32mode)
......
...@@ -18487,29 +18487,6 @@ ...@@ -18487,29 +18487,6 @@
"* return output_probe_stack_range (operands[0], operands[2]);" "* return output_probe_stack_range (operands[0], operands[2]);"
[(set_attr "type" "multi")]) [(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" (define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0))] [(label_ref (match_operand 0))]
"!TARGET_64BIT && flag_pic" "!TARGET_64BIT && flag_pic"
...@@ -18530,19 +18507,46 @@ ...@@ -18530,19 +18507,46 @@
DONE; DONE;
}) })
(define_expand "builtin_longjmp" (define_expand "save_stack_nonlocal"
[(match_operand 0 "address_operand")] [(set (match_operand 0 "memory_operand")
"TARGET_SHSTK" (match_operand 1 "register_operand"))]
""
{ {
rtx fp, lab, stack; rtx stack_slot;
rtx flags, jump, noadj_label, inc_label, loop_label; if ((flag_cf_protection & CF_RETURN))
rtx reg_adj, reg_ssp, mem_buf, tmp, clob; {
machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); /* 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 (define_expand "restore_stack_nonlocal"
jmp_buf. The saving was done in the builtin_setjmp_setup. */ [(set (match_operand 0 "register_operand" "")
if (flag_cf_protection & CF_RETURN) (match_operand 1 "memory_operand" ""))]
""
{
rtx stack_slot;
if ((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 /* Get the current shadow stack pointer. The code below will check if
SHSTK feature is enabled. If it is not enabled the RDSSP instruction SHSTK feature is enabled. If it is not enabled the RDSSP instruction
is a NOP. */ is a NOP. */
...@@ -18551,13 +18555,11 @@ ...@@ -18551,13 +18555,11 @@
emit_insn ((word_mode == SImode) emit_insn ((word_mode == SImode)
? gen_rdsspsi (reg_ssp) ? gen_rdsspsi (reg_ssp)
: gen_rdsspdi (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 /* Compare through substraction the saved and the current ssp to decide
if ssp has to be adjusted. */ 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)); 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);
...@@ -18597,14 +18599,17 @@ ...@@ -18597,14 +18599,17 @@
jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)); jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
JUMP_LABEL (jump) = inc_label; 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. */ /* Adjust the ssp in a loop. */
loop_label = gen_label_rtx (); loop_label = gen_label_rtx ();
emit_label (loop_label); emit_label (loop_label);
LABEL_NUSES (loop_label) = 1; LABEL_NUSES (loop_label) = 1;
emit_insn ((word_mode == SImode) emit_insn ((word_mode == SImode)
? gen_incsspsi (reg_ssp) ? gen_incsspsi (reg_255)
: gen_incsspdi (reg_ssp)); : gen_incsspdi (reg_255));
tmp = gen_rtx_SET (reg_adj, gen_rtx_MINUS (ptr_mode, tmp = gen_rtx_SET (reg_adj, gen_rtx_MINUS (ptr_mode,
reg_adj, reg_adj,
GEN_INT (255))); GEN_INT (255)));
...@@ -18633,26 +18638,10 @@ ...@@ -18633,26 +18638,10 @@
emit_label (noadj_label); emit_label (noadj_label);
LABEL_NUSES (noadj_label) = 1; LABEL_NUSES (noadj_label) = 1;
} }
else
/* This code is the same as in expand_buildin_longjmp. */ stack_slot = adjust_address (operands[1], Pmode, 0);
fp = gen_rtx_MEM (ptr_mode, operands[0]); emit_move_insn (operands[0], stack_slot);
lab = gen_rtx_MEM (ptr_mode, plus_constant (Pmode, operands[0], DONE;
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);
}) })
......
2018-04-19 H.J. Lu <hongjiu.lu@intel.com> 2018-04-19 H.J. Lu <hongjiu.lu@intel.com>
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.
2018-04-19 H.J. Lu <hongjiu.lu@intel.com>
PR target/85404 PR target/85404
* gcc.target/i386/pr85404.c: New test. * gcc.target/i386/pr85404.c: New test.
......
/* { 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;
}
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
/* { dg-require-effective-target maybe_x32 } */ /* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O -maddress-mode=short -fcf-protection -mcet -mx32" } */ /* { dg-options "-O -maddress-mode=short -fcf-protection -mcet -mx32" } */
/* { dg-final { scan-assembler-times "endbr64" 2 } } */ /* { dg-final { scan-assembler-times "endbr64" 2 } } */
/* { dg-final { scan-assembler-times "movq\t.*buf\\+12" 1 } } */ /* { dg-final { scan-assembler-times "movq\t.*buf\\+8" 1 } } */
/* { dg-final { scan-assembler-times "subq\tbuf\\+12" 1 } } */ /* { dg-final { scan-assembler-times "subq\tbuf\\+8" 1 } } */
/* { dg-final { scan-assembler-times "shrl\t\\\$3," 1 } } */ /* { dg-final { scan-assembler-times "shrl\t\\\$3," 1 } } */
/* { dg-final { scan-assembler-times "rdsspq" 2 } } */ /* { dg-final { scan-assembler-times "rdsspq" 2 } } */
/* { dg-final { scan-assembler-times "incsspq" 2 } } */ /* { dg-final { scan-assembler-times "incsspq" 2 } } */
......
/* { dg-do compile { target { ! ia32 } } } */ /* { dg-do compile { target { ! ia32 } } } */
/* { dg-options "-O -maddress-mode=long -fcf-protection -mcet -mx32" } */ /* { dg-options "-O -maddress-mode=long -fcf-protection -mcet -mx32" } */
/* { dg-final { scan-assembler-times "endbr64" 2 } } */ /* { dg-final { scan-assembler-times "endbr64" 2 } } */
/* { dg-final { scan-assembler-times "movq\t.*buf\\+12" 1 } } */ /* { dg-final { scan-assembler-times "movq\t.*buf\\+16" 1 } } */
/* { dg-final { scan-assembler-times "subq\tbuf\\+12" 1 } } */ /* { dg-final { scan-assembler-times "subq\tbuf\\+16" 1 } } */
/* { dg-final { scan-assembler-times "shrl\t\\\$3," 1 } } */ /* { dg-final { scan-assembler-times "shrl\t\\\$3," 1 } } */
/* { dg-final { scan-assembler-times "rdsspq" 2 } } */ /* { dg-final { scan-assembler-times "rdsspq" 2 } } */
/* { dg-final { scan-assembler-times "incsspq" 2 } } */ /* { dg-final { scan-assembler-times "incsspq" 2 } } */
......
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