| /* { dg-do run { target *-*-linux* *-*-gnu* } } */ |
| /* { dg-options "-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2 -fno-stack-protector" } */ |
| /* Test complex CFA value expressions. */ |
| |
| #include <unwind.h> |
| #include <stdlib.h> |
| #include <stddef.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <unistd.h> |
| |
| 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) |
| { |
| if (actions & _UA_END_OF_STACK) |
| abort (); |
| return _URC_NO_REASON; |
| } |
| |
| static void |
| force_unwind () |
| { |
| struct _Unwind_Exception *exc = malloc (sizeof (*exc)); |
| memset (&exc->exception_class, 0, sizeof (exc->exception_class)); |
| exc->exception_cleanup = 0; |
| |
| _Unwind_ForcedUnwind (exc, force_unwind_stop, 0); |
| abort (); |
| } |
| |
| int count; |
| |
| static void |
| counter (void *p __attribute__((unused))) |
| { |
| ++count; |
| } |
| |
| static void |
| handler (void *p __attribute__((unused))) |
| { |
| if (count != 2) |
| abort (); |
| _exit (0); |
| } |
| |
| static void |
| __attribute__((noinline)) |
| check (intptr_t p) |
| { |
| if ((p & 15) != 0) |
| abort (); |
| } |
| |
| static int __attribute__((noinline)) |
| fn5 (void) |
| { |
| char dummy __attribute__((cleanup (counter))); |
| force_unwind (); |
| return 0; |
| } |
| |
| void |
| bar (void) |
| { |
| char dummy __attribute__((cleanup (counter))); |
| unsigned long tmp[4] __attribute__((aligned(16))); |
| check ((intptr_t) tmp); |
| fn5 (); |
| } |
| |
| void __attribute__((noinline)) |
| foo (int x) |
| { |
| char buf[256]; |
| #ifdef __i386__ |
| __asm ( |
| "testl %0, %0\n\t" |
| "jnz 1f\n\t" |
| ".subsection 1\n\t" |
| ".type _L_mutex_lock_%=, @function\n" |
| "_L_mutex_lock_%=:\n" |
| "1:\t" "leal %1, %%ecx\n" |
| "2:\t" "call bar\n" |
| "3:\t" "jmp 18f\n" |
| "4:\t" ".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t" |
| ".previous\n\t" |
| ".section .eh_frame,\"a\",@progbits\n" |
| "5:\t" ".long 7f-6f # Length of Common Information Entry\n" |
| "6:\t" ".long 0x0 # CIE Identifier Tag\n\t" |
| ".byte 0x1 # CIE Version\n\t" |
| ".ascii \"zR\\0\" # CIE Augmentation\n\t" |
| ".uleb128 0x1 # CIE Code Alignment Factor\n\t" |
| ".sleb128 -4 # CIE Data Alignment Factor\n\t" |
| ".byte 0x8 # CIE RA Column\n\t" |
| ".uleb128 0x1 # Augmentation size\n\t" |
| ".byte 0x1b # FDE Encoding (pcrel sdata4)\n\t" |
| ".byte 0xc # DW_CFA_def_cfa\n\t" |
| ".uleb128 0x4\n\t" |
| ".uleb128 0x0\n\t" |
| ".align 4\n" |
| "7:\t" ".long 17f-8f # FDE Length\n" |
| "8:\t" ".long 8b-5b # FDE CIE offset\n\t" |
| ".long 1b-. # FDE initial location\n\t" |
| ".long 4b-1b # FDE address range\n\t" |
| ".uleb128 0x0 # Augmentation size\n\t" |
| ".byte 0x16 # DW_CFA_val_expression\n\t" |
| ".uleb128 0x8\n\t" |
| ".uleb128 10f-9f\n" |
| "9:\t" ".byte 0x78 # DW_OP_breg8\n\t" |
| ".sleb128 3b-1b\n" |
| "10:\t" ".byte 0x40 + (2b-1b) # DW_CFA_advance_loc\n\t" |
| ".byte 0x16 # DW_CFA_val_expression\n\t" |
| ".uleb128 0x8\n\t" |
| ".uleb128 12f-11f\n" |
| "11:\t" ".byte 0x78 # DW_OP_breg8\n\t" |
| ".sleb128 3b-2b\n" |
| "12:\t" ".byte 0x40 + (3b-2b-1) # DW_CFA_advance_loc\n\t" |
| ".byte 0x16 # DW_CFA_val_expression\n\t" |
| ".uleb128 0x8\n\t" |
| ".uleb128 16f-13f\n" |
| "13:\t" ".byte 0x78 # DW_OP_breg8\n\t" |
| ".sleb128 15f-14f\n\t" |
| ".byte 0x0d # DW_OP_const4s\n" |
| "14:\t" ".4byte 3b-.\n\t" |
| ".byte 0x1c # DW_OP_minus\n\t" |
| ".byte 0x0d # DW_OP_const4s\n" |
| "15:\t" ".4byte 18f-.\n\t" |
| ".byte 0x22 # DW_OP_plus\n" |
| "16:\t" ".align 4\n" |
| "17:\t" ".previous\n" |
| "18:" |
| : : "r" (x), "m" (x), "r" (buf) |
| : "memory", "eax", "edx", "ecx"); |
| #elif defined __x86_64__ |
| __asm ( |
| "testl %0, %0\n\t" |
| "jnz 1f\n\t" |
| ".subsection 1\n\t" |
| ".type _L_mutex_lock_%=, @function\n" |
| "_L_mutex_lock_%=:\n" |
| "1:\t" "leaq %1, %%rdi\n" |
| "2:\t" "subq $136, %%rsp\n" |
| "3:\t" "call bar\n" |
| "4:\t" "addq $136, %%rsp\n" |
| "5:\t" "jmp 24f\n" |
| "6:\t" ".size _L_mutex_lock_%=, .-_L_mutex_lock_%=\n\t" |
| ".previous\n\t" |
| ".section .eh_frame,\"a\",@progbits\n" |
| "7:\t" ".long 9f-8f # Length of Common Information Entry\n" |
| "8:\t" ".long 0x0 # CIE Identifier Tag\n\t" |
| ".byte 0x1 # CIE Version\n\t" |
| ".ascii \"zR\\0\" # CIE Augmentation\n\t" |
| ".uleb128 0x1 # CIE Code Alignment Factor\n\t" |
| ".sleb128 -8 # CIE Data Alignment Factor\n\t" |
| ".byte 0x10 # CIE RA Column\n\t" |
| ".uleb128 0x1 # Augmentation size\n\t" |
| ".byte 0x1b # FDE Encoding (pcrel sdata4)\n\t" |
| ".byte 0x12 # DW_CFA_def_cfa_sf\n\t" |
| ".uleb128 0x7\n\t" |
| ".sleb128 16\n\t" |
| ".align 8\n" |
| "9:\t" ".long 23f-10f # FDE Length\n" |
| "10:\t" ".long 10b-7b # FDE CIE offset\n\t" |
| ".long 1b-. # FDE initial location\n\t" |
| ".long 6b-1b # FDE address range\n\t" |
| ".uleb128 0x0 # Augmentation size\n\t" |
| ".byte 0x16 # DW_CFA_val_expression\n\t" |
| ".uleb128 0x10\n\t" |
| ".uleb128 12f-11f\n" |
| "11:\t" ".byte 0x80 # DW_OP_breg16\n\t" |
| ".sleb128 4b-1b\n" |
| "12:\t" ".byte 0x40 + (2b-1b) # DW_CFA_advance_loc\n\t" |
| ".byte 0x16 # DW_CFA_val_expression\n\t" |
| ".uleb128 0x10\n\t" |
| ".uleb128 14f-13f\n" |
| "13:\t" ".byte 0x80 # DW_OP_breg16\n\t" |
| ".sleb128 4b-2b\n" |
| "14:\t" ".byte 0x40 + (3b-2b) # DW_CFA_advance_loc\n\t" |
| ".byte 0x0e # DW_CFA_def_cfa_offset\n\t" |
| ".uleb128 0\n\t" |
| ".byte 0x16 # DW_CFA_val_expression\n\t" |
| ".uleb128 0x10\n\t" |
| ".uleb128 16f-15f\n" |
| "15:\t" ".byte 0x80 # DW_OP_breg16\n\t" |
| ".sleb128 4b-3b\n" |
| "16:\t" ".byte 0x40 + (4b-3b-1) # DW_CFA_advance_loc\n\t" |
| ".byte 0x0e # DW_CFA_def_cfa_offset\n\t" |
| ".uleb128 136\n\t" |
| ".byte 0x16 # DW_CFA_val_expression\n\t" |
| ".uleb128 0x10\n\t" |
| ".uleb128 20f-17f\n" |
| "17:\t" ".byte 0x80 # DW_OP_breg16\n\t" |
| ".sleb128 19f-18f\n\t" |
| ".byte 0x0d # DW_OP_const4s\n" |
| "18:\t" ".4byte 4b-.\n\t" |
| ".byte 0x1c # DW_OP_minus\n\t" |
| ".byte 0x0d # DW_OP_const4s\n" |
| "19:\t" ".4byte 24f-.\n\t" |
| ".byte 0x22 # DW_OP_plus\n" |
| "20:\t" ".byte 0x40 + (5b-4b+1) # DW_CFA_advance_loc\n\t" |
| ".byte 0x13 # DW_CFA_def_cfa_offset_sf\n\t" |
| ".sleb128 16\n\t" |
| ".byte 0x16 # DW_CFA_val_expression\n\t" |
| ".uleb128 0x10\n\t" |
| ".uleb128 22f-21f\n" |
| "21:\t" ".byte 0x80 # DW_OP_breg16\n\t" |
| ".sleb128 4b-5b\n" |
| "22:\t" ".align 8\n" |
| "23:\t" ".previous\n" |
| "24:" |
| : : "r" (x), "m" (x), "r" (buf) |
| : "memory", "rax", "rdx", "rcx", "rsi", "rdi", |
| "r8", "r9", "r10", "r11"); |
| #else |
| # error Unsupported test architecture |
| #endif |
| } |
| |
| static int __attribute__((noinline)) |
| fn2 (void) |
| { |
| foo (3); |
| return 0; |
| } |
| |
| static int __attribute__((noinline)) |
| fn1 (void) |
| { |
| fn2 (); |
| return 0; |
| } |
| |
| static void * |
| fn0 (void) |
| { |
| char dummy __attribute__((cleanup (handler))); |
| fn1 (); |
| return 0; |
| } |
| |
| int |
| main (void) |
| { |
| fn0 (); |
| return 0; |
| } |