mirror of
https://gcc.gnu.org/git/gcc.git
synced 2025-01-12 14:04:22 +08:00
unwind-dw2.h (_Unwind_FrameState): Add REG_SAVED_VAL_OFFSET and REG_SAVED_VAL_EXP constants.
* unwind-dw2.h (_Unwind_FrameState): Add REG_SAVED_VAL_OFFSET and REG_SAVED_VAL_EXP constants. * unwind-dw2.c (struct _Unwind_Context): Add by_value array. (_Unwind_GetGR, _Unwind_SetGR, _Unwind_GetGRPtr, _Unwind_SetGRPtr): Handle regs stored by value. (_Unwind_SetGRValue, _Unwind_GRByValue): New functions. (execute_cfa_program): Handle DW_CFA_val_offset, DW_CFA_val_offset_sf and DW_CFA_val_expression. (uw_update_context_1): Handle REG_SAVED_REG with regs stored by value specially. Handle REG_SAVED_VAL_OFFSET and REG_SAVED_VAL_EXP. (uw_install_context_1): Handle target regs stored by value. * gcc.target/i386/cleanup-1.c: New test. * gcc.target/i386/cleanup-2.c: New test. From-SVN: r111705
This commit is contained in:
parent
636ffc571b
commit
4469af7acf
@ -1,3 +1,17 @@
|
||||
2006-03-04 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* unwind-dw2.h (_Unwind_FrameState): Add REG_SAVED_VAL_OFFSET
|
||||
and REG_SAVED_VAL_EXP constants.
|
||||
* unwind-dw2.c (struct _Unwind_Context): Add by_value array.
|
||||
(_Unwind_GetGR, _Unwind_SetGR, _Unwind_GetGRPtr, _Unwind_SetGRPtr):
|
||||
Handle regs stored by value.
|
||||
(_Unwind_SetGRValue, _Unwind_GRByValue): New functions.
|
||||
(execute_cfa_program): Handle DW_CFA_val_offset,
|
||||
DW_CFA_val_offset_sf and DW_CFA_val_expression.
|
||||
(uw_update_context_1): Handle REG_SAVED_REG with regs stored by
|
||||
value specially. Handle REG_SAVED_VAL_OFFSET and REG_SAVED_VAL_EXP.
|
||||
(uw_install_context_1): Handle target regs stored by value.
|
||||
|
||||
2006-03-03 Daniel Berlin <dberlin@dberlin.org>
|
||||
|
||||
* tree-sra.c (tree_sra): Return todoflags;
|
||||
|
@ -1,3 +1,8 @@
|
||||
2006-03-04 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gcc.target/i386/cleanup-1.c: New test.
|
||||
* gcc.target/i386/cleanup-2.c: New test.
|
||||
|
||||
2006-03-04 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* gfortran.dg/dependency_9.f90: Remove for the time being.
|
||||
|
240
gcc/testsuite/gcc.target/i386/cleanup-1.c
Normal file
240
gcc/testsuite/gcc.target/i386/cleanup-1.c
Normal file
@ -0,0 +1,240 @@
|
||||
/* { dg-do run { target i?86-*-linux* x86_64-*-linux* } } */
|
||||
/* { dg-options "-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2" } */
|
||||
/* Test complex CFA value expressions. */
|
||||
|
||||
#include <unwind.h>
|
||||
#include <stdlib.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 int __attribute__((noinline))
|
||||
fn5 (void)
|
||||
{
|
||||
char dummy __attribute__((cleanup (counter)));
|
||||
force_unwind ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
bar (void)
|
||||
{
|
||||
char dummy __attribute__((cleanup (counter)));
|
||||
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 $128, %%rsp\n"
|
||||
"3:\t" "call bar\n"
|
||||
"4:\t" "addq $128, %%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 128\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;
|
||||
}
|
205
gcc/testsuite/gcc.target/i386/cleanup-2.c
Normal file
205
gcc/testsuite/gcc.target/i386/cleanup-2.c
Normal file
@ -0,0 +1,205 @@
|
||||
/* { dg-do run { target { { i?86-*-linux* x86_64-*-linux* } && lp64 } } } */
|
||||
/* { dg-options "-fexceptions -fnon-call-exceptions -fasynchronous-unwind-tables -O2" } */
|
||||
/* Test complex CFA value expressions. */
|
||||
|
||||
#include <unwind.h>
|
||||
#include <stdlib.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 int __attribute__((noinline))
|
||||
fn5 (void)
|
||||
{
|
||||
char dummy __attribute__((cleanup (counter)));
|
||||
force_unwind ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
bar (void)
|
||||
{
|
||||
char dummy __attribute__((cleanup (counter)));
|
||||
fn5 ();
|
||||
}
|
||||
|
||||
void __attribute__((noinline))
|
||||
foo (int x)
|
||||
{
|
||||
char buf[256];
|
||||
#ifdef __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 $128, %%rsp\n"
|
||||
"3:\t" "call bar\n"
|
||||
"4:\t" "addq $128, %%rsp\n"
|
||||
"5:\t" "jmp 21f\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 0xc # DW_CFA_def_cfa\n\t"
|
||||
".uleb128 0x7\n\t"
|
||||
".uleb128 0x0\n\t"
|
||||
".align 8\n"
|
||||
"9:\t" ".long 20f-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"
|
||||
/* This CFA expression computes the address right
|
||||
past the jnz instruction above, from %rip somewhere
|
||||
within the _L_mutex_lock_%= subsection. */
|
||||
".byte 0x16 # DW_CFA_val_expression\n\t"
|
||||
".uleb128 0x10\n\t"
|
||||
".uleb128 19f-11f\n"
|
||||
"11:\t" ".byte 0x80 # DW_OP_breg16\n\t"
|
||||
".sleb128 0\n"
|
||||
"12:\t" ".byte 0x12 # DW_OP_dup\n\t"
|
||||
".byte 0x94 # DW_OP_deref_size\n\t"
|
||||
".byte 1\n\t"
|
||||
".byte 0x12 # DW_OP_dup\n\t"
|
||||
".byte 0x08 # DW_OP_const1u\n\t"
|
||||
".byte 0x48\n\t"
|
||||
".byte 0x2e # DW_OP_ne\n\t"
|
||||
".byte 0x28 # DW_OP_bra\n\t"
|
||||
".2byte 16f-13f\n"
|
||||
"13:\t" ".byte 0x13 # DW_OP_drop\n\t"
|
||||
".byte 0x23 # DW_OP_plus_uconst\n\t"
|
||||
".uleb128 1\n\t"
|
||||
".byte 0x12 # DW_OP_dup\n\t"
|
||||
".byte 0x94 # DW_OP_deref_size\n\t"
|
||||
".byte 1\n\t"
|
||||
".byte 0x08 # DW_OP_const1u\n\t"
|
||||
".byte 0x81\n\t"
|
||||
".byte 0x2e # DW_OP_ne\n\t"
|
||||
".byte 0x28 # DW_OP_bra\n\t"
|
||||
".2byte 15f-14f\n"
|
||||
"14:\t" ".byte 0x23 # DW_OP_plus_uconst\n\t"
|
||||
".uleb128 3b-2b-1\n\t"
|
||||
".byte 0x2f # DW_OP_skip\n\t"
|
||||
".2byte 12b-15f\n"
|
||||
"15:\t" ".byte 0x23 # DW_OP_plus_uconst\n\t"
|
||||
".uleb128 2b-1b-1\n\t"
|
||||
".byte 0x2f # DW_OP_skip\n\t"
|
||||
".2byte 12b-16f\n"
|
||||
"16:\t" ".byte 0x08 # DW_OP_const1u\n\t"
|
||||
".byte 0xe8\n\t"
|
||||
".byte 0x2e # DW_OP_ne\n\t"
|
||||
".byte 0x28 # DW_OP_bra\n\t"
|
||||
".2byte 18f-17f\n"
|
||||
"17:\t" ".byte 0x23 # DW_OP_plus_uconst\n\t"
|
||||
".uleb128 4b-3b\n\t"
|
||||
".byte 0x2f # DW_OP_skip\n\t"
|
||||
".2byte 12b-18f\n"
|
||||
"18:\t" ".byte 0x23 # DW_OP_plus_uconst\n\t"
|
||||
".uleb128 1\n\t"
|
||||
".byte 0x12 # DW_OP_dup\n\t"
|
||||
".byte 0x94 # DW_OP_deref_size\n\t"
|
||||
".byte 4\n\t"
|
||||
".byte 0x08 # DW_OP_const1u\n\t"
|
||||
".byte 72 - (6b-5b) * 8 # (6b-5b) == 5 ? 32 : 56\n\t"
|
||||
".byte 0x24 # DW_OP_shl\n\t"
|
||||
".byte 0x08 # DW_OP_const1u\n\t"
|
||||
".byte 72 - (6b-5b) * 8 # (6b-5b) == 5 ? 32 : 56\n\t"
|
||||
".byte 0x26 # DW_OP_shra\n\t"
|
||||
".byte 0x22 # DW_OP_plus\n\t"
|
||||
".byte 0x23 # DW_OP_plus_uconst\n\t"
|
||||
".uleb128 6b-5b-1\n"
|
||||
"19:\t" ".byte 0x40 + (3b-1b) # DW_CFA_advance_loc\n\t"
|
||||
".byte 0xe # DW_CFA_def_cfa_offset\n\t"
|
||||
".uleb128 128\n\t"
|
||||
".byte 0x40 + (5b-3b) # DW_CFA_advance_loc\n\t"
|
||||
".byte 0xe # DW_CFA_def_cfa_offset\n\t"
|
||||
".uleb128 0\n\t"
|
||||
".align 8\n"
|
||||
"20:\t" ".previous\n"
|
||||
"21:"
|
||||
: : "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;
|
||||
}
|
124
gcc/unwind-dw2.c
124
gcc/unwind-dw2.c
@ -72,6 +72,7 @@ struct _Unwind_Context
|
||||
struct dwarf_eh_bases bases;
|
||||
_Unwind_Word args_size;
|
||||
char signal_frame;
|
||||
char by_value[DWARF_FRAME_REGISTERS+1];
|
||||
};
|
||||
|
||||
/* Byte size of every register managed by these routines. */
|
||||
@ -118,7 +119,7 @@ read_8u (const void *p) { const union unaligned *up = p; return up->u8; }
|
||||
static inline unsigned long
|
||||
read_8s (const void *p) { const union unaligned *up = p; return up->s8; }
|
||||
|
||||
/* Get the value of register REG as saved in CONTEXT. */
|
||||
/* Get the value of register INDEX as saved in CONTEXT. */
|
||||
|
||||
inline _Unwind_Word
|
||||
_Unwind_GetGR (struct _Unwind_Context *context, int index)
|
||||
@ -136,6 +137,9 @@ _Unwind_GetGR (struct _Unwind_Context *context, int index)
|
||||
size = dwarf_reg_size_table[index];
|
||||
ptr = context->reg[index];
|
||||
|
||||
if (context->by_value[index])
|
||||
return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr;
|
||||
|
||||
/* This will segfault if the register hasn't been saved. */
|
||||
if (size == sizeof(_Unwind_Ptr))
|
||||
return * (_Unwind_Ptr *) ptr;
|
||||
@ -160,7 +164,7 @@ _Unwind_GetCFA (struct _Unwind_Context *context)
|
||||
return (_Unwind_Ptr) context->cfa;
|
||||
}
|
||||
|
||||
/* Overwrite the saved value for register REG in CONTEXT with VAL. */
|
||||
/* Overwrite the saved value for register INDEX in CONTEXT with VAL. */
|
||||
|
||||
inline void
|
||||
_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
|
||||
@ -171,6 +175,13 @@ _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
|
||||
index = DWARF_REG_TO_UNWIND_COLUMN (index);
|
||||
gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
|
||||
size = dwarf_reg_size_table[index];
|
||||
|
||||
if (context->by_value[index])
|
||||
{
|
||||
context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
|
||||
return;
|
||||
}
|
||||
|
||||
ptr = context->reg[index];
|
||||
|
||||
if (size == sizeof(_Unwind_Ptr))
|
||||
@ -188,6 +199,8 @@ static inline void *
|
||||
_Unwind_GetGRPtr (struct _Unwind_Context *context, int index)
|
||||
{
|
||||
index = DWARF_REG_TO_UNWIND_COLUMN (index);
|
||||
if (context->by_value[index])
|
||||
return &context->reg[index];
|
||||
return context->reg[index];
|
||||
}
|
||||
|
||||
@ -197,9 +210,34 @@ static inline void
|
||||
_Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p)
|
||||
{
|
||||
index = DWARF_REG_TO_UNWIND_COLUMN (index);
|
||||
context->by_value[index] = 0;
|
||||
context->reg[index] = p;
|
||||
}
|
||||
|
||||
/* Overwrite the saved value for register INDEX in CONTEXT with VAL. */
|
||||
|
||||
static inline void
|
||||
_Unwind_SetGRValue (struct _Unwind_Context *context, int index,
|
||||
_Unwind_Word val)
|
||||
{
|
||||
index = DWARF_REG_TO_UNWIND_COLUMN (index);
|
||||
gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
|
||||
gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Ptr));
|
||||
|
||||
context->by_value[index] = 1;
|
||||
context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
|
||||
}
|
||||
|
||||
/* Return non-zero if register INDEX is stored by value rather than
|
||||
by reference. */
|
||||
|
||||
static inline int
|
||||
_Unwind_GRByValue (struct _Unwind_Context *context, int index)
|
||||
{
|
||||
index = DWARF_REG_TO_UNWIND_COLUMN (index);
|
||||
return context->by_value[index];
|
||||
}
|
||||
|
||||
/* Retrieve the return address for CONTEXT. */
|
||||
|
||||
inline _Unwind_Ptr
|
||||
@ -922,7 +960,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
|
||||
insn_ptr += utmp;
|
||||
break;
|
||||
|
||||
/* From the dwarf3 draft. */
|
||||
/* Dwarf3. */
|
||||
case DW_CFA_offset_extended_sf:
|
||||
insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
insn_ptr = read_sleb128 (insn_ptr, &stmp);
|
||||
@ -945,6 +983,33 @@ execute_cfa_program (const unsigned char *insn_ptr,
|
||||
/* cfa_how deliberately not set. */
|
||||
break;
|
||||
|
||||
case DW_CFA_val_offset:
|
||||
insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
offset = (_Unwind_Sword) utmp * fs->data_align;
|
||||
fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
|
||||
= REG_SAVED_VAL_OFFSET;
|
||||
fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
|
||||
break;
|
||||
|
||||
case DW_CFA_val_offset_sf:
|
||||
insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
insn_ptr = read_sleb128 (insn_ptr, &stmp);
|
||||
offset = stmp * fs->data_align;
|
||||
fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
|
||||
= REG_SAVED_VAL_OFFSET;
|
||||
fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset;
|
||||
break;
|
||||
|
||||
case DW_CFA_val_expression:
|
||||
insn_ptr = read_uleb128 (insn_ptr, ®);
|
||||
fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how
|
||||
= REG_SAVED_VAL_EXP;
|
||||
fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr;
|
||||
insn_ptr = read_uleb128 (insn_ptr, &utmp);
|
||||
insn_ptr += utmp;
|
||||
break;
|
||||
|
||||
case DW_CFA_GNU_window_save:
|
||||
/* ??? Hardcoded for SPARC register window configuration. */
|
||||
for (reg = 16; reg < 32; ++reg)
|
||||
@ -1113,7 +1178,7 @@ typedef union { _Unwind_Ptr ptr; _Unwind_Word word; } _Unwind_SpTmp;
|
||||
|
||||
static inline void
|
||||
_Unwind_SetSpColumn (struct _Unwind_Context *context, void *cfa,
|
||||
_Unwind_SpTmp *tmp_sp)
|
||||
_Unwind_SpTmp *tmp_sp)
|
||||
{
|
||||
int size = dwarf_reg_size_table[__builtin_dwarf_sp_column ()];
|
||||
|
||||
@ -1194,9 +1259,14 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
|
||||
break;
|
||||
|
||||
case REG_SAVED_REG:
|
||||
_Unwind_SetGRPtr
|
||||
(context, i,
|
||||
_Unwind_GetGRPtr (&orig_context, fs->regs.reg[i].loc.reg));
|
||||
if (_Unwind_GRByValue (&orig_context, fs->regs.reg[i].loc.reg))
|
||||
_Unwind_SetGRValue (context, i,
|
||||
_Unwind_GetGR (&orig_context,
|
||||
fs->regs.reg[i].loc.reg));
|
||||
else
|
||||
_Unwind_SetGRPtr (context, i,
|
||||
_Unwind_GetGRPtr (&orig_context,
|
||||
fs->regs.reg[i].loc.reg));
|
||||
break;
|
||||
|
||||
case REG_SAVED_EXP:
|
||||
@ -1211,6 +1281,25 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
|
||||
_Unwind_SetGRPtr (context, i, (void *) val);
|
||||
}
|
||||
break;
|
||||
|
||||
case REG_SAVED_VAL_OFFSET:
|
||||
_Unwind_SetGRValue (context, i,
|
||||
(_Unwind_Internal_Ptr)
|
||||
(cfa + fs->regs.reg[i].loc.offset));
|
||||
break;
|
||||
|
||||
case REG_SAVED_VAL_EXP:
|
||||
{
|
||||
const unsigned char *exp = fs->regs.reg[i].loc.exp;
|
||||
_Unwind_Word len;
|
||||
_Unwind_Ptr val;
|
||||
|
||||
exp = read_uleb128 (exp, &len);
|
||||
val = execute_stack_op (exp, exp + len, &orig_context,
|
||||
(_Unwind_Ptr) cfa);
|
||||
_Unwind_SetGRValue (context, i, val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
context->signal_frame = fs->signal_frame;
|
||||
@ -1327,14 +1416,31 @@ uw_install_context_1 (struct _Unwind_Context *current,
|
||||
/* If the target frame does not have a saved stack pointer,
|
||||
then set up the target's CFA. */
|
||||
if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ()))
|
||||
_Unwind_SetSpColumn (target, target->cfa, &sp_slot);
|
||||
_Unwind_SetSpColumn (target, target->cfa, &sp_slot);
|
||||
|
||||
for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
|
||||
{
|
||||
void *c = current->reg[i];
|
||||
void *t = target->reg[i];
|
||||
|
||||
if (t && c && t != c)
|
||||
gcc_assert (current->by_value[i] == 0);
|
||||
if (target->by_value[i] && c)
|
||||
{
|
||||
_Unwind_Word w;
|
||||
_Unwind_Ptr p;
|
||||
if (dwarf_reg_size_table[i] == sizeof (_Unwind_Word))
|
||||
{
|
||||
w = (_Unwind_Internal_Ptr) t;
|
||||
memcpy (c, &w, sizeof (_Unwind_Word));
|
||||
}
|
||||
else
|
||||
{
|
||||
gcc_assert (dwarf_reg_size_table[i] == sizeof (_Unwind_Ptr));
|
||||
p = (_Unwind_Internal_Ptr) t;
|
||||
memcpy (c, &p, sizeof (_Unwind_Ptr));
|
||||
}
|
||||
}
|
||||
else if (t && c && t != c)
|
||||
memcpy (c, t, dwarf_reg_size_table[i]);
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,9 @@ typedef struct
|
||||
REG_UNSAVED,
|
||||
REG_SAVED_OFFSET,
|
||||
REG_SAVED_REG,
|
||||
REG_SAVED_EXP
|
||||
REG_SAVED_EXP,
|
||||
REG_SAVED_VAL_OFFSET,
|
||||
REG_SAVED_VAL_EXP
|
||||
} how;
|
||||
} reg[DWARF_FRAME_REGISTERS+1];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user