aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/builtins.c11
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr64242.c30
4 files changed, 50 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bda587b..6c57ed0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2018-11-30 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR middle-end/64242
+ * builtins.c (expand_builtin_longjmp): Use a temporary when restoring
+ the frame pointer.
+ (expand_builtin_nonlocal_goto): Likewise.
+
2018-11-30 David Malcolm <dmalcolm@redhat.com>
* diagnostic-core.h (emit_diagnostic): New decl.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 537228c..669e548 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1143,8 +1143,11 @@ expand_builtin_longjmp (rtx buf_addr, rtx value)
emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
- emit_move_insn (hard_frame_pointer_rtx, fp);
+ /* Restore the frame pointer and stack pointer. We must use a
+ temporary since the setjmp buffer may be a local. */
+ fp = copy_to_reg (fp);
emit_stack_restore (SAVE_NONLOCAL, stack);
+ emit_move_insn (hard_frame_pointer_rtx, fp);
emit_use (hard_frame_pointer_rtx);
emit_use (stack_pointer_rtx);
@@ -1287,9 +1290,11 @@ expand_builtin_nonlocal_goto (tree exp)
emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
- /* Restore frame pointer for containing function. */
- emit_move_insn (hard_frame_pointer_rtx, r_fp);
+ /* Restore the frame pointer and stack pointer. We must use a
+ temporary since the setjmp buffer may be a local. */
+ r_fp = copy_to_reg (r_fp);
emit_stack_restore (SAVE_NONLOCAL, r_sp);
+ emit_move_insn (hard_frame_pointer_rtx, r_fp);
/* USE of hard_frame_pointer_rtx added for consistency;
not clear if really needed. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c5b5513..903f7cb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-11-30 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR middle-end/64242
+ * gcc.c-torture/execute/pr64242.c: New test.
+
2018-11-30 David Malcolm <dmalcolm@redhat.com>
* g++.dg/parse/missing-parens-fixit.C: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr64242.c b/gcc/testsuite/gcc.c-torture/execute/pr64242.c
new file mode 100644
index 0000000..72dab57
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr64242.c
@@ -0,0 +1,30 @@
+/* { dg-require-effective-target indirect_jumps } */
+
+extern void abort (void);
+
+__attribute ((noinline)) void
+broken_longjmp(void *p)
+{
+ void *buf[5];
+ __builtin_memcpy (buf, p, 5 * sizeof (void*));
+ /* Corrupts stack pointer... */
+ __builtin_longjmp (buf, 1);
+}
+
+volatile int x = 0;
+volatile void *p;
+int
+main (void)
+{
+ void *buf[5];
+ p = __builtin_alloca (x);
+
+ if (!__builtin_setjmp (buf))
+ broken_longjmp (buf);
+
+ /* Fails if stack pointer corrupted. */
+ if (p != __builtin_alloca (x))
+ abort();
+
+ return 0;
+}