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