1 /* PR target/94514. Unwind across mixed pac-ret and non-pac-ret frames.  */
2 /* { dg-do run } */
3 /* { dg-require-effective-target lp64 } */
4 /* { dg-options "-fexceptions -O2" } */
5 
6 #include <unwind.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 
10 #define die() \
11   do { \
12     printf ("%s:%d: reached unexpectedly.\n", __FILE__, __LINE__); \
13     fflush (stdout); \
14     abort (); \
15   } while (0)
16 
17 static struct _Unwind_Exception exc;
18 
19 static _Unwind_Reason_Code
force_unwind_stop(int version,_Unwind_Action actions,_Unwind_Exception_Class exc_class,struct _Unwind_Exception * exc_obj,struct _Unwind_Context * context,void * stop_parameter)20 force_unwind_stop (int version, _Unwind_Action actions,
21                    _Unwind_Exception_Class exc_class,
22                    struct _Unwind_Exception *exc_obj,
23                    struct _Unwind_Context *context,
24                    void *stop_parameter)
25 {
26   printf ("%s: CFA: %p PC: %p actions: %d\n",
27 	  __func__,
28 	  (void *)_Unwind_GetCFA (context),
29 	  (void *)_Unwind_GetIP (context),
30 	  (int)actions);
31   if (actions & _UA_END_OF_STACK)
32     die ();
33   return _URC_NO_REASON;
34 }
35 
force_unwind(void)36 static void force_unwind (void)
37 {
38 #ifndef __USING_SJLJ_EXCEPTIONS__
39   _Unwind_ForcedUnwind (&exc, force_unwind_stop, 0);
40 #else
41   _Unwind_SjLj_ForcedUnwind (&exc, force_unwind_stop, 0);
42 #endif
43 }
44 
45 __attribute__((noinline, target("branch-protection=pac-ret")))
f2_pac_ret(void)46 static void f2_pac_ret (void)
47 {
48   force_unwind ();
49   die ();
50 }
51 
52 __attribute__((noinline, target("branch-protection=none")))
f1_no_pac_ret(void)53 static void f1_no_pac_ret (void)
54 {
55   f2_pac_ret ();
56   die ();
57 }
58 
59 __attribute__((noinline, target("branch-protection=pac-ret")))
f0_pac_ret(void)60 static void f0_pac_ret (void)
61 {
62   f1_no_pac_ret ();
63   die ();
64 }
65 
cleanup_handler(void * p)66 static void cleanup_handler (void *p)
67 {
68   printf ("%s: Success.\n", __func__);
69   exit (0);
70 }
71 
main()72 int main ()
73 {
74   char dummy __attribute__((cleanup (cleanup_handler)));
75   f0_pac_ret ();
76   die ();
77 }
78