diff options
Diffstat (limited to 'contrib/gcc/unwind.inc')
-rw-r--r-- | contrib/gcc/unwind.inc | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/contrib/gcc/unwind.inc b/contrib/gcc/unwind.inc index f00441e..0938d50 100644 --- a/contrib/gcc/unwind.inc +++ b/contrib/gcc/unwind.inc @@ -72,7 +72,6 @@ _Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc, return code; } - /* Raise an exception, passing along the given exception object. */ _Unwind_Reason_Code @@ -81,6 +80,7 @@ _Unwind_RaiseException(struct _Unwind_Exception *exc) struct _Unwind_Context this_context, cur_context; _Unwind_Reason_Code code; + /* Set up this_context to describe the current stack frame. */ uw_init_context (&this_context); cur_context = this_context; @@ -90,6 +90,8 @@ _Unwind_RaiseException(struct _Unwind_Exception *exc) { _Unwind_FrameState fs; + /* Set up fs to describe the FDE for the caller of cur_context. The + first time through the loop, that means __cxa_throw. */ code = uw_frame_state_for (&cur_context, &fs); if (code == _URC_END_OF_STACK) @@ -112,6 +114,7 @@ _Unwind_RaiseException(struct _Unwind_Exception *exc) return _URC_FATAL_PHASE1_ERROR; } + /* Update cur_context to describe the same frame as fs. */ uw_update_context (&cur_context, &fs); } @@ -144,6 +147,7 @@ _Unwind_ForcedUnwind_Phase2(struct _Unwind_Exception *exc, _Unwind_FrameState fs; int action; + /* Set up fs to describe the FDE for the caller of cur_context. */ code = uw_frame_state_for (context, &fs); if (code != _URC_NO_REASON && code != _URC_END_OF_STACK) return _URC_FATAL_PHASE2_ERROR; @@ -172,6 +176,7 @@ _Unwind_ForcedUnwind_Phase2(struct _Unwind_Exception *exc, return _URC_FATAL_PHASE2_ERROR; } + /* Update cur_context to describe the same frame as fs. */ uw_update_context (context, &fs); } @@ -227,10 +232,73 @@ _Unwind_Resume (struct _Unwind_Exception *exc) uw_install_context (&this_context, &cur_context); } + +/* Resume propagation of an FORCE_UNWIND exception, or to rethrow + a normal exception that was handled. */ + +_Unwind_Reason_Code +_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc) +{ + struct _Unwind_Context this_context, cur_context; + _Unwind_Reason_Code code; + + /* Choose between continuing to process _Unwind_RaiseException + or _Unwind_ForcedUnwind. */ + if (exc->private_1 == 0) + return _Unwind_RaiseException (exc); + + uw_init_context (&this_context); + cur_context = this_context; + + code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context); + + if (code != _URC_INSTALL_CONTEXT) + abort (); + + uw_install_context (&this_context, &cur_context); +} + + /* A convenience function that calls the exception_cleanup field. */ void _Unwind_DeleteException (struct _Unwind_Exception *exc) { - (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc); + if (exc->exception_cleanup) + (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc); +} + + +/* Perform stack backtrace through unwind data. */ + +_Unwind_Reason_Code +_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument) +{ + struct _Unwind_Context context; + _Unwind_Reason_Code code; + + uw_init_context (&context); + + while (1) + { + _Unwind_FrameState fs; + + /* Set up fs to describe the FDE for the caller of context. */ + code = uw_frame_state_for (&context, &fs); + if (code != _URC_NO_REASON && code != _URC_END_OF_STACK) + return _URC_FATAL_PHASE1_ERROR; + + /* Call trace function. */ + if ((*trace) (&context, trace_argument) != _URC_NO_REASON) + return _URC_FATAL_PHASE1_ERROR; + + /* We're done at end of stack. */ + if (code == _URC_END_OF_STACK) + break; + + /* Update context to describe the same frame as fs. */ + uw_update_context (&context, &fs); + } + + return code; } |