aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2018-04-19 16:36:34 +0000
committerH.J. Lu <hjl@gcc.gnu.org>2018-04-19 09:36:34 -0700
commit5e1e91c4fdd5946556e8d4e4520dbb643a2e7b5e (patch)
treeed7f9067c97293bce49d41b27ec4b0d75a7b7b0e /gcc
parent2130a2afe7e45001936bb55b8ba1340c54953bbd (diff)
downloadgcc-5e1e91c4fdd5946556e8d4e4520dbb643a2e7b5e.zip
gcc-5e1e91c4fdd5946556e8d4e4520dbb643a2e7b5e.tar.gz
gcc-5e1e91c4fdd5946556e8d4e4520dbb643a2e7b5e.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/i386/i386.h11
-rw-r--r--gcc/config/i386/i386.md107
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr85397-1.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-sjlj-6a.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c4
7 files changed, 108 insertions, 63 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 89a4f3f..6d676a1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,14 @@
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
* config/i386/cet.c (file_end_indicate_exec_stack_and_cet):
Replace ASM_OUTPUT_LABEL with fprintf.
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 0b0f0d2..3734ba1 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -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)
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index ae1fea1..33e8060 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -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"
@@ -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. */
@@ -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);
@@ -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)));
@@ -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;
})
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d09c567..a00911d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,12 @@
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
* gcc.target/i386/pr85404.c: New test.
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 0000000..6508524
--- /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 8410ff9..87fe2e6 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 ce11163..b3866d5 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 } } */