+2020-02-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR libgcc/85334
+ * config/i386/shadow-stack-unwind.h (_Unwind_Frames_Increment):
+ New.
+
2020-02-10 Richard Earnshaw <rearnsha@arm.com>
PR target/91913
+2020-02-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR libgcc/85334
+ * g++.target/i386/pr85334-1.C: New test.
+ * g++.target/i386/pr85334-2.C: Likewise.
+
2020-02-10 Jakub Jelinek <jakub@redhat.com>
PR other/93641
--- /dev/null
+// { dg-do run }
+// { dg-require-effective-target cet }
+// { dg-additional-options "-fexceptions -fnon-call-exceptions -fcf-protection" }
+
+// Delta between numbers of call stacks of pr85334-1.C and pr85334-2.C is 1.
+
+#include <signal.h>
+#include <stdlib.h>
+
+void sighandler (int signo, siginfo_t * si, void * uc)
+{
+ throw (5);
+}
+
+char *
+__attribute ((noinline, noclone))
+dosegv ()
+{
+ * ((volatile int *)0) = 12;
+ return 0;
+}
+
+int
+__attribute ((noinline, noclone))
+func2 ()
+{
+ try {
+ dosegv ();
+ }
+ catch (int x) {
+ return (x != 5);
+ }
+ return 1;
+}
+
+int
+__attribute ((noinline, noclone))
+func1 ()
+{
+ return func2 ();
+}
+
+int main ()
+{
+ struct sigaction sa;
+ int status;
+
+ sa.sa_sigaction = sighandler;
+ sa.sa_flags = SA_SIGINFO;
+
+ status = sigaction (SIGSEGV, & sa, NULL);
+ status = sigaction (SIGBUS, & sa, NULL);
+
+ return func1 ();
+}
--- /dev/null
+// { dg-do run }
+// { dg-require-effective-target cet }
+// { dg-additional-options "-fexceptions -fnon-call-exceptions -fcf-protection" }
+
+// Delta between numbers of call stacks of pr85334-1.C and pr85334-2.C is 1.
+
+#include <signal.h>
+#include <stdlib.h>
+
+void sighandler (int signo, siginfo_t * si, void * uc)
+{
+ throw (5);
+}
+
+char *
+__attribute ((noinline, noclone))
+dosegv ()
+{
+ * ((volatile int *)0) = 12;
+ return 0;
+}
+
+int
+__attribute ((noinline, noclone))
+func1 ()
+{
+ try {
+ dosegv ();
+ }
+ catch (int x) {
+ return (x != 5);
+ }
+ return 1;
+}
+
+int main ()
+{
+ struct sigaction sa;
+ int status;
+
+ sa.sa_sigaction = sighandler;
+ sa.sa_flags = SA_SIGINFO;
+
+ status = sigaction (SIGSEGV, & sa, NULL);
+ status = sigaction (SIGBUS, & sa, NULL);
+
+ return func1 ();
+}
} \
} \
while (0)
+
+/* Linux CET kernel places a restore token on shadow stack for signal
+ handler to enhance security. The restore token is 8 byte and aligned
+ to 8 bytes. It is usually transparent to user programs since kernel
+ will pop the restore token when signal handler returns. But when an
+ exception is thrown from a signal handler, now we need to pop the
+ restore token from shadow stack. For x86-64, we just need to treat
+ the signal frame as normal frame. For i386, we need to search for
+ the restore token to check if the original shadow stack is 8 byte
+ aligned. If the original shadow stack is 8 byte aligned, we just
+ need to pop 2 slots, one restore token, from shadow stack. Otherwise,
+ we need to pop 3 slots, one restore token + 4 byte padding, from
+ shadow stack. */
+#ifndef __x86_64__
+#undef _Unwind_Frames_Increment
+#define _Unwind_Frames_Increment(context, frames) \
+ if (_Unwind_IsSignalFrame (context)) \
+ do \
+ { \
+ _Unwind_Word ssp, prev_ssp, token; \
+ ssp = _get_ssp (); \
+ if (ssp != 0) \
+ { \
+ /* Align shadow stack pointer to the next \
+ 8 byte aligned boundary. */ \
+ ssp = (ssp + 4) & ~7; \
+ do \
+ { \
+ /* Look for a restore token. */ \
+ token = (*(_Unwind_Word *) (ssp - 8)); \
+ prev_ssp = token & ~7; \
+ if (prev_ssp == ssp) \
+ break; \
+ ssp += 8; \
+ } \
+ while (1); \
+ frames += (token & 0x4) ? 3 : 2; \
+ } \
+ } \
+ while (0); \
+ else \
+ frames++;
+#endif