aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/arm
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2005-11-16 17:04:41 +0000
committerDaniel Jacobowitz <drow@gcc.gnu.org>2005-11-16 17:04:41 +0000
commit1dcca6f3616f620f7ac81e9f4b814b06b246b093 (patch)
tree334b3d2a842b79dc3b040fb2439effee2404892f /gcc/config/arm
parent8656214b84c3e789deffe8f7b465bd1c886b2a03 (diff)
downloadgcc-1dcca6f3616f620f7ac81e9f4b814b06b246b093.zip
gcc-1dcca6f3616f620f7ac81e9f4b814b06b246b093.tar.gz
gcc-1dcca6f3616f620f7ac81e9f4b814b06b246b093.tar.bz2
unwind-arm.h: Reorder interface function declarations.
2005-11-16 Nathan Sidwell <nathan@codesourcery.com> gcc/ * 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. * 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. gcc/testsuite/ * 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. libstdc++-v3/ * 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. From-SVN: r107089
Diffstat (limited to 'gcc/config/arm')
-rw-r--r--gcc/config/arm/libunwind.S12
-rw-r--r--gcc/config/arm/unwind-arm.c130
-rw-r--r--gcc/config/arm/unwind-arm.h73
3 files changed, 160 insertions, 55 deletions
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