X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=gcc%2Funwind.inc;fp=gcc%2Funwind.inc;h=5e2ec29c79a00884e2f448feabd364c189a79f5b;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=f00441ea02430c280ac9439c39883990e7b17d01;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/gcc/unwind.inc b/gcc/unwind.inc index f00441ea..5e2ec29c 100644 --- a/gcc/unwind.inc +++ b/gcc/unwind.inc @@ -1,11 +1,11 @@ /* Exception handling and frame unwind runtime interface routines. -*- C -*- - Copyright (C) 2001 Free Software Foundation, Inc. + Copyright (C) 2001, 2003, 2008, 2009 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT @@ -13,14 +13,19 @@ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ /* This is derived from the C++ ABI for IA-64. Where we diverge for cross-architecture compatibility are noted with "@@@". - This file is included from unwind-dw2.c or unwind-ia64.c. */ + This file is included from unwind-dw2.c, unwind-sjlj.c or + unwind-ia64.c. */ /* Subroutine of _Unwind_RaiseException also invoked from _Unwind_Resume. @@ -63,8 +68,7 @@ _Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc, } /* Don't let us unwind past the handler context. */ - if (match_handler) - abort (); + gcc_assert (!match_handler); uw_update_context (context, &fs); } @@ -72,15 +76,15 @@ _Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc, return code; } - /* Raise an exception, passing along the given exception object. */ -_Unwind_Reason_Code +_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE _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 +94,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) @@ -97,7 +103,7 @@ _Unwind_RaiseException(struct _Unwind_Exception *exc) return _URC_END_OF_STACK; if (code != _URC_NO_REASON) - /* Some error encountered. Ususally the unwinder doesn't + /* Some error encountered. Usually the unwinder doesn't diagnose these and merely crashes. */ return _URC_FATAL_PHASE1_ERROR; @@ -112,6 +118,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); } @@ -132,8 +139,8 @@ _Unwind_RaiseException(struct _Unwind_Exception *exc) /* Subroutine of _Unwind_ForcedUnwind also invoked from _Unwind_Resume. */ static _Unwind_Reason_Code -_Unwind_ForcedUnwind_Phase2(struct _Unwind_Exception *exc, - struct _Unwind_Context *context) +_Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc, + struct _Unwind_Context *context) { _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) (_Unwind_Ptr) exc->private_1; void *stop_argument = (void *) (_Unwind_Ptr) exc->private_2; @@ -144,6 +151,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,7 +180,9 @@ _Unwind_ForcedUnwind_Phase2(struct _Unwind_Exception *exc, return _URC_FATAL_PHASE2_ERROR; } - uw_update_context (context, &fs); + /* Update cur_context to describe the same frame as fs, and discard + the previous context if necessary. */ + uw_advance_context (context, &fs); } return code; @@ -181,7 +191,7 @@ _Unwind_ForcedUnwind_Phase2(struct _Unwind_Exception *exc, /* Raise an exception for forced unwinding. */ -_Unwind_Reason_Code +_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE _Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop, void * stop_argument) { @@ -205,7 +215,7 @@ _Unwind_ForcedUnwind (struct _Unwind_Exception *exc, /* Resume propagation of an existing exception. This is used after e.g. executing cleanup code, and not to implement rethrowing. */ -void +void LIBGCC2_UNWIND_ATTRIBUTE _Unwind_Resume (struct _Unwind_Exception *exc) { struct _Unwind_Context this_context, cur_context; @@ -221,16 +231,77 @@ _Unwind_Resume (struct _Unwind_Exception *exc) else code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context); - if (code != _URC_INSTALL_CONTEXT) - abort (); + gcc_assert (code == _URC_INSTALL_CONTEXT); + + 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 LIBGCC2_UNWIND_ATTRIBUTE +_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); + + gcc_assert (code == _URC_INSTALL_CONTEXT); 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 LIBGCC2_UNWIND_ATTRIBUTE +_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; }