Skip to content

Commit

Permalink
i386: Add save_stack_nonlocal and restore_stack_nonlocal
Browse files Browse the repository at this point in the history
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.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@259500 138bc75d-0d04-0410-961f-82ee72b054a4
  • Loading branch information
hjl committed Apr 19, 2018
1 parent cc7817c commit a97c3d5
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 63 deletions.
9 changes: 9 additions & 0 deletions gcc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
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
Expand Down
11 changes: 11 additions & 0 deletions gcc/config/i386/i386.h
Original file line number Diff line number Diff line change
Expand Up @@ -1948,6 +1948,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)

Expand Down
107 changes: 48 additions & 59 deletions gcc/config/i386/i386.md
Original file line number Diff line number Diff line change
Expand Up @@ -18487,29 +18487,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"
Expand All @@ -18530,19 +18507,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 ((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 ((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. */
Expand All @@ -18551,13 +18555,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);
Expand Down Expand Up @@ -18597,14 +18599,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)));
Expand Down Expand Up @@ -18633,26 +18638,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;
})


Expand Down
7 changes: 7 additions & 0 deletions gcc/testsuite/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
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
Expand Down
29 changes: 29 additions & 0 deletions gcc/testsuite/gcc.dg/torture/pr85397-1.c
Original file line number Diff line number Diff line change
@@ -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;
}
4 changes: 2 additions & 2 deletions gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 } } */
Expand Down
4 changes: 2 additions & 2 deletions gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c
Original file line number Diff line number Diff line change
@@ -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 } } */
Expand Down

0 comments on commit a97c3d5

Please sign in to comment.