(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.target/
aarch64/
pr104689.c
       1  /* PR target/104689. Unwind across pac-ret frames with unusual dwarf.  */
       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  
      18  /* Code to invoke unwinding with a logging callback.  */
      19  
      20  static struct _Unwind_Exception exc;
      21  
      22  static _Unwind_Reason_Code
      23  force_unwind_stop (int version, _Unwind_Action actions,
      24                     _Unwind_Exception_Class exc_class,
      25                     struct _Unwind_Exception *exc_obj,
      26                     struct _Unwind_Context *context,
      27                     void *stop_parameter)
      28  {
      29    printf ("%s: CFA: %p PC: %p actions: %d\n",
      30  	  __func__,
      31  	  (void *)_Unwind_GetCFA (context),
      32  	  (void *)_Unwind_GetIP (context),
      33  	  (int)actions);
      34    if (actions & _UA_END_OF_STACK)
      35      die ();
      36    return _URC_NO_REASON;
      37  }
      38  
      39  static void force_unwind (void)
      40  {
      41  #ifndef __USING_SJLJ_EXCEPTIONS__
      42    _Unwind_ForcedUnwind (&exc, force_unwind_stop, 0);
      43  #else
      44    _Unwind_SjLj_ForcedUnwind (&exc, force_unwind_stop, 0);
      45  #endif
      46  }
      47  
      48  
      49  /* Define functions with unusual pac-ret dwarf via top level asm.  */
      50  
      51  #define STR(x) #x
      52  #define DW_CFA_val_expression 0x16
      53  #define RA_SIGN_STATE 34
      54  #define DW_OP_lit0 0x30
      55  #define DW_OP_lit1 0x31
      56  
      57  #define cfi_escape(a1, a2, a3, a4) \
      58    ".cfi_escape " STR(a1) ", " STR(a2) ", " STR(a3) ", " STR(a4)
      59  
      60  /* Bytes: 0x16 0x22 0x01 0x30  */
      61  #define SET_RA_STATE_0 \
      62    cfi_escape (DW_CFA_val_expression, RA_SIGN_STATE, 1, DW_OP_lit0)
      63  
      64  /* Bytes: 0x16 0x22 0x01 0x31  */
      65  #define SET_RA_STATE_1 \
      66    cfi_escape (DW_CFA_val_expression, RA_SIGN_STATE, 1, DW_OP_lit1)
      67  
      68  /* These function call their argument.  */
      69  void unusual_pac_ret (void *);
      70  void unusual_no_pac_ret (void *);
      71  
      72  asm(""
      73  ".global unusual_pac_ret\n"
      74  ".type unusual_pac_ret, %function\n"
      75  "unusual_pac_ret:\n"
      76  "	.cfi_startproc\n"
      77  "	" SET_RA_STATE_0 "\n"
      78  "	hint	25 // paciasp\n"
      79  "	" SET_RA_STATE_1 "\n"
      80  "	stp	x29, x30, [sp, -16]!\n"
      81  "	.cfi_def_cfa_offset 16\n"
      82  "	.cfi_offset 29, -16\n"
      83  "	.cfi_offset 30, -8\n"
      84  "	mov	x29, sp\n"
      85  "	blr	x0\n"
      86  "	ldp	x29, x30, [sp], 16\n"
      87  "	.cfi_restore 30\n"
      88  "	.cfi_restore 29\n"
      89  "	.cfi_def_cfa_offset 0\n"
      90  "	hint	29 // autiasp\n"
      91  "	" SET_RA_STATE_0 "\n"
      92  "	ret\n"
      93  "	.cfi_endproc\n");
      94  
      95  asm(""
      96  ".global unusual_no_pac_ret\n"
      97  ".type unusual_no_pac_ret, %function\n"
      98  "unusual_no_pac_ret:\n"
      99  "	.cfi_startproc\n"
     100  "	" SET_RA_STATE_0 "\n"
     101  "	stp	x29, x30, [sp, -16]!\n"
     102  "	.cfi_def_cfa_offset 16\n"
     103  "	.cfi_offset 29, -16\n"
     104  "	.cfi_offset 30, -8\n"
     105  "	mov	x29, sp\n"
     106  "	blr	x0\n"
     107  "	ldp	x29, x30, [sp], 16\n"
     108  "	.cfi_restore 30\n"
     109  "	.cfi_restore 29\n"
     110  "	.cfi_def_cfa_offset 0\n"
     111  "	ret\n"
     112  "	.cfi_endproc\n");
     113  
     114  
     115  /* Functions to create a call chain with mixed pac-ret dwarf.  */
     116  
     117  __attribute__((target("branch-protection=pac-ret")))
     118  static void f2_pac_ret (void)
     119  {
     120    force_unwind ();
     121    die ();
     122  }
     123  
     124  __attribute__((target("branch-protection=none")))
     125  static void f1_no_pac_ret (void)
     126  {
     127    unusual_pac_ret (f2_pac_ret);
     128    die ();
     129  }
     130  
     131  __attribute__((noinline, target("branch-protection=pac-ret")))
     132  static void f0_pac_ret (void)
     133  {
     134    unusual_no_pac_ret (f1_no_pac_ret);
     135    die ();
     136  }
     137  
     138  static void cleanup_handler (void *p)
     139  {
     140    printf ("%s: Success.\n", __func__);
     141    exit (0);
     142  }
     143  
     144  int main ()
     145  {
     146    char dummy __attribute__((cleanup (cleanup_handler)));
     147    f0_pac_ret ();
     148    die ();
     149  }