1 /* { dg-do run { target *-*-linux* *-*-gnu* } } */
2 /* { dg-options "-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2" } */
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
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)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
force_unwind()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
counter(void * p)38 counter (void *p __attribute__((unused)))
39 {
40   ++count;
41 }
42 
43 static void
handler(void * p)44 handler (void *p __attribute__((unused)))
45 {
46   if (count != 2)
47     abort ();
48   _exit (0);
49 }
50 
51 static void
52 __attribute__((noinline))
check(intptr_t p)53 check (intptr_t p)
54 {
55   if ((p & 15) != 0)
56     abort ();
57 }
58 
59 static int __attribute__((noinline))
fn5(void)60 fn5 (void)
61 {
62   char dummy __attribute__((cleanup (counter)));
63   force_unwind ();
64   return 0;
65 }
66 
67 void
bar(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))
foo(int x)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))
fn2(void)225 fn2 (void)
226 {
227   foo (3);
228   return 0;
229 }
230 
231 static int __attribute__((noinline))
fn1(void)232 fn1 (void)
233 {
234   fn2 ();
235   return 0;
236 }
237 
238 static void *
fn0(void)239 fn0 (void)
240 {
241   char dummy __attribute__((cleanup (handler)));
242   fn1 ();
243   return 0;
244 }
245 
246 int
main(void)247 main (void)
248 {
249   fn0 ();
250   return 0;
251 }
252