Commit | Line | Data |
---|---|---|
b966cb8a TT |
1 | /* This file comes from GCC. If you are tempted to change it, |
2 | consider also changing the copy there. */ | |
3 | ||
4 | /* HP-UX libunwind.so doesn't provide _UA_END_OF_STACK */ | |
5 | /* { dg-do run } */ | |
6 | /* { dg-options "-fexceptions" } */ | |
7 | /* { dg-skip-if "" { "ia64-*-hpux11.*" } { "*" } { "" } } */ | |
8 | /* Verify DW_OP_* handling in the unwinder. */ | |
9 | ||
10 | #include <unwind.h> | |
11 | #include <stdlib.h> | |
12 | #include <string.h> | |
13 | ||
14 | /* #define OP_addr(x) 0x06, ... */ | |
15 | #define OP_deref 0x06, | |
16 | #define SLEB128(x) (x)&0x7f /* Assume here the value is -0x40 ... 0x3f. */ | |
17 | #define ULEB128(x) (x)&0x7f /* Assume here the value is 0 ... 0x7f. */ | |
18 | #define VAL1(x) (x)&0xff | |
19 | #if defined (__BIG_ENDIAN__) | |
20 | #define VAL2(x) ((x)>>8)&0xff,(x)&0xff | |
21 | #define VAL4(x) ((x)>>24)&0xff,((x)>>16)&0xff,((x)>>8)&0xff,(x)&0xff | |
22 | #define VAL8(x) ((x)>>56)&0xff,((x)>>48)&0xff,((x)>>40)&0xff,((x)>>32)&0xff,((x)>>24)&0xff,((x)>>16)&0xff,((x)>>8)&0xff,(x)&0xff | |
23 | #elif defined(__LITTLE_ENDIAN__) || defined(__x86_64__) || defined(__i386__) | |
24 | #define VAL2(x) (x)&0xff,((x)>>8)&0xff | |
25 | #define VAL4(x) (x)&0xff,((x)>>8)&0xff,((x)>>16)&0xff,((x)>>24)&0xff | |
26 | #define VAL8(x) (x)&0xff,((x)>>8)&0xff,((x)>>16)&0xff,((x)>>24)&0xff,((x)>>32)&0xff,((x)>>40)&0xff,((x)>>48)&0xff,((x)>>56)&0xff | |
27 | #endif | |
28 | #define OP_const1u(x) 0x08,VAL1(x), | |
29 | #define OP_const1s(x) 0x09,VAL1(x), | |
30 | #define OP_const2u(x) 0x0a,VAL2(x), | |
31 | #define OP_const2s(x) 0x0b,VAL2(x), | |
32 | #define OP_const4u(x) 0x0c,VAL4(x), | |
33 | #define OP_const4s(x) 0x0d,VAL4(x), | |
34 | #define OP_const8u(x) 0x0e,VAL8(x), | |
35 | #define OP_const8s(x) 0x0f,VAL8(x), | |
36 | #define OP_constu(x) 0x10,ULEB128(x), | |
37 | #define OP_consts(x) 0x11,SLEB128(x), | |
38 | #define OP_dup 0x12, | |
39 | #define OP_drop 0x13, | |
40 | #define OP_over 0x14, | |
41 | #define OP_pick(x) 0x15,VAL1(x), | |
42 | #define OP_swap 0x16, | |
43 | #define OP_rot 0x17, | |
44 | #define OP_xderef 0x18, | |
45 | #define OP_abs 0x19, | |
46 | #define OP_and 0x1a, | |
47 | #define OP_div 0x1b, | |
48 | #define OP_minus 0x1c, | |
49 | #define OP_mod 0x1d, | |
50 | #define OP_mul 0x1e, | |
51 | #define OP_neg 0x1f, | |
52 | #define OP_not 0x20, | |
53 | #define OP_or 0x21, | |
54 | #define OP_plus 0x22, | |
55 | #define OP_plus_uconst(x) 0x23,ULEB128(x), | |
56 | #define OP_shl 0x24, | |
57 | #define OP_shr 0x25, | |
58 | #define OP_shra 0x26, | |
59 | #define OP_xor 0x27, | |
60 | #define OP_bra(x) 0x28,VAL2(x), | |
61 | #define OP_eq 0x29, | |
62 | #define OP_ge 0x2a, | |
63 | #define OP_gt 0x2b, | |
64 | #define OP_le 0x2c, | |
65 | #define OP_lt 0x2d, | |
66 | #define OP_ne 0x2e, | |
67 | #define OP_skip(x) 0x2f,VAL2(x), | |
68 | #define OP_lit0 0x30, | |
69 | #define OP_lit1 0x31, | |
70 | #define OP_lit2 0x32, | |
71 | #define OP_lit3 0x33, | |
72 | #define OP_lit4 0x34, | |
73 | #define OP_lit5 0x35, | |
74 | #define OP_lit6 0x36, | |
75 | #define OP_lit7 0x37, | |
76 | #define OP_lit8 0x38, | |
77 | #define OP_lit9 0x39, | |
78 | #define OP_lit10 0x3a, | |
79 | #define OP_lit11 0x3b, | |
80 | #define OP_lit12 0x3c, | |
81 | #define OP_lit13 0x3d, | |
82 | #define OP_lit14 0x3e, | |
83 | #define OP_lit15 0x3f, | |
84 | #define OP_lit16 0x40, | |
85 | #define OP_lit17 0x41, | |
86 | #define OP_lit18 0x42, | |
87 | #define OP_lit19 0x43, | |
88 | #define OP_lit20 0x44, | |
89 | #define OP_lit21 0x45, | |
90 | #define OP_lit22 0x46, | |
91 | #define OP_lit23 0x47, | |
92 | #define OP_lit24 0x48, | |
93 | #define OP_lit25 0x49, | |
94 | #define OP_lit26 0x4a, | |
95 | #define OP_lit27 0x4b, | |
96 | #define OP_lit28 0x4c, | |
97 | #define OP_lit29 0x4d, | |
98 | #define OP_lit30 0x4e, | |
99 | #define OP_lit31 0x4f, | |
100 | #define OP_reg0 0x50, | |
101 | #define OP_reg1 0x51, | |
102 | #define OP_reg2 0x52, | |
103 | #define OP_reg3 0x53, | |
104 | #define OP_reg4 0x54, | |
105 | #define OP_reg5 0x55, | |
106 | #define OP_reg6 0x56, | |
107 | #define OP_reg7 0x57, | |
108 | #define OP_reg8 0x58, | |
109 | #define OP_reg9 0x59, | |
110 | #define OP_reg10 0x5a, | |
111 | #define OP_reg11 0x5b, | |
112 | #define OP_reg12 0x5c, | |
113 | #define OP_reg13 0x5d, | |
114 | #define OP_reg14 0x5e, | |
115 | #define OP_reg15 0x5f, | |
116 | #define OP_reg16 0x60, | |
117 | #define OP_reg17 0x61, | |
118 | #define OP_reg18 0x62, | |
119 | #define OP_reg19 0x63, | |
120 | #define OP_reg20 0x64, | |
121 | #define OP_reg21 0x65, | |
122 | #define OP_reg22 0x66, | |
123 | #define OP_reg23 0x67, | |
124 | #define OP_reg24 0x68, | |
125 | #define OP_reg25 0x69, | |
126 | #define OP_reg26 0x6a, | |
127 | #define OP_reg27 0x6b, | |
128 | #define OP_reg28 0x6c, | |
129 | #define OP_reg29 0x6d, | |
130 | #define OP_reg30 0x6e, | |
131 | #define OP_reg31 0x6f, | |
132 | #define OP_breg0(x) 0x70,SLEB128(x), | |
133 | #define OP_breg1(x) 0x71,SLEB128(x), | |
134 | #define OP_breg2(x) 0x72,SLEB128(x), | |
135 | #define OP_breg3(x) 0x73,SLEB128(x), | |
136 | #define OP_breg4(x) 0x74,SLEB128(x), | |
137 | #define OP_breg5(x) 0x75,SLEB128(x), | |
138 | #define OP_breg6(x) 0x76,SLEB128(x), | |
139 | #define OP_breg7(x) 0x77,SLEB128(x), | |
140 | #define OP_breg8(x) 0x78,SLEB128(x), | |
141 | #define OP_breg9(x) 0x79,SLEB128(x), | |
142 | #define OP_breg10(x) 0x7a,SLEB128(x), | |
143 | #define OP_breg11(x) 0x7b,SLEB128(x), | |
144 | #define OP_breg12(x) 0x7c,SLEB128(x), | |
145 | #define OP_breg13(x) 0x7d,SLEB128(x), | |
146 | #define OP_breg14(x) 0x7e,SLEB128(x), | |
147 | #define OP_breg15(x) 0x7f,SLEB128(x), | |
148 | #define OP_breg16(x) 0x80,SLEB128(x), | |
149 | #define OP_breg17(x) 0x81,SLEB128(x), | |
150 | #define OP_breg18(x) 0x82,SLEB128(x), | |
151 | #define OP_breg19(x) 0x83,SLEB128(x), | |
152 | #define OP_breg20(x) 0x84,SLEB128(x), | |
153 | #define OP_breg21(x) 0x85,SLEB128(x), | |
154 | #define OP_breg22(x) 0x86,SLEB128(x), | |
155 | #define OP_breg23(x) 0x87,SLEB128(x), | |
156 | #define OP_breg24(x) 0x88,SLEB128(x), | |
157 | #define OP_breg25(x) 0x89,SLEB128(x), | |
158 | #define OP_breg26(x) 0x8a,SLEB128(x), | |
159 | #define OP_breg27(x) 0x8b,SLEB128(x), | |
160 | #define OP_breg28(x) 0x8c,SLEB128(x), | |
161 | #define OP_breg29(x) 0x8d,SLEB128(x), | |
162 | #define OP_breg30(x) 0x8e,SLEB128(x), | |
163 | #define OP_breg31(x) 0x8f,SLEB128(x), | |
164 | #define OP_regx(x) 0x90,SLEB128(x), | |
165 | #define OP_fbreg(x) 0x91,SLEB128(x), | |
166 | #define OP_bregx(x,y) 0x92,ULEB128(x),SLEB128(y), | |
167 | #define OP_piece(x) 0x93,ULEB128(x), | |
168 | #define OP_deref_size(x) 0x94,VAL1(x), | |
169 | #define OP_xderef_size(x) 0x95,VAL1(x), | |
170 | #define OP_nop 0x96, | |
171 | #define OP_nop_termination 0x96 | |
172 | #define OP_push_object_address 0x97, | |
173 | #define OP_call2(x) 0x98,VAL2(x), | |
174 | #define OP_call4(x) 0x99,VAL4(x), | |
175 | /* #define OP_call_ref(x) 0x9a,... */ | |
176 | #define OP_form_tls_address(x) 0x9b, | |
177 | #define OP_call_frame_cfa 0x9c, | |
178 | #define OP_bit_piece(x) 0x9d,ULEB128(x), | |
179 | /* #define OP_implicit_value(x...) 0x9e,... */ | |
180 | #define OP_stack_value 0x9f, | |
181 | #define OP_GNU_push_tls_address 0xe0, | |
182 | /* #define OP_GNU_encoded_addr(x...) 0xf1, */ | |
183 | ||
184 | #define ASSERT_TOS_NON0 OP_bra(3) OP_skip(-3) | |
185 | #define ASSERT_TOS_0 OP_lit0 OP_eq ASSERT_TOS_NON0 | |
186 | ||
187 | /* Initially there is CFA value on the stack, we want to | |
188 | keep it there at the end. */ | |
189 | #define CFI_PROGRAM \ | |
190 | OP_lit0 OP_nop ASSERT_TOS_0 \ | |
191 | OP_lit1 ASSERT_TOS_NON0 \ | |
192 | OP_lit1 OP_const1u(1) OP_eq ASSERT_TOS_NON0 \ | |
193 | OP_lit16 OP_const2u(16) OP_eq ASSERT_TOS_NON0 \ | |
194 | OP_lit31 OP_const4u(31) OP_ne ASSERT_TOS_0 \ | |
195 | OP_lit1 OP_neg OP_const1s(-1) OP_eq ASSERT_TOS_NON0 \ | |
196 | OP_lit16 OP_neg OP_const2s(-16) OP_ne ASSERT_TOS_0 \ | |
197 | OP_lit31 OP_const4s(-31) OP_neg OP_ne ASSERT_TOS_0 \ | |
198 | OP_lit7 OP_dup OP_plus_uconst(2) OP_lit9 OP_eq ASSERT_TOS_NON0 \ | |
199 | OP_lit7 OP_eq ASSERT_TOS_NON0 \ | |
200 | OP_lit20 OP_lit1 OP_drop OP_lit20 OP_eq ASSERT_TOS_NON0 \ | |
201 | OP_lit17 OP_lit19 OP_over OP_lit17 OP_eq ASSERT_TOS_NON0 \ | |
202 | OP_lit19 OP_eq ASSERT_TOS_NON0 OP_lit17 OP_eq ASSERT_TOS_NON0 \ | |
203 | OP_lit1 OP_lit2 OP_lit3 OP_lit4 OP_pick(2) OP_lit2 OP_eq ASSERT_TOS_NON0\ | |
204 | OP_lit4 OP_eq ASSERT_TOS_NON0 OP_lit3 OP_eq ASSERT_TOS_NON0 \ | |
205 | OP_pick(0) OP_lit2 OP_eq ASSERT_TOS_NON0 \ | |
206 | OP_lit2 OP_eq ASSERT_TOS_NON0 OP_lit1 OP_eq ASSERT_TOS_NON0 \ | |
207 | OP_lit6 OP_lit12 OP_swap OP_lit6 OP_eq ASSERT_TOS_NON0 \ | |
208 | OP_lit12 OP_eq ASSERT_TOS_NON0 \ | |
209 | OP_lit7 OP_lit8 OP_lit9 OP_rot OP_lit8 OP_eq ASSERT_TOS_NON0 \ | |
210 | OP_lit7 OP_eq ASSERT_TOS_NON0 OP_lit9 OP_eq ASSERT_TOS_NON0 \ | |
211 | OP_lit7 OP_abs OP_lit7 OP_eq ASSERT_TOS_NON0 \ | |
212 | OP_const1s(-123) OP_abs OP_const1u(123) OP_eq ASSERT_TOS_NON0 \ | |
213 | OP_lit3 OP_lit6 OP_and OP_lit2 OP_eq ASSERT_TOS_NON0 \ | |
214 | OP_lit3 OP_lit6 OP_or OP_lit7 OP_eq ASSERT_TOS_NON0 \ | |
215 | OP_lit17 OP_lit2 OP_minus OP_lit15 OP_eq ASSERT_TOS_NON0 \ | |
216 | /* Divide is signed truncating toward zero. */ \ | |
217 | OP_const1s(-6) OP_const1s(-2) OP_div OP_lit3 OP_eq ASSERT_TOS_NON0 \ | |
218 | OP_const1s(-7) OP_const1s(3) OP_div OP_const1s(-2) \ | |
219 | OP_eq ASSERT_TOS_NON0 \ | |
220 | /* Modulo is unsigned. */ \ | |
221 | OP_const1s(-6) OP_const1s(-4) OP_mod OP_const1s(-6) \ | |
222 | OP_eq ASSERT_TOS_NON0 \ | |
223 | OP_const1s(-6) OP_lit4 OP_mod OP_lit2 OP_eq ASSERT_TOS_NON0 \ | |
224 | OP_lit6 OP_const1s(-4) OP_mod OP_lit6 OP_eq ASSERT_TOS_NON0 \ | |
225 | /* Signed modulo can be implemented using "over over div mul minus". */\ | |
226 | OP_const1s(-6) OP_const1s(-4) OP_over OP_over OP_div OP_mul OP_minus \ | |
227 | OP_const1s(-2) OP_eq ASSERT_TOS_NON0 \ | |
228 | OP_const1s(-7) OP_lit3 OP_over OP_over OP_div OP_mul OP_minus \ | |
229 | OP_const1s(-1) OP_eq ASSERT_TOS_NON0 \ | |
230 | OP_lit7 OP_const1s(-3) OP_over OP_over OP_div OP_mul OP_minus \ | |
231 | OP_lit1 OP_eq ASSERT_TOS_NON0 \ | |
232 | OP_lit16 OP_lit31 OP_plus_uconst(1) OP_mul OP_const2u(512) \ | |
233 | OP_eq ASSERT_TOS_NON0 \ | |
234 | OP_lit5 OP_not OP_lit31 OP_and OP_lit26 OP_eq ASSERT_TOS_NON0 \ | |
235 | OP_lit12 OP_lit31 OP_plus OP_const1u(43) OP_eq ASSERT_TOS_NON0 \ | |
236 | OP_const1s(-6) OP_lit2 OP_plus OP_const1s(-4) OP_eq ASSERT_TOS_NON0 \ | |
237 | OP_const1s(-6) OP_plus_uconst(3) OP_const1s(-3) OP_eq ASSERT_TOS_NON0 \ | |
238 | OP_lit16 OP_lit4 OP_shl OP_const2u(256) OP_eq ASSERT_TOS_NON0 \ | |
239 | OP_lit16 OP_lit3 OP_shr OP_lit2 OP_eq ASSERT_TOS_NON0 \ | |
240 | OP_const1s(-16) OP_lit3 OP_shra OP_const1s(-2) OP_eq ASSERT_TOS_NON0 \ | |
241 | OP_lit3 OP_lit6 OP_xor OP_lit5 OP_eq ASSERT_TOS_NON0 \ | |
242 | OP_lit3 OP_lit6 OP_le ASSERT_TOS_NON0 \ | |
243 | OP_lit3 OP_lit3 OP_le ASSERT_TOS_NON0 \ | |
244 | OP_lit6 OP_lit3 OP_le ASSERT_TOS_0 \ | |
245 | OP_lit3 OP_lit6 OP_lt ASSERT_TOS_NON0 \ | |
246 | OP_lit3 OP_lit3 OP_lt ASSERT_TOS_0 \ | |
247 | OP_lit6 OP_lit3 OP_lt ASSERT_TOS_0 \ | |
248 | OP_lit3 OP_lit6 OP_ge ASSERT_TOS_0 \ | |
249 | OP_lit3 OP_lit3 OP_ge ASSERT_TOS_NON0 \ | |
250 | OP_lit6 OP_lit3 OP_ge ASSERT_TOS_NON0 \ | |
251 | OP_lit3 OP_lit6 OP_gt ASSERT_TOS_0 \ | |
252 | OP_lit3 OP_lit3 OP_gt ASSERT_TOS_0 \ | |
253 | OP_lit6 OP_lit3 OP_gt ASSERT_TOS_NON0 \ | |
254 | OP_const1s(-6) OP_lit1 OP_shr OP_lit0 OP_gt ASSERT_TOS_NON0 \ | |
255 | OP_const1s(-6) OP_lit1 OP_shra OP_lit0 OP_lt ASSERT_TOS_NON0 | |
256 | ||
257 | #define CFI_ESCAPE_VAL_2(VALUES...) #VALUES | |
258 | #define CFI_ESCAPE_VAL_1(VALUES...) CFI_ESCAPE_VAL_2(VALUES) | |
259 | #define CFI_ESCAPE_VAL(VALUES...) CFI_ESCAPE_VAL_1(VALUES) | |
260 | #define CFI_ESCAPE do { } while (0) | |
261 | #define CFI_ARCH_PROGRAM OP_nop_termination | |
262 | #ifdef __GCC_HAVE_DWARF2_CFI_ASM | |
263 | #if defined (__x86_64__) | |
264 | #undef CFI_ESCAPE | |
265 | #undef CFI_ARCH_PROGRAM | |
266 | #define CFI_ARCH_PROGRAM CFI_PROGRAM OP_lit8 OP_minus OP_nop_termination | |
267 | unsigned char cfi_arch_program[] = { CFI_ARCH_PROGRAM }; | |
268 | extern char verify_it[sizeof (cfi_arch_program) - 0x80 < 0x3f80 ? 1 : -1]; | |
269 | /* DW_CFA_expression %rip, uleb128(l2-l1), l1: program DW_OP_lit8 DW_OP_minus DW_OP_nop l2: */ | |
270 | #define CFI_ESCAPE \ | |
271 | asm volatile (".cfi_escape 0x10, 0x10, (%P0&0x7f)+0x80, %P0>>7, " \ | |
272 | CFI_ESCAPE_VAL (CFI_ARCH_PROGRAM) \ | |
273 | : : "i" (sizeof (cfi_arch_program))) | |
274 | #elif defined (__i386__) | |
275 | #undef CFI_ESCAPE | |
276 | #undef CFI_ARCH_PROGRAM | |
277 | #define CFI_ARCH_PROGRAM CFI_PROGRAM OP_lit4 OP_minus OP_nop_termination | |
278 | unsigned char cfi_arch_program[] = { CFI_ARCH_PROGRAM }; | |
279 | extern char verify_it[sizeof (cfi_arch_program) - 0x80 < 0x3f80 ? 1 : -1]; | |
280 | /* DW_CFA_expression %eip, uleb128(l2-l1), l1: program DW_OP_lit4 DW_OP_minus DW_OP_nop l2: */ | |
281 | #define CFI_ESCAPE \ | |
282 | asm volatile (".cfi_escape 0x10, 8, (%P0&0x7f)+0x80, %P0>>7, " \ | |
283 | CFI_ESCAPE_VAL (CFI_ARCH_PROGRAM) \ | |
284 | : : "i" (sizeof (cfi_arch_program))) | |
285 | #endif | |
286 | #endif | |
287 | static _Unwind_Reason_Code | |
288 | force_unwind_stop (int version, _Unwind_Action actions, | |
289 | _Unwind_Exception_Class exc_class, | |
290 | struct _Unwind_Exception *exc_obj, | |
291 | struct _Unwind_Context *context, | |
292 | void *stop_parameter) | |
293 | { | |
294 | if (actions & _UA_END_OF_STACK) | |
295 | abort (); | |
296 | return _URC_NO_REASON; | |
297 | } | |
298 | ||
299 | static void force_unwind () | |
300 | { | |
301 | struct _Unwind_Exception *exc = malloc (sizeof (*exc)); | |
302 | memset (&exc->exception_class, 0, sizeof (exc->exception_class)); | |
303 | exc->exception_cleanup = 0; | |
304 | ||
305 | #ifndef __USING_SJLJ_EXCEPTIONS__ | |
306 | _Unwind_ForcedUnwind (exc, force_unwind_stop, 0); | |
307 | #else | |
308 | _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0); | |
309 | #endif | |
310 | ||
311 | abort (); | |
312 | } | |
313 | ||
314 | static void handler (void *p __attribute__((unused))) | |
315 | { | |
316 | exit (0); | |
317 | } | |
318 | ||
319 | __attribute__((noinline)) static void callme () | |
320 | { | |
321 | CFI_ESCAPE; | |
322 | force_unwind (); | |
323 | } | |
324 | ||
325 | __attribute__((noinline)) static void doit () | |
326 | { | |
327 | char dummy __attribute__((cleanup (handler))); | |
328 | callme (); | |
329 | } | |
330 | ||
331 | int main() | |
332 | { | |
333 | doit (); | |
334 | abort (); | |
335 | } |