From 74d9c39f6aeaec9ed8a99167890283f4519219dd Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Wed, 16 Nov 2005 17:08:05 +0000 Subject: [PATCH] unwind-arm.c (abort): Add prototype here. gcc/ * config/arm/unwind-arm.c (abort): Add prototype here. (UCB_FORCED_STOP_ARG): Correct typo in macro argument. (struct phase1_vrs): Add prev_sp. (unwind_phase2_forced): Save the original core registers instead of modifying entry_vrs. Take a new flag argument for resuming unwinding and set action flags accordingly. Always set _US_END_OF_STACK when get_eit_entry fails. Unwind before calling the stop function. (_Unwind_GetCFA): New function. (__gnu_Unwind_ForcedUnwind): Update call to unwind_phase2_forced. (__gnu_Unwind_Resume_or_Rethrow): Likewise. (__gnu_Unwind_Resume): Do not unwind here for forced unwinding; just call unwind_phase2_forced. (_Unwind_GetDataRelBase, _Unwind_GetTextRelBase): Move to here. * config/arm/unwind-arm.h (abort): Remove prototype. (_Unwind_GetDataRelBase, _Unwind_GetTextRelBase): Change to prototypes. (_Unwind_GetCFA): New prototype. * config/arm/pr-support.c (abort): Add prototype here. * unwind-c.c (PERSONALITY_FUNCTION) [__ARM_EABI_UNWINDER__]: Handle forced unwinding. * config/arm/arm.c (arm_expand_prologue, thumb_expand_prologue): Do not schedule the prologue with non-call exceptions and EABI. gcc/testsuite/ * gcc.dg/cleanup-5.c, gcc.dg/cleanup-8.c, gcc.dg/cleanup-9.c, gcc.dg/cleanup-10.c, gcc.dg/cleanup-11.c: Update for ARM EABI. From-SVN: r107091 --- gcc/ChangeLog | 25 ++++++ gcc/config/arm/arm.c | 15 +++- gcc/config/arm/pr-support.c | 4 + gcc/config/arm/unwind-arm.c | 121 +++++++++++++++++++++++------- gcc/config/arm/unwind-arm.h | 20 +---- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/cleanup-10.c | 3 +- gcc/testsuite/gcc.dg/cleanup-11.c | 3 +- gcc/testsuite/gcc.dg/cleanup-5.c | 3 +- gcc/testsuite/gcc.dg/cleanup-8.c | 3 +- gcc/testsuite/gcc.dg/cleanup-9.c | 3 +- gcc/unwind-c.c | 2 +- 12 files changed, 154 insertions(+), 53 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 34205f18fbb..0b14036d431 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2005-11-16 Daniel Jacobowitz + + * config/arm/unwind-arm.c (abort): Add prototype here. + (UCB_FORCED_STOP_ARG): Correct typo in macro argument. + (struct phase1_vrs): Add prev_sp. + (unwind_phase2_forced): Save the original core registers instead of + modifying entry_vrs. Take a new flag argument for resuming unwinding + and set action flags accordingly. Always set _US_END_OF_STACK when + get_eit_entry fails. Unwind before calling the stop function. + (_Unwind_GetCFA): New function. + (__gnu_Unwind_ForcedUnwind): Update call to unwind_phase2_forced. + (__gnu_Unwind_Resume_or_Rethrow): Likewise. + (__gnu_Unwind_Resume): Do not unwind here for forced unwinding; + just call unwind_phase2_forced. + (_Unwind_GetDataRelBase, _Unwind_GetTextRelBase): Move to here. + * config/arm/unwind-arm.h (abort): Remove prototype. + (_Unwind_GetDataRelBase, _Unwind_GetTextRelBase): Change to + prototypes. + (_Unwind_GetCFA): New prototype. + * config/arm/pr-support.c (abort): Add prototype here. + * unwind-c.c (PERSONALITY_FUNCTION) [__ARM_EABI_UNWINDER__]: Handle + forced unwinding. + * config/arm/arm.c (arm_expand_prologue, thumb_expand_prologue): Do + not schedule the prologue with non-call exceptions and EABI. + 2005-11-16 Nathan Sidwell * config/arm/unwind-arm.h: Reorder interface function declarations. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index c3a7562f8fa..b2fad5634e1 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -10850,8 +10850,11 @@ arm_expand_prologue (void) /* If we are profiling, make sure no instructions are scheduled before the call to mcount. Similarly if the user has requested no - scheduling in the prolog. */ - if (current_function_profile || !TARGET_SCHED_PROLOG) + scheduling in the prolog. Similarly if we want non-call exceptions + using the EABI unwinder, to prevent faulting instructions from being + swapped with a stack adjustment. */ + if (current_function_profile || !TARGET_SCHED_PROLOG + || (ARM_EABI_UNWIND_TABLES && flag_non_call_exceptions)) emit_insn (gen_blockage ()); /* If the link register is being kept alive, with the return address in it, @@ -13714,7 +13717,13 @@ thumb_expand_prologue (void) RTX_FRAME_RELATED_P (insn) = 1; } - if (current_function_profile || !TARGET_SCHED_PROLOG) + /* If we are profiling, make sure no instructions are scheduled before + the call to mcount. Similarly if the user has requested no + scheduling in the prolog. Similarly if we want non-call exceptions + using the EABI unwinder, to prevent faulting instructions from being + swapped with a stack adjustment. */ + if (current_function_profile || !TARGET_SCHED_PROLOG + || (ARM_EABI_UNWIND_TABLES && flag_non_call_exceptions)) emit_insn (gen_blockage ()); cfun->machine->lr_save_eliminated = !thumb_force_lr_save (); diff --git a/gcc/config/arm/pr-support.c b/gcc/config/arm/pr-support.c index 8ea1e608921..072b4a98d5c 100644 --- a/gcc/config/arm/pr-support.c +++ b/gcc/config/arm/pr-support.c @@ -27,6 +27,10 @@ Boston, MA 02110-1301, USA. */ #include "unwind.h" +/* We add a prototype for abort here to avoid creating a dependency on + target headers. */ +extern void abort (void); + typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */ /* Misc constants. */ diff --git a/gcc/config/arm/unwind-arm.c b/gcc/config/arm/unwind-arm.c index 4d703dbf09a..b3f8a00dcb5 100644 --- a/gcc/config/arm/unwind-arm.c +++ b/gcc/config/arm/unwind-arm.c @@ -27,6 +27,10 @@ Boston, MA 02110-1301, USA. */ #include "unwind.h" +/* We add a prototype for abort here to avoid creating a dependency on + target headers. */ +extern void abort (void); + /* Definitions for C++ runtime support routines. We make these weak declarations to avoid pulling in libsupc++ unnecessarily. */ typedef unsigned char bool; @@ -54,7 +58,7 @@ __gnu_Unwind_Find_exidx (_Unwind_Ptr, int *); #define UCB_FORCED_STOP_FN(ucbp) ((ucbp)->unwinder_cache.reserved1) #define UCB_PR_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved2) #define UCB_SAVED_CALLSITE_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved3) -#define UCB_FORCED_STOP_ARG(ucb) ((ucbp)->unwinder_cache.reserved4) +#define UCB_FORCED_STOP_ARG(ucbp) ((ucbp)->unwinder_cache.reserved4) struct core_regs { @@ -107,6 +111,7 @@ typedef struct /* The first fields must be the same as a phase2_vrs. */ _uw demand_save_flags; struct core_regs core; + _uw prev_sp; /* Only valid during forced unwinding. */ struct vfp_regs vfp; struct fpa_regs fpa; } phase1_vrs; @@ -497,11 +502,21 @@ unwind_phase2 (_Unwind_Control_Block * ucbp, phase2_vrs * vrs) /* Perform phase2 forced unwinding. */ static _Unwind_Reason_Code -unwind_phase2_forced (_Unwind_Control_Block *ucbp, phase2_vrs *entry_vrs) +unwind_phase2_forced (_Unwind_Control_Block *ucbp, phase2_vrs *entry_vrs, + int resuming) { _Unwind_Stop_Fn stop_fn = (_Unwind_Stop_Fn) UCB_FORCED_STOP_FN (ucbp); void *stop_arg = (void *)UCB_FORCED_STOP_ARG (ucbp); - _Unwind_Reason_Code pr_result; + _Unwind_Reason_Code pr_result = 0; + /* We use phase1_vrs here even though we do not demand save, for the + prev_sp field. */ + phase1_vrs saved_vrs, next_vrs; + + /* Save the core registers. */ + saved_vrs.core = entry_vrs->core; + /* We don't need to demand-save the non-core registers, because we + unwind in a single pass. */ + saved_vrs.demand_save_flags = 0; /* Unwind until we reach a propagation barrier. */ do @@ -511,27 +526,51 @@ unwind_phase2_forced (_Unwind_Control_Block *ucbp, phase2_vrs *entry_vrs) _Unwind_Reason_Code stop_code; /* Find the entry for this routine. */ - entry_code = get_eit_entry (ucbp, entry_vrs->core.r[R_PC]); + entry_code = get_eit_entry (ucbp, saved_vrs.core.r[R_PC]); - action = _US_UNWIND_FRAME_STARTING | _US_FORCE_UNWIND; - if (entry_code == _URC_END_OF_STACK) - action |= _US_END_OF_STACK; - else if (entry_code != _URC_OK) - return _URC_FAILURE; + if (resuming) + { + action = _US_UNWIND_FRAME_RESUME | _US_FORCE_UNWIND; + resuming = 0; + } + else + action = _US_UNWIND_FRAME_STARTING | _US_FORCE_UNWIND; + + if (entry_code == _URC_OK) + { + UCB_SAVED_CALLSITE_ADDR (ucbp) = saved_vrs.core.r[R_PC]; + + next_vrs = saved_vrs; + + /* Call the pr to decide what to do. */ + pr_result = ((personality_routine) UCB_PR_ADDR (ucbp)) + (action, ucbp, (void *) &next_vrs); + + saved_vrs.prev_sp = next_vrs.core.r[R_SP]; + } + else + { + /* Treat any failure as the end of unwinding, to cope more + gracefully with missing EH information. Mixed EH and + non-EH within one object will usually result in failure, + because the .ARM.exidx tables do not indicate the end + of the code to which they apply; but mixed EH and non-EH + shared objects should return an unwind failure at the + entry of a non-EH shared object. */ + action |= _US_END_OF_STACK; + + saved_vrs.prev_sp = saved_vrs.core.r[R_SP]; + } stop_code = stop_fn (1, action, ucbp->exception_class, ucbp, - (void *)entry_vrs, stop_arg); + (void *)&saved_vrs, stop_arg); if (stop_code != _URC_NO_REASON) return _URC_FAILURE; - if (entry_code == _URC_END_OF_STACK) + if (entry_code != _URC_OK) return entry_code; - UCB_SAVED_CALLSITE_ADDR (ucbp) = entry_vrs->core.r[R_PC]; - - /* Call the pr to decide what to do. */ - pr_result = ((personality_routine) UCB_PR_ADDR (ucbp)) - (action, ucbp, (void *) entry_vrs); + saved_vrs = next_vrs; } while (pr_result == _URC_CONTINUE_UNWIND); @@ -542,7 +581,20 @@ unwind_phase2_forced (_Unwind_Control_Block *ucbp, phase2_vrs *entry_vrs) return _URC_FAILURE; } - restore_core_regs (&entry_vrs->core); + restore_core_regs (&saved_vrs.core); +} + +/* This is a very limited implementation of _Unwind_GetCFA. It returns + the stack pointer as it is about to be unwound, and is only valid + while calling the stop function during forced unwinding. If the + current personality routine result is going to run a cleanup, this + will not be the CFA; but when the frame is really unwound, it will + be. */ + +_Unwind_Word +_Unwind_GetCFA (_Unwind_Context *context) +{ + return ((phase1_vrs *) context)->prev_sp; } /* Perform phase1 unwinding. UCBP is the exception being thrown, and @@ -610,7 +662,7 @@ __gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *ucbp, /* Set the pc to the call site. */ entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR]; - return unwind_phase2_forced (ucbp, entry_vrs); + return unwind_phase2_forced (ucbp, entry_vrs, 0); } _Unwind_Reason_Code @@ -620,18 +672,21 @@ _Unwind_Reason_Code __gnu_Unwind_Resume (_Unwind_Control_Block * ucbp, phase2_vrs * entry_vrs) { _Unwind_Reason_Code pr_result; - _Unwind_State action; /* Recover the saved address. */ entry_vrs->core.r[R_PC] = UCB_SAVED_CALLSITE_ADDR (ucbp); - /* Call the cached PR. */ - action = _US_UNWIND_FRAME_RESUME; if (UCB_FORCED_STOP_FN (ucbp)) - action |= _US_FORCE_UNWIND; + { + unwind_phase2_forced (ucbp, entry_vrs, 1); + /* We can't return failure at this point. */ + abort (); + } + + /* Call the cached PR. */ pr_result = ((personality_routine) UCB_PR_ADDR (ucbp)) - (action, ucbp, (_Unwind_Context *) entry_vrs); + (_US_UNWIND_FRAME_RESUME, ucbp, (_Unwind_Context *) entry_vrs); switch (pr_result) { @@ -641,10 +696,7 @@ __gnu_Unwind_Resume (_Unwind_Control_Block * ucbp, phase2_vrs * entry_vrs) case _URC_CONTINUE_UNWIND: /* Continue unwinding the next frame. */ - if (UCB_FORCED_STOP_FN (ucbp)) - return unwind_phase2_forced (ucbp, entry_vrs); - else - unwind_phase2 (ucbp, entry_vrs); + unwind_phase2 (ucbp, entry_vrs); default: abort (); @@ -664,7 +716,7 @@ __gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block * ucbp, /* Set the pc to the call site. */ entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR]; /* Continue unwinding the next frame. */ - return unwind_phase2_forced (ucbp, entry_vrs); + return unwind_phase2_forced (ucbp, entry_vrs, 0); } /* Clean up an exception object when unwinding is complete. */ @@ -947,3 +999,16 @@ __aeabi_unwind_cpp_pr2 (_Unwind_State state, { return __gnu_unwind_pr_common (state, ucbp, context, 2); } + +/* These two should never be used. */ +_Unwind_Ptr +_Unwind_GetDataRelBase (_Unwind_Context *context __attribute__ ((unused))) +{ + abort (); +} + +_Unwind_Ptr +_Unwind_GetTextRelBase (_Unwind_Context *context __attribute__ ((unused))) +{ + abort (); +} diff --git a/gcc/config/arm/unwind-arm.h b/gcc/config/arm/unwind-arm.h index f0c545ff797..dd8d2affe39 100644 --- a/gcc/config/arm/unwind-arm.h +++ b/gcc/config/arm/unwind-arm.h @@ -37,10 +37,6 @@ #ifdef __cplusplus extern "C" { #endif - /* We add a prototype for abort here to avoid creating a dependency on - target headers. */ - extern void abort(); - typedef unsigned _Unwind_Word __attribute__((__mode__(__word__))); typedef signed _Unwind_Sword __attribute__((__mode__(__word__))); typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); @@ -195,18 +191,9 @@ extern "C" { void * _Unwind_GetLanguageSpecificData (_Unwind_Context *); _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *); - /* These two should never be used */ - static inline _Unwind_Ptr - _Unwind_GetDataRelBase (_Unwind_Context * context __attribute__ ((unused))) - { - abort (); - } - - static inline _Unwind_Ptr - _Unwind_GetTextRelBase (_Unwind_Context * context __attribute__ ((unused))) - { - abort (); - } + /* These two should never be used. */ + _Unwind_Ptr _Unwind_GetDataRelBase (_Unwind_Context *); + _Unwind_Ptr _Unwind_GetTextRelBase (_Unwind_Context *); /* Interface functions: */ _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp); @@ -218,6 +205,7 @@ extern "C" { _Unwind_Control_Block *, struct _Unwind_Context *, void *); _Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *, _Unwind_Stop_Fn, void *); + _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *); void _Unwind_Complete(_Unwind_Control_Block *ucbp); void _Unwind_DeleteException (_Unwind_Exception *); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 63f6361687b..22335ac22fc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-11-16 Daniel Jacobowitz + + * gcc.dg/cleanup-5.c, gcc.dg/cleanup-8.c, gcc.dg/cleanup-9.c, + gcc.dg/cleanup-10.c, gcc.dg/cleanup-11.c: Update for ARM EABI. + 2005-11-16 Nathan Sidwell * g++.dg/eh/forced1.C: Adjust to cope with ARM EABI diff --git a/gcc/testsuite/gcc.dg/cleanup-10.c b/gcc/testsuite/gcc.dg/cleanup-10.c index 35936eabb53..e8ae3bca78e 100644 --- a/gcc/testsuite/gcc.dg/cleanup-10.c +++ b/gcc/testsuite/gcc.dg/cleanup-10.c @@ -7,6 +7,7 @@ #include #include #include +#include static _Unwind_Reason_Code force_unwind_stop (int version, _Unwind_Action actions, @@ -23,7 +24,7 @@ force_unwind_stop (int version, _Unwind_Action actions, static void force_unwind () { struct _Unwind_Exception *exc = malloc (sizeof (*exc)); - exc->exception_class = 0; + memset (&exc->exception_class, 0, sizeof (exc->exception_class)); exc->exception_cleanup = 0; #ifndef __USING_SJLJ_EXCEPTIONS__ diff --git a/gcc/testsuite/gcc.dg/cleanup-11.c b/gcc/testsuite/gcc.dg/cleanup-11.c index 447b3986222..ff315f73d7a 100644 --- a/gcc/testsuite/gcc.dg/cleanup-11.c +++ b/gcc/testsuite/gcc.dg/cleanup-11.c @@ -7,6 +7,7 @@ #include #include #include +#include static _Unwind_Reason_Code force_unwind_stop (int version, _Unwind_Action actions, @@ -23,7 +24,7 @@ force_unwind_stop (int version, _Unwind_Action actions, static void force_unwind () { struct _Unwind_Exception *exc = malloc (sizeof (*exc)); - exc->exception_class = 0; + memset (&exc->exception_class, 0, sizeof (exc->exception_class)); exc->exception_cleanup = 0; #ifndef __USING_SJLJ_EXCEPTIONS__ diff --git a/gcc/testsuite/gcc.dg/cleanup-5.c b/gcc/testsuite/gcc.dg/cleanup-5.c index 497ab0be90f..c335c1e4492 100644 --- a/gcc/testsuite/gcc.dg/cleanup-5.c +++ b/gcc/testsuite/gcc.dg/cleanup-5.c @@ -6,6 +6,7 @@ #include #include +#include static _Unwind_Reason_Code force_unwind_stop (int version, _Unwind_Action actions, @@ -22,7 +23,7 @@ force_unwind_stop (int version, _Unwind_Action actions, static void force_unwind () { struct _Unwind_Exception *exc = malloc (sizeof (*exc)); - exc->exception_class = 0; + memset (&exc->exception_class, 0, sizeof (exc->exception_class)); exc->exception_cleanup = 0; #ifndef __USING_SJLJ_EXCEPTIONS__ diff --git a/gcc/testsuite/gcc.dg/cleanup-8.c b/gcc/testsuite/gcc.dg/cleanup-8.c index 25bc305adc1..321e1f029df 100644 --- a/gcc/testsuite/gcc.dg/cleanup-8.c +++ b/gcc/testsuite/gcc.dg/cleanup-8.c @@ -6,6 +6,7 @@ #include #include #include +#include static _Unwind_Reason_Code force_unwind_stop (int version, _Unwind_Action actions, @@ -22,7 +23,7 @@ force_unwind_stop (int version, _Unwind_Action actions, static void force_unwind () { struct _Unwind_Exception *exc = malloc (sizeof (*exc)); - exc->exception_class = 0; + memset (&exc->exception_class, 0, sizeof (exc->exception_class)); exc->exception_cleanup = 0; #ifndef __USING_SJLJ_EXCEPTIONS__ diff --git a/gcc/testsuite/gcc.dg/cleanup-9.c b/gcc/testsuite/gcc.dg/cleanup-9.c index 4cf4a413fa4..c3ac5fb726b 100644 --- a/gcc/testsuite/gcc.dg/cleanup-9.c +++ b/gcc/testsuite/gcc.dg/cleanup-9.c @@ -6,6 +6,7 @@ #include #include #include +#include static _Unwind_Reason_Code force_unwind_stop (int version, _Unwind_Action actions, @@ -22,7 +23,7 @@ force_unwind_stop (int version, _Unwind_Action actions, static void force_unwind () { struct _Unwind_Exception *exc = malloc (sizeof (*exc)); - exc->exception_class = 0; + memset (&exc->exception_class, 0, sizeof (exc->exception_class)); exc->exception_cleanup = 0; #ifndef __USING_SJLJ_EXCEPTIONS__ diff --git a/gcc/unwind-c.c b/gcc/unwind-c.c index 6fb66e0b738..e3e2eca1804 100644 --- a/gcc/unwind-c.c +++ b/gcc/unwind-c.c @@ -129,7 +129,7 @@ PERSONALITY_FUNCTION (int version, _Unwind_Ptr landing_pad, ip; #ifdef __ARM_EABI_UNWINDER__ - if (state != _US_UNWIND_FRAME_STARTING) + if ((state & _US_ACTION_MASK) != _US_UNWIND_FRAME_STARTING) CONTINUE_UNWINDING; /* The dwarf unwinder assumes the context structure holds things like the -- 2.30.2