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