/* PR target/104689. Unwind across pac-ret frames with unusual dwarf. */ /* { dg-do run } */ /* { dg-require-effective-target lp64 } */ /* { dg-options "-fexceptions -O2" } */ #include #include #include #define die() \ do { \ printf ("%s:%d: reached unexpectedly.\n", __FILE__, __LINE__); \ fflush (stdout); \ abort (); \ } while (0) /* Code to invoke unwinding with a logging callback. */ 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 } /* Define functions with unusual pac-ret dwarf via top level asm. */ #define STR(x) #x #define DW_CFA_val_expression 0x16 #define RA_SIGN_STATE 34 #define DW_OP_lit0 0x30 #define DW_OP_lit1 0x31 #define cfi_escape(a1, a2, a3, a4) \ ".cfi_escape " STR(a1) ", " STR(a2) ", " STR(a3) ", " STR(a4) /* Bytes: 0x16 0x22 0x01 0x30 */ #define SET_RA_STATE_0 \ cfi_escape (DW_CFA_val_expression, RA_SIGN_STATE, 1, DW_OP_lit0) /* Bytes: 0x16 0x22 0x01 0x31 */ #define SET_RA_STATE_1 \ cfi_escape (DW_CFA_val_expression, RA_SIGN_STATE, 1, DW_OP_lit1) /* These function call their argument. */ void unusual_pac_ret (void *); void unusual_no_pac_ret (void *); asm("" ".global unusual_pac_ret\n" ".type unusual_pac_ret, %function\n" "unusual_pac_ret:\n" " .cfi_startproc\n" " " SET_RA_STATE_0 "\n" " hint 25 // paciasp\n" " " SET_RA_STATE_1 "\n" " stp x29, x30, [sp, -16]!\n" " .cfi_def_cfa_offset 16\n" " .cfi_offset 29, -16\n" " .cfi_offset 30, -8\n" " mov x29, sp\n" " blr x0\n" " ldp x29, x30, [sp], 16\n" " .cfi_restore 30\n" " .cfi_restore 29\n" " .cfi_def_cfa_offset 0\n" " hint 29 // autiasp\n" " " SET_RA_STATE_0 "\n" " ret\n" " .cfi_endproc\n"); asm("" ".global unusual_no_pac_ret\n" ".type unusual_no_pac_ret, %function\n" "unusual_no_pac_ret:\n" " .cfi_startproc\n" " " SET_RA_STATE_0 "\n" " stp x29, x30, [sp, -16]!\n" " .cfi_def_cfa_offset 16\n" " .cfi_offset 29, -16\n" " .cfi_offset 30, -8\n" " mov x29, sp\n" " blr x0\n" " ldp x29, x30, [sp], 16\n" " .cfi_restore 30\n" " .cfi_restore 29\n" " .cfi_def_cfa_offset 0\n" " ret\n" " .cfi_endproc\n"); /* Functions to create a call chain with mixed pac-ret dwarf. */ __attribute__((target("branch-protection=pac-ret"))) static void f2_pac_ret (void) { force_unwind (); die (); } __attribute__((target("branch-protection=none"))) static void f1_no_pac_ret (void) { unusual_pac_ret (f2_pac_ret); die (); } __attribute__((noinline, target("branch-protection=pac-ret"))) static void f0_pac_ret (void) { unusual_no_pac_ret (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 (); }