1  /* { dg-do run { target *-*-linux* *-*-gnu* } } */
       2  /* { dg-options "-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2 -fno-stack-protector" } */
       3  /* Test complex CFA value expressions.  */
       4  
       5  #include <unwind.h>
       6  #include <stdlib.h>
       7  #include <stddef.h>
       8  #include <string.h>
       9  #include <stdio.h>
      10  #include <unistd.h>
      11  
      12  static _Unwind_Reason_Code
      13  force_unwind_stop (int version, _Unwind_Action actions,
      14  		   _Unwind_Exception_Class exc_class,
      15  		   struct _Unwind_Exception *exc_obj,
      16  		   struct _Unwind_Context *context,
      17  		   void *stop_parameter)
      18  {
      19    if (actions & _UA_END_OF_STACK)
      20      abort ();
      21    return _URC_NO_REASON;
      22  }
      23  
      24  static void
      25  force_unwind ()
      26  {
      27    struct _Unwind_Exception *exc = malloc (sizeof (*exc));
      28    memset (&exc->exception_class, 0, sizeof (exc->exception_class));
      29    exc->exception_cleanup = 0;
      30  
      31    _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
      32    abort ();
      33  }
      34  
      35  int count;
      36  
      37  static void
      38  counter (void *p __attribute__((unused)))
      39  {
      40    ++count;
      41  }
      42  
      43  static void
      44  handler (void *p __attribute__((unused)))
      45  {
      46    if (count != 2)
      47      abort ();
      48    _exit (0);
      49  }
      50  
      51  static void
      52  __attribute__((noinline))
      53  check (intptr_t p)
      54  {
      55    if ((p & 15) != 0)
      56      abort ();
      57  }
      58  
      59  static int __attribute__((noinline))
      60  fn5 (void)
      61  {
      62    char dummy __attribute__((cleanup (counter)));
      63    force_unwind ();
      64    return 0;
      65  }
      66  
      67  void
      68  bar (void)
      69  {
      70    char dummy __attribute__((cleanup (counter)));
      71    unsigned long tmp[4] __attribute__((aligned(16)));
      72    check ((intptr_t) tmp);
      73    fn5 ();
      74  }
      75  
      76  void __attribute__((noinline))
      77  foo (int x)
      78  {
      79    char buf[256];
      80  #ifdef __i386__
      81    __asm (
      82  	"testl	%0, %0\n\t"
      83  	"jnz	1f\n\t"
      84  	".subsection 1\n\t"
      85  	".type	_L_mutex_lock_%=, @function\n"
      86  "_L_mutex_lock_%=:\n"
      87  "1:\t"	"leal	%1, %%ecx\n"
      88  "2:\t"	"call	bar\n"
      89  "3:\t"	"jmp	18f\n"
      90  "4:\t"	".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t"
      91  	".previous\n\t"
      92  	".section	.eh_frame,\"a\",@progbits\n"
      93  "5:\t"	".long	7f-6f	# Length of Common Information Entry\n"
      94  "6:\t"	".long	0x0	# CIE Identifier Tag\n\t"
      95  	".byte	0x1	# CIE Version\n\t"
      96  	".ascii \"zR\\0\"	# CIE Augmentation\n\t"
      97  	".uleb128 0x1	# CIE Code Alignment Factor\n\t"
      98  	".sleb128 -4	# CIE Data Alignment Factor\n\t"
      99  	".byte	0x8	# CIE RA Column\n\t"
     100  	".uleb128 0x1	# Augmentation size\n\t"
     101  	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t"
     102  	".byte	0xc	# DW_CFA_def_cfa\n\t"
     103  	".uleb128 0x4\n\t"
     104  	".uleb128 0x0\n\t"
     105  	".align 4\n"
     106  "7:\t"	".long	17f-8f	# FDE Length\n"
     107  "8:\t"	".long	8b-5b	# FDE CIE offset\n\t"
     108  	".long	1b-.	# FDE initial location\n\t"
     109  	".long	4b-1b	# FDE address range\n\t"
     110  	".uleb128 0x0	# Augmentation size\n\t"
     111  	".byte	0x16	# DW_CFA_val_expression\n\t"
     112  	".uleb128 0x8\n\t"
     113  	".uleb128 10f-9f\n"
     114  "9:\t"	".byte	0x78	# DW_OP_breg8\n\t"
     115  	".sleb128 3b-1b\n"
     116  "10:\t"	".byte	0x40 + (2b-1b) # DW_CFA_advance_loc\n\t"
     117  	".byte	0x16	# DW_CFA_val_expression\n\t"
     118  	".uleb128 0x8\n\t"
     119  	".uleb128 12f-11f\n"
     120  "11:\t"	".byte	0x78	# DW_OP_breg8\n\t"
     121  	".sleb128 3b-2b\n"
     122  "12:\t"	".byte	0x40 + (3b-2b-1) # DW_CFA_advance_loc\n\t"
     123  	".byte	0x16	# DW_CFA_val_expression\n\t"
     124  	".uleb128 0x8\n\t"
     125  	".uleb128 16f-13f\n"
     126  "13:\t"	".byte	0x78	# DW_OP_breg8\n\t"
     127  	".sleb128 15f-14f\n\t"
     128  	".byte	0x0d	# DW_OP_const4s\n"
     129  "14:\t"	".4byte	3b-.\n\t"
     130  	".byte	0x1c	# DW_OP_minus\n\t"
     131  	".byte	0x0d	# DW_OP_const4s\n"
     132  "15:\t"	".4byte	18f-.\n\t"
     133  	".byte	0x22	# DW_OP_plus\n"
     134  "16:\t"	".align 4\n"
     135  "17:\t"	".previous\n"
     136  "18:"
     137  	: : "r" (x), "m" (x), "r" (buf)
     138  	: "memory", "eax", "edx", "ecx");
     139  #elif defined __x86_64__
     140    __asm (
     141  	"testl	%0, %0\n\t"
     142  	"jnz	1f\n\t"
     143  	".subsection 1\n\t"
     144  	".type	_L_mutex_lock_%=, @function\n"
     145  "_L_mutex_lock_%=:\n"
     146  "1:\t"	"leaq	%1, %%rdi\n"
     147  "2:\t"	"subq	$136, %%rsp\n"
     148  "3:\t"	"call	bar\n"
     149  "4:\t"	"addq	$136, %%rsp\n"
     150  "5:\t"	"jmp	24f\n"
     151  "6:\t"	".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t"
     152  	".previous\n\t"
     153  	".section	.eh_frame,\"a\",@progbits\n"
     154  "7:\t"	".long	9f-8f	# Length of Common Information Entry\n"
     155  "8:\t"	".long	0x0	# CIE Identifier Tag\n\t"
     156  	".byte	0x1	# CIE Version\n\t"
     157  	".ascii \"zR\\0\"	# CIE Augmentation\n\t"
     158  	".uleb128 0x1	# CIE Code Alignment Factor\n\t"
     159  	".sleb128 -8	# CIE Data Alignment Factor\n\t"
     160  	".byte	0x10	# CIE RA Column\n\t"
     161  	".uleb128 0x1	# Augmentation size\n\t"
     162  	".byte	0x1b	# FDE Encoding (pcrel sdata4)\n\t"
     163  	".byte	0x12	# DW_CFA_def_cfa_sf\n\t"
     164  	".uleb128 0x7\n\t"
     165  	".sleb128 16\n\t"
     166  	".align 8\n"
     167  "9:\t"	".long	23f-10f	# FDE Length\n"
     168  "10:\t"	".long	10b-7b	# FDE CIE offset\n\t"
     169  	".long	1b-.	# FDE initial location\n\t"
     170  	".long	6b-1b	# FDE address range\n\t"
     171  	".uleb128 0x0	# Augmentation size\n\t"
     172  	".byte	0x16	# DW_CFA_val_expression\n\t"
     173  	".uleb128 0x10\n\t"
     174  	".uleb128 12f-11f\n"
     175  "11:\t"	".byte	0x80	# DW_OP_breg16\n\t"
     176  	".sleb128 4b-1b\n"
     177  "12:\t"	".byte	0x40 + (2b-1b) # DW_CFA_advance_loc\n\t"
     178  	".byte	0x16	# DW_CFA_val_expression\n\t"
     179  	".uleb128 0x10\n\t"
     180  	".uleb128 14f-13f\n"
     181  "13:\t"	".byte	0x80	# DW_OP_breg16\n\t"
     182  	".sleb128 4b-2b\n"
     183  "14:\t"	".byte	0x40 + (3b-2b) # DW_CFA_advance_loc\n\t"
     184  	".byte	0x0e	# DW_CFA_def_cfa_offset\n\t"
     185  	".uleb128 0\n\t"
     186  	".byte	0x16	# DW_CFA_val_expression\n\t"
     187  	".uleb128 0x10\n\t"
     188  	".uleb128 16f-15f\n"
     189  "15:\t"	".byte	0x80	# DW_OP_breg16\n\t"
     190  	".sleb128 4b-3b\n"
     191  "16:\t"	".byte	0x40 + (4b-3b-1) # DW_CFA_advance_loc\n\t"
     192  	".byte	0x0e	# DW_CFA_def_cfa_offset\n\t"
     193  	".uleb128 136\n\t"
     194  	".byte	0x16	# DW_CFA_val_expression\n\t"
     195  	".uleb128 0x10\n\t"
     196  	".uleb128 20f-17f\n"
     197  "17:\t"	".byte	0x80	# DW_OP_breg16\n\t"
     198  	".sleb128 19f-18f\n\t"
     199  	".byte	0x0d	# DW_OP_const4s\n"
     200  "18:\t"	".4byte	4b-.\n\t"
     201  	".byte	0x1c	# DW_OP_minus\n\t"
     202  	".byte	0x0d	# DW_OP_const4s\n"
     203  "19:\t"	".4byte	24f-.\n\t"
     204  	".byte	0x22	# DW_OP_plus\n"
     205  "20:\t"	".byte	0x40 + (5b-4b+1) # DW_CFA_advance_loc\n\t"
     206  	".byte	0x13	# DW_CFA_def_cfa_offset_sf\n\t"
     207  	".sleb128 16\n\t"
     208  	".byte	0x16	# DW_CFA_val_expression\n\t"
     209  	".uleb128 0x10\n\t"
     210  	".uleb128 22f-21f\n"
     211  "21:\t"	".byte	0x80	# DW_OP_breg16\n\t"
     212  	".sleb128 4b-5b\n"
     213  "22:\t"	".align 8\n"
     214  "23:\t"	".previous\n"
     215  "24:"
     216  	: : "r" (x), "m" (x), "r" (buf)
     217  	: "memory", "rax", "rdx", "rcx", "rsi", "rdi",
     218  	  "r8", "r9", "r10", "r11");
     219  #else
     220  # error Unsupported test architecture
     221  #endif
     222  }
     223  
     224  static int __attribute__((noinline))
     225  fn2 (void)
     226  {
     227    foo (3);
     228    return 0;
     229  }
     230  
     231  static int __attribute__((noinline))
     232  fn1 (void)
     233  {
     234    fn2 ();
     235    return 0;
     236  }
     237  
     238  static void *
     239  fn0 (void)
     240  {
     241    char dummy __attribute__((cleanup (handler)));
     242    fn1 ();
     243    return 0;
     244  }
     245  
     246  int
     247  main (void)
     248  {
     249    fn0 ();
     250    return 0;
     251  }