diff options
-rw-r--r-- | gcc/ChangeLog | 25 | ||||
-rw-r--r-- | gcc/config/arm/libunwind.S | 12 | ||||
-rw-r--r-- | gcc/config/arm/unwind-arm.c | 130 | ||||
-rw-r--r-- | gcc/config/arm/unwind-arm.h | 73 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/forced1.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/forced2.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/forced3.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/forced4.C | 4 | ||||
-rw-r--r-- | libstdc++-v3/ChangeLog | 10 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_arm.cc | 43 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_personality.cc | 14 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/eh_throw.cc | 2 |
13 files changed, 254 insertions, 82 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c7f4f79..34205f1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2005-11-16 Nathan Sidwell <nathan@codesourcery.com> + + * config/arm/unwind-arm.h: Reorder interface function declarations. + (_URC_END_OF_STACK): New enumeration value. + (_US_UNWIND_ACTION_MASK, _US_FORCE_UNWIND, _US_END_OF_STACK): Likewise. + (struct _Unwind_Control_Block): Document reserved field use. + (_Unwind_Stop_Fn): New typedef. + (_Unwind_ForcedUnwind): Declare. + (_Unwind_Resume_or_Rethrow): Declare. + * gcc/config/arm/libunwind.S (UNWIND_WRAPER): Add nargs + argument. Adjust. + (_Unwind_Resume_or_Rethrow, _Unwind_ForcedUnwind): New. + * config/arm/unwind-arm.c (UCB_FORCED_STOP_FN) + (UCB_FORCED_STOP_ARG): New. + (search_EIT_table): Update boundary condition checks. + (get_eit_entry): Return _URC_END_OF_STACK when cannot unwind. + (unwind_phase2): Replace for with do..while. + (unwind_phase2_forced): New. + (__gnu_Unwind_RaiseException): Replace for with do..while. + (__gnu_Unwind_ForcedUnwind): New. + (__gnu_Unwind_Resume): Set FORCE_UNWIND flag, if forced unwinding. + Use appropriate phase2 unwinder. + (__gnu_Unwind_Resume_or_Rethrow): New. + (__gnu_unwind_pr_common): Cope with forced unwinding. + 2005-11-16 David Edelsohn <edelsohn@gnu.org> PR target/24772 diff --git a/gcc/config/arm/libunwind.S b/gcc/config/arm/libunwind.S index 8d226df..06e1310 100644 --- a/gcc/config/arm/libunwind.S +++ b/gcc/config/arm/libunwind.S @@ -78,7 +78,7 @@ ARM_FUNC_START gnu_Unwind_Save_VFP /* Wrappers to save core registers, then call the real routine. */ -.macro UNWIND_WRAPPER name +.macro UNWIND_WRAPPER name nargs ARM_FUNC_START \name /* Create a phase2_vrs structure. */ /* Split reg push in two to ensure the correct value for sp. */ @@ -89,8 +89,8 @@ ARM_FUNC_START gnu_Unwind_Save_VFP mov r3, #0 stmfd sp!, {r2, r3} - /* Point r1 at the block. Pass r0 unchanged. */ - add r1, sp, #4 + /* Point r1 at the block. Pass r[0..nargs) unchanged. */ + add r\nargs, sp, #4 #if defined(__thumb__) /* Switch back to thumb mode to avoid interworking hassle. */ adr ip, .L1_\name @@ -112,7 +112,9 @@ ARM_FUNC_START gnu_Unwind_Save_VFP UNPREFIX \name .endm -UNWIND_WRAPPER _Unwind_RaiseException -UNWIND_WRAPPER _Unwind_Resume +UNWIND_WRAPPER _Unwind_RaiseException 1 +UNWIND_WRAPPER _Unwind_Resume 1 +UNWIND_WRAPPER _Unwind_Resume_or_Rethrow 1 +UNWIND_WRAPPER _Unwind_ForcedUnwind 3 #endif /* __symbian__ */ diff --git a/gcc/config/arm/unwind-arm.c b/gcc/config/arm/unwind-arm.c index e436f7c..4d703db 100644 --- a/gcc/config/arm/unwind-arm.c +++ b/gcc/config/arm/unwind-arm.c @@ -51,8 +51,10 @@ __gnu_Unwind_Find_exidx (_Unwind_Ptr, int *); #define EXIDX_CANTUNWIND 1 #define uint32_highbit (((_uw) 1) << 31) +#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) struct core_regs { @@ -356,9 +358,9 @@ search_EIT_table (const __EIT_entry * table, int nrec, _uw return_address) n = (left + right) / 2; this_fn = selfrel_offset31 (&table[n].fnoffset); if (n != nrec - 1) - next_fn = selfrel_offset31 (&table[n + 1].fnoffset); + next_fn = selfrel_offset31 (&table[n + 1].fnoffset) - 1; else - next_fn = ~(_uw) 0; + next_fn = (_uw)0 - 1; if (return_address < this_fn) { @@ -366,7 +368,7 @@ search_EIT_table (const __EIT_entry * table, int nrec, _uw return_address) return (__EIT_entry *) 0; right = n - 1; } - else if (return_address < next_fn) + else if (return_address <= next_fn) return &table[n]; else left = n + 1; @@ -419,7 +421,7 @@ get_eit_entry (_Unwind_Control_Block *ucbp, _uw return_address) if (eitp->content == EXIDX_CANTUNWIND) { UCB_PR_ADDR (ucbp) = 0; - return _URC_FAILURE; + return _URC_END_OF_STACK; } /* Obtain the address of the "real" __EHT_Header word. */ @@ -472,21 +474,19 @@ unwind_phase2 (_Unwind_Control_Block * ucbp, phase2_vrs * vrs) { _Unwind_Reason_Code pr_result; - for(;;) + do { /* Find the entry for this routine. */ if (get_eit_entry (ucbp, vrs->core.r[R_PC]) != _URC_OK) abort (); UCB_SAVED_CALLSITE_ADDR (ucbp) = vrs->core.r[R_PC]; - + /* Call the pr to decide what to do. */ pr_result = ((personality_routine) UCB_PR_ADDR (ucbp)) (_US_UNWIND_FRAME_STARTING, ucbp, (_Unwind_Context *) vrs); - - if (pr_result != _URC_CONTINUE_UNWIND) - break; } + while (pr_result == _URC_CONTINUE_UNWIND); if (pr_result != _URC_INSTALL_CONTEXT) abort(); @@ -494,6 +494,57 @@ unwind_phase2 (_Unwind_Control_Block * ucbp, phase2_vrs * vrs) restore_core_regs (&vrs->core); } +/* Perform phase2 forced unwinding. */ + +static _Unwind_Reason_Code +unwind_phase2_forced (_Unwind_Control_Block *ucbp, phase2_vrs *entry_vrs) +{ + _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 until we reach a propagation barrier. */ + do + { + _Unwind_State action; + _Unwind_Reason_Code entry_code; + _Unwind_Reason_Code stop_code; + + /* Find the entry for this routine. */ + entry_code = get_eit_entry (ucbp, entry_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; + + stop_code = stop_fn (1, action, ucbp->exception_class, ucbp, + (void *)entry_vrs, stop_arg); + if (stop_code != _URC_NO_REASON) + return _URC_FAILURE; + + if (entry_code == _URC_END_OF_STACK) + 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); + } + while (pr_result == _URC_CONTINUE_UNWIND); + + if (pr_result != _URC_INSTALL_CONTEXT) + { + /* Some sort of failure has occurred in the pr and probably the + pr returned _URC_FAILURE. */ + return _URC_FAILURE; + } + + restore_core_regs (&entry_vrs->core); +} + /* Perform phase1 unwinding. UCBP is the exception being thrown, and entry_VRS is the register state on entry to _Unwind_RaiseException. */ @@ -516,7 +567,7 @@ __gnu_Unwind_RaiseException (_Unwind_Control_Block * ucbp, saved_vrs.demand_save_flags = ~(_uw) 0; /* Unwind until we reach a propagation barrier. */ - for (;;) + do { /* Find the entry for this routine. */ if (get_eit_entry (ucbp, saved_vrs.core.r[R_PC]) != _URC_OK) @@ -525,10 +576,8 @@ __gnu_Unwind_RaiseException (_Unwind_Control_Block * ucbp, /* Call the pr to decide what to do. */ pr_result = ((personality_routine) UCB_PR_ADDR (ucbp)) (_US_VIRTUAL_UNWIND_FRAME, ucbp, (void *) &saved_vrs); - - if (pr_result != _URC_CONTINUE_UNWIND) - break; } + while (pr_result == _URC_CONTINUE_UNWIND); /* We've unwound as far as we want to go, so restore the original register state. */ @@ -547,19 +596,42 @@ __gnu_Unwind_RaiseException (_Unwind_Control_Block * ucbp, being thrown and ENTRY_VRS is the register state on entry to _Unwind_Resume. */ _Unwind_Reason_Code +__gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *, + _Unwind_Stop_Fn, void *, phase2_vrs *); + +_Unwind_Reason_Code +__gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *ucbp, + _Unwind_Stop_Fn stop_fn, void *stop_arg, + phase2_vrs *entry_vrs) +{ + UCB_FORCED_STOP_FN (ucbp) = (_uw) stop_fn; + UCB_FORCED_STOP_ARG (ucbp) = (_uw) stop_arg; + + /* 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); +} + +_Unwind_Reason_Code __gnu_Unwind_Resume (_Unwind_Control_Block *, phase2_vrs *); _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; + pr_result = ((personality_routine) UCB_PR_ADDR (ucbp)) - (_US_UNWIND_FRAME_RESUME, ucbp, (_Unwind_Context *) entry_vrs); + (action, ucbp, (_Unwind_Context *) entry_vrs); switch (pr_result) { @@ -569,13 +641,32 @@ __gnu_Unwind_Resume (_Unwind_Control_Block * ucbp, phase2_vrs * entry_vrs) case _URC_CONTINUE_UNWIND: /* Continue unwinding the next frame. */ - unwind_phase2 (ucbp, entry_vrs); + if (UCB_FORCED_STOP_FN (ucbp)) + return unwind_phase2_forced (ucbp, entry_vrs); + else + unwind_phase2 (ucbp, entry_vrs); default: abort (); } } +_Unwind_Reason_Code +__gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block *, phase2_vrs *); + +_Unwind_Reason_Code +__gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block * ucbp, + phase2_vrs * entry_vrs) +{ + if (!UCB_FORCED_STOP_FN (ucbp)) + return __gnu_Unwind_RaiseException (ucbp, entry_vrs); + + /* 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); +} + /* Clean up an exception object when unwinding is complete. */ void _Unwind_Complete (_Unwind_Control_Block * ucbp __attribute__((unused))) @@ -619,6 +710,9 @@ __gnu_unwind_pr_common (_Unwind_State state, _uw rtti_count; int phase2_call_unexpected_after_unwind = 0; int in_range = 0; + int forced_unwind = state & _US_FORCE_UNWIND; + + state &= _US_ACTION_MASK; data = (_uw *) ucbp->pr_cache.ehtp; uws.data = *(data++); @@ -748,9 +842,9 @@ __gnu_unwind_pr_common (_Unwind_State state, /* Exception specification. */ if (state == _US_VIRTUAL_UNWIND_FRAME) { - if (in_range) + if (in_range && (!forced_unwind || !rtti_count)) { - /* Match against teh exception specification. */ + /* Match against the exception specification. */ _uw i; _uw rtti; void *matched; diff --git a/gcc/config/arm/unwind-arm.h b/gcc/config/arm/unwind-arm.h index 4d86407..f0c545f 100644 --- a/gcc/config/arm/unwind-arm.h +++ b/gcc/config/arm/unwind-arm.h @@ -1,5 +1,5 @@ /* Header file for the ARM EABI unwinder - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Paul Brook This file is free software; you can redistribute it and/or modify it @@ -54,28 +54,41 @@ extern "C" { { _URC_OK = 0, /* operation completed successfully */ _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_END_OF_STACK = 5, _URC_HANDLER_FOUND = 6, _URC_INSTALL_CONTEXT = 7, _URC_CONTINUE_UNWIND = 8, _URC_FAILURE = 9 /* unspecified failure of some kind */ } _Unwind_Reason_Code; - + typedef enum { _US_VIRTUAL_UNWIND_FRAME = 0, _US_UNWIND_FRAME_STARTING = 1, - _US_UNWIND_FRAME_RESUME = 2 + _US_UNWIND_FRAME_RESUME = 2, + _US_ACTION_MASK = 3, + _US_FORCE_UNWIND = 8, + _US_END_OF_STACK = 16 } _Unwind_State; - + + /* Provided only for for compatibility with existing code. */ + typedef int _Unwind_Action; +#define _UA_SEARCH_PHASE 1 +#define _UA_CLEANUP_PHASE 2 +#define _UA_HANDLER_FRAME 4 +#define _UA_FORCE_UNWIND 8 +#define _UA_END_OF_STACK 16 +#define _URC_NO_REASON _URC_OK + typedef struct _Unwind_Control_Block _Unwind_Control_Block; typedef struct _Unwind_Context _Unwind_Context; typedef _uw _Unwind_EHT_Header; - - + + /* UCB: */ - + struct _Unwind_Control_Block { char exception_class[8]; @@ -83,10 +96,10 @@ extern "C" { /* Unwinder cache, private fields for the unwinder's use */ struct { - _uw reserved1; /* init reserved1 to 0, then don't touch */ - _uw reserved2; - _uw reserved3; - _uw reserved4; + _uw reserved1; /* Forced unwind stop fn, 0 if not forced */ + _uw reserved2; /* Personality routine address */ + _uw reserved3; /* Saved callsite address */ + _uw reserved4; /* Forced unwind stop arg */ _uw reserved5; } unwinder_cache; @@ -114,14 +127,9 @@ extern "C" { pr_cache; long long int :0; /* Force alignment to 8-byte boundary */ }; - - /* Interface functions: */ - _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp); - void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp); - void _Unwind_Complete(_Unwind_Control_Block *ucbp); /* Virtual Register Set*/ - + typedef enum { _UVRSC_CORE = 0, /* integer register */ @@ -131,7 +139,7 @@ extern "C" { _UVRSC_WMMXC = 4 /* Intel WMMX control register */ } _Unwind_VRS_RegClass; - + typedef enum { _UVRSD_UINT32 = 0, @@ -142,13 +150,13 @@ extern "C" { _UVRSD_DOUBLE = 5 } _Unwind_VRS_DataRepresentation; - + typedef enum { _UVRSR_OK = 0, _UVRSR_NOT_IMPLEMENTED = 1, _UVRSR_FAILED = 2 - } + } _Unwind_VRS_Result; /* Frame unwinding state. */ @@ -171,11 +179,11 @@ extern "C" { _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *, _Unwind_VRS_RegClass, _uw, _Unwind_VRS_DataRepresentation, void *); - + _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *, _Unwind_VRS_RegClass, _uw, _Unwind_VRS_DataRepresentation, void *); - + _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *, _Unwind_VRS_RegClass, _uw, _Unwind_VRS_DataRepresentation); @@ -200,6 +208,17 @@ extern "C" { abort (); } + /* Interface functions: */ + _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp); + void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp); + _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp); + + typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) + (int, _Unwind_Action, _Unwind_Exception_Class, + _Unwind_Control_Block *, struct _Unwind_Context *, void *); + _Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *, + _Unwind_Stop_Fn, void *); + void _Unwind_Complete(_Unwind_Control_Block *ucbp); void _Unwind_DeleteException (_Unwind_Exception *); _Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *, @@ -254,16 +273,6 @@ extern "C" { #define _Unwind_SetIP(context, val) \ _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1)) - /* Provided only for for compatibility with existing code. */ - typedef int _Unwind_Action; -#define _UA_SEARCH_PHASE 1 -#define _UA_CLEANUP_PHASE 2 -#define _UA_HANDLER_FRAME 4 -#define _UA_FORCE_UNWIND 8 -#define _UA_END_OF_STACK 16 - -#define _URC_NO_REASON _URC_OK - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8b43fc8..63f6361 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2005-11-16 Nathan Sidwell <nathan@codesourcery.com> + + * g++.dg/eh/forced1.C: Adjust to cope with ARM EABI + structures. + * g++.dg/eh/forced2.C: Likewise. + * g++.dg/eh/forced3.C: Likewise. + * g++.dg/eh/forced4.C: Likewise. + 2005-11-11 Mike Stump <mrs@apple.com> * g++.old-deja/g++.mike/unused.C: Add. diff --git a/gcc/testsuite/g++.dg/eh/forced1.C b/gcc/testsuite/g++.dg/eh/forced1.C index 0068dae..b020081 100644 --- a/gcc/testsuite/g++.dg/eh/forced1.C +++ b/gcc/testsuite/g++.dg/eh/forced1.C @@ -6,6 +6,7 @@ #include <unwind.h> #include <stdlib.h> +#include <string.h> static int test = 0; @@ -35,7 +36,8 @@ force_unwind_cleanup (_Unwind_Reason_Code, struct _Unwind_Exception *) static void force_unwind () { _Unwind_Exception *exc = new _Unwind_Exception; - exc->exception_class = 0; + // exception_class might not be a scalar. + memset (&exc->exception_class, 0, sizeof (exc->exception_class)); exc->exception_cleanup = force_unwind_cleanup; #ifndef __USING_SJLJ_EXCEPTIONS__ @@ -54,7 +56,7 @@ struct S ~S() { test |= bit; } }; -static void doit () +static __attribute__ ((noinline)) void doit () { try { S four(4); @@ -62,7 +64,6 @@ static void doit () try { S one(1); force_unwind (); - } catch(...) { test |= 2; throw; diff --git a/gcc/testsuite/g++.dg/eh/forced2.C b/gcc/testsuite/g++.dg/eh/forced2.C index 3c6719d..54586a0 100644 --- a/gcc/testsuite/g++.dg/eh/forced2.C +++ b/gcc/testsuite/g++.dg/eh/forced2.C @@ -6,6 +6,7 @@ #include <unwind.h> #include <stdlib.h> +#include <string.h> static _Unwind_Reason_Code force_unwind_stop (int version, _Unwind_Action actions, @@ -29,7 +30,8 @@ static void force_unwind () { _Unwind_Exception *exc = new _Unwind_Exception; - exc->exception_class = 0; + // exception_class might not be a scalar. + memset (&exc->exception_class, 0, sizeof (exc->exception_class)); exc->exception_cleanup = force_unwind_cleanup; #ifndef __USING_SJLJ_EXCEPTIONS__ diff --git a/gcc/testsuite/g++.dg/eh/forced3.C b/gcc/testsuite/g++.dg/eh/forced3.C index 34d2764..96319d4 100644 --- a/gcc/testsuite/g++.dg/eh/forced3.C +++ b/gcc/testsuite/g++.dg/eh/forced3.C @@ -7,6 +7,7 @@ #include <unwind.h> #include <stdlib.h> #include <exception> +#include <string.h> static _Unwind_Reason_Code force_unwind_stop (int version, _Unwind_Action actions, @@ -24,7 +25,8 @@ static void __attribute__((noreturn)) force_unwind () { _Unwind_Exception *exc = new _Unwind_Exception; - exc->exception_class = 0; + // exception_class might not be a scalar. + memset (&exc->exception_class, 0, sizeof (exc->exception_class)); exc->exception_cleanup = 0; #ifndef __USING_SJLJ_EXCEPTIONS__ diff --git a/gcc/testsuite/g++.dg/eh/forced4.C b/gcc/testsuite/g++.dg/eh/forced4.C index df691ca..17fd94a 100644 --- a/gcc/testsuite/g++.dg/eh/forced4.C +++ b/gcc/testsuite/g++.dg/eh/forced4.C @@ -6,6 +6,7 @@ #include <unwind.h> #include <stdlib.h> +#include <string.h> static _Unwind_Reason_Code force_unwind_stop (int version, _Unwind_Action actions, @@ -23,7 +24,8 @@ static void __attribute__((noreturn)) force_unwind () { _Unwind_Exception *exc = new _Unwind_Exception; - exc->exception_class = 0; + // exception_class might not be a scalar. + memset (&exc->exception_class, 0, sizeof (exc->exception_class)); exc->exception_cleanup = 0; #ifndef __USING_SJLJ_EXCEPTIONS__ diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 0fa5039..f84cefd 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,13 @@ +2005-11-16 Nathan Sidwell <nathan@codesourcery.com> + + * libsupc++/eh_arm.cc (__cxa_begin_cleanup): Remember a + foreign exception too. + (__gnu_end_cleanup): Recover a foreign exception too. + * libsupc++/eh_personality.cc (PERSONALITY_FUNCTION): Cope + with forced unwinding. + * libsupc++/eh_throw.cc (__cxxabiv1::__cxa_rethrow): Use + _Unwind_Resume_or_Rethrow for ARM EABI. + 2005-11-14 Geoffrey Keating <geoffk@apple.com> * acinclude.m4 (GLIBCXX_CHECK_LINKER_FEATURES): Don't check for diff --git a/libstdc++-v3/libsupc++/eh_arm.cc b/libstdc++-v3/libsupc++/eh_arm.cc index d87d82a..269b2ec 100644 --- a/libstdc++-v3/libsupc++/eh_arm.cc +++ b/libstdc++-v3/libsupc++/eh_arm.cc @@ -89,20 +89,31 @@ __cxa_begin_cleanup(_Unwind_Exception* ue_header) { __cxa_eh_globals *globals = __cxa_get_globals(); __cxa_exception *header = __get_exception_header_from_ue(ue_header); + bool native = __is_gxx_exception_class(header->unwindHeader.exception_class); - if (!__is_gxx_exception_class(header->unwindHeader.exception_class)) + + if (native) { - // TODO: cleanups with foreign exceptions. - return false; + header->propagationCount++; + // Add it to the chain if this is the first time we've seen this + // exception. + if (header->propagationCount == 1) + { + header->nextPropagatingException = globals->propagatingExceptions; + globals->propagatingExceptions = header; + } } - header->propagationCount++; - // Add it to the chain if this is the first time we've seen this exception. - if (header->propagationCount == 1) + else { - header->nextPropagatingException = globals->propagatingExceptions; + // Remember the exception object, so end_cleanup can return it. + // These cannot be stacked, so we must abort if we already have + // a propagating exception. + if (globals->propagatingExceptions) + std::terminate (); globals->propagatingExceptions = header; } - return true; + + return !native; } // Do the work for __cxa_end_cleanup. Returns the currently propagating @@ -119,13 +130,19 @@ __gnu_end_cleanup(void) if (!header) std::terminate(); - header->propagationCount--; - if (header->propagationCount == 0) + if (__is_gxx_exception_class(header->unwindHeader.exception_class)) { - // Remove exception from chain. - globals->propagatingExceptions = header->nextPropagatingException; - header->nextPropagatingException = NULL; + header->propagationCount--; + if (header->propagationCount == 0) + { + // Remove exception from chain. + globals->propagatingExceptions = header->nextPropagatingException; + header->nextPropagatingException = NULL; + } } + else + globals->propagatingExceptions = NULL; + return &header->unwindHeader; } diff --git a/libstdc++-v3/libsupc++/eh_personality.cc b/libstdc++-v3/libsupc++/eh_personality.cc index 6205851..f07864f 100644 --- a/libstdc++-v3/libsupc++/eh_personality.cc +++ b/libstdc++-v3/libsupc++/eh_personality.cc @@ -369,7 +369,7 @@ PERSONALITY_FUNCTION (int version, #ifdef __ARM_EABI_UNWINDER__ _Unwind_Action actions; - switch (state) + switch (state & _US_ACTION_MASK) { case _US_VIRTUAL_UNWIND_FRAME: actions = _UA_SEARCH_PHASE; @@ -377,7 +377,8 @@ PERSONALITY_FUNCTION (int version, case _US_UNWIND_FRAME_STARTING: actions = _UA_CLEANUP_PHASE; - if (ue_header->barrier_cache.sp == _Unwind_GetGR(context, 13)) + if (!(state & _US_FORCE_UNWIND) + && ue_header->barrier_cache.sp == _Unwind_GetGR(context, 13)) actions |= _UA_HANDLER_FRAME; break; @@ -388,6 +389,7 @@ PERSONALITY_FUNCTION (int version, default: abort(); } + actions |= state & _US_FORCE_UNWIND; // We don't know which runtime we're working with, so can't check this. // However the ABI routines hide this from us, and we don't actually need @@ -523,13 +525,13 @@ PERSONALITY_FUNCTION (int version, // exception class, there's no exception type. // ??? What to do about GNU Java and GNU Ada exceptions. -#ifdef __ARM_EABI_UNWINDER__ - throw_type = ue_header; -#else if ((actions & _UA_FORCE_UNWIND) || foreign_exception) throw_type = 0; else +#ifdef __ARM_EABI_UNWINDER__ + throw_type = ue_header; +#else throw_type = xh->exceptionType; #endif @@ -613,7 +615,6 @@ PERSONALITY_FUNCTION (int version, install_context: -#ifndef __ARM_EABI_UNWINDER__ // We can't use any of the cxa routines with foreign exceptions, // because they all expect ue_header to be a struct __cxa_exception. // So in that case, call terminate or unexpected directly. @@ -631,7 +632,6 @@ PERSONALITY_FUNCTION (int version, } } else -#endif { if (found_type == found_terminate) __cxa_call_terminate(ue_header); diff --git a/libstdc++-v3/libsupc++/eh_throw.cc b/libstdc++-v3/libsupc++/eh_throw.cc index 8b04f39..9f26be0 100644 --- a/libstdc++-v3/libsupc++/eh_throw.cc +++ b/libstdc++-v3/libsupc++/eh_throw.cc @@ -97,7 +97,7 @@ __cxxabiv1::__cxa_rethrow () #ifdef _GLIBCXX_SJLJ_EXCEPTIONS _Unwind_SjLj_Resume_or_Rethrow (&header->unwindHeader); #else -#if defined(_LIBUNWIND_STD_ABI) || defined (__ARM_EABI_UNWINDER__) +#if defined(_LIBUNWIND_STD_ABI) _Unwind_RaiseException (&header->unwindHeader); #else _Unwind_Resume_or_Rethrow (&header->unwindHeader); |