blob: cbc940421d241637a3ff778e66b6d2ed2a329bb0 [file] [log] [blame]
/* PR target/94514. Unwind across mixed pac-ret and non-pac-ret frames. */
/* { dg-do run } */
/* { dg-require-effective-target lp64 } */
/* { dg-options "-fexceptions -O2" } */
#include <unwind.h>
#include <stdlib.h>
#include <stdio.h>
#define die() \
do { \
printf ("%s:%d: reached unexpectedly.\n", __FILE__, __LINE__); \
fflush (stdout); \
abort (); \
} while (0)
static struct _Unwind_Exception exc;
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)
{
printf ("%s: CFA: %p PC: %p actions: %d\n",
__func__,
(void *)_Unwind_GetCFA (context),
(void *)_Unwind_GetIP (context),
(int)actions);
if (actions & _UA_END_OF_STACK)
die ();
return _URC_NO_REASON;
}
static void force_unwind (void)
{
#ifndef __USING_SJLJ_EXCEPTIONS__
_Unwind_ForcedUnwind (&exc, force_unwind_stop, 0);
#else
_Unwind_SjLj_ForcedUnwind (&exc, force_unwind_stop, 0);
#endif
}
__attribute__((noinline, target("branch-protection=pac-ret")))
static void f2_pac_ret (void)
{
force_unwind ();
die ();
}
__attribute__((noinline, target("branch-protection=none")))
static void f1_no_pac_ret (void)
{
f2_pac_ret ();
die ();
}
__attribute__((noinline, target("branch-protection=pac-ret")))
static void f0_pac_ret (void)
{
f1_no_pac_ret ();
die ();
}
static void cleanup_handler (void *p)
{
printf ("%s: Success.\n", __func__);
exit (0);
}
int main ()
{
char dummy __attribute__((cleanup (cleanup_handler)));
f0_pac_ret ();
die ();
}