1*c87b03e5Sespie/* Exception handling and frame unwind runtime interface routines. -*- C -*- 2*c87b03e5Sespie Copyright (C) 2001 Free Software Foundation, Inc. 3*c87b03e5Sespie 4*c87b03e5Sespie This file is part of GCC. 5*c87b03e5Sespie 6*c87b03e5Sespie GCC is free software; you can redistribute it and/or modify it 7*c87b03e5Sespie under the terms of the GNU General Public License as published by 8*c87b03e5Sespie the Free Software Foundation; either version 2, or (at your option) 9*c87b03e5Sespie any later version. 10*c87b03e5Sespie 11*c87b03e5Sespie GCC is distributed in the hope that it will be useful, but WITHOUT 12*c87b03e5Sespie ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13*c87b03e5Sespie or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14*c87b03e5Sespie License for more details. 15*c87b03e5Sespie 16*c87b03e5Sespie You should have received a copy of the GNU General Public License 17*c87b03e5Sespie along with GCC; see the file COPYING. If not, write to the Free 18*c87b03e5Sespie Software Foundation, 59 Temple Place - Suite 330, Boston, MA 19*c87b03e5Sespie 02111-1307, USA. */ 20*c87b03e5Sespie 21*c87b03e5Sespie/* This is derived from the C++ ABI for IA-64. Where we diverge 22*c87b03e5Sespie for cross-architecture compatibility are noted with "@@@". 23*c87b03e5Sespie This file is included from unwind-dw2.c or unwind-ia64.c. */ 24*c87b03e5Sespie 25*c87b03e5Sespie/* Subroutine of _Unwind_RaiseException also invoked from _Unwind_Resume. 26*c87b03e5Sespie 27*c87b03e5Sespie Unwind the stack calling the personality routine to find both the 28*c87b03e5Sespie exception handler and intermediary cleanup code. We'll only locate 29*c87b03e5Sespie the first such frame here. Cleanup code will call back into 30*c87b03e5Sespie _Unwind_Resume and we'll continue Phase 2 there. */ 31*c87b03e5Sespie 32*c87b03e5Sespiestatic _Unwind_Reason_Code 33*c87b03e5Sespie_Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc, 34*c87b03e5Sespie struct _Unwind_Context *context) 35*c87b03e5Sespie{ 36*c87b03e5Sespie _Unwind_Reason_Code code; 37*c87b03e5Sespie 38*c87b03e5Sespie while (1) 39*c87b03e5Sespie { 40*c87b03e5Sespie _Unwind_FrameState fs; 41*c87b03e5Sespie int match_handler; 42*c87b03e5Sespie 43*c87b03e5Sespie code = uw_frame_state_for (context, &fs); 44*c87b03e5Sespie 45*c87b03e5Sespie /* Identify when we've reached the designated handler context. */ 46*c87b03e5Sespie match_handler = (uw_identify_context (context) == exc->private_2 47*c87b03e5Sespie ? _UA_HANDLER_FRAME : 0); 48*c87b03e5Sespie 49*c87b03e5Sespie if (code != _URC_NO_REASON) 50*c87b03e5Sespie /* Some error encountered. Usually the unwinder doesn't 51*c87b03e5Sespie diagnose these and merely crashes. */ 52*c87b03e5Sespie return _URC_FATAL_PHASE2_ERROR; 53*c87b03e5Sespie 54*c87b03e5Sespie /* Unwind successful. Run the personality routine, if any. */ 55*c87b03e5Sespie if (fs.personality) 56*c87b03e5Sespie { 57*c87b03e5Sespie code = (*fs.personality) (1, _UA_CLEANUP_PHASE | match_handler, 58*c87b03e5Sespie exc->exception_class, exc, context); 59*c87b03e5Sespie if (code == _URC_INSTALL_CONTEXT) 60*c87b03e5Sespie break; 61*c87b03e5Sespie if (code != _URC_CONTINUE_UNWIND) 62*c87b03e5Sespie return _URC_FATAL_PHASE2_ERROR; 63*c87b03e5Sespie } 64*c87b03e5Sespie 65*c87b03e5Sespie /* Don't let us unwind past the handler context. */ 66*c87b03e5Sespie if (match_handler) 67*c87b03e5Sespie abort (); 68*c87b03e5Sespie 69*c87b03e5Sespie uw_update_context (context, &fs); 70*c87b03e5Sespie } 71*c87b03e5Sespie 72*c87b03e5Sespie return code; 73*c87b03e5Sespie} 74*c87b03e5Sespie 75*c87b03e5Sespie/* Raise an exception, passing along the given exception object. */ 76*c87b03e5Sespie 77*c87b03e5Sespie_Unwind_Reason_Code 78*c87b03e5Sespie_Unwind_RaiseException(struct _Unwind_Exception *exc) 79*c87b03e5Sespie{ 80*c87b03e5Sespie struct _Unwind_Context this_context, cur_context; 81*c87b03e5Sespie _Unwind_Reason_Code code; 82*c87b03e5Sespie 83*c87b03e5Sespie /* Set up this_context to describe the current stack frame. */ 84*c87b03e5Sespie uw_init_context (&this_context); 85*c87b03e5Sespie cur_context = this_context; 86*c87b03e5Sespie 87*c87b03e5Sespie /* Phase 1: Search. Unwind the stack, calling the personality routine 88*c87b03e5Sespie with the _UA_SEARCH_PHASE flag set. Do not modify the stack yet. */ 89*c87b03e5Sespie while (1) 90*c87b03e5Sespie { 91*c87b03e5Sespie _Unwind_FrameState fs; 92*c87b03e5Sespie 93*c87b03e5Sespie /* Set up fs to describe the FDE for the caller of cur_context. The 94*c87b03e5Sespie first time through the loop, that means __cxa_throw. */ 95*c87b03e5Sespie code = uw_frame_state_for (&cur_context, &fs); 96*c87b03e5Sespie 97*c87b03e5Sespie if (code == _URC_END_OF_STACK) 98*c87b03e5Sespie /* Hit end of stack with no handler found. */ 99*c87b03e5Sespie return _URC_END_OF_STACK; 100*c87b03e5Sespie 101*c87b03e5Sespie if (code != _URC_NO_REASON) 102*c87b03e5Sespie /* Some error encountered. Ususally the unwinder doesn't 103*c87b03e5Sespie diagnose these and merely crashes. */ 104*c87b03e5Sespie return _URC_FATAL_PHASE1_ERROR; 105*c87b03e5Sespie 106*c87b03e5Sespie /* Unwind successful. Run the personality routine, if any. */ 107*c87b03e5Sespie if (fs.personality) 108*c87b03e5Sespie { 109*c87b03e5Sespie code = (*fs.personality) (1, _UA_SEARCH_PHASE, exc->exception_class, 110*c87b03e5Sespie exc, &cur_context); 111*c87b03e5Sespie if (code == _URC_HANDLER_FOUND) 112*c87b03e5Sespie break; 113*c87b03e5Sespie else if (code != _URC_CONTINUE_UNWIND) 114*c87b03e5Sespie return _URC_FATAL_PHASE1_ERROR; 115*c87b03e5Sespie } 116*c87b03e5Sespie 117*c87b03e5Sespie /* Update cur_context to describe the same frame as fs. */ 118*c87b03e5Sespie uw_update_context (&cur_context, &fs); 119*c87b03e5Sespie } 120*c87b03e5Sespie 121*c87b03e5Sespie /* Indicate to _Unwind_Resume and associated subroutines that this 122*c87b03e5Sespie is not a forced unwind. Further, note where we found a handler. */ 123*c87b03e5Sespie exc->private_1 = 0; 124*c87b03e5Sespie exc->private_2 = uw_identify_context (&cur_context); 125*c87b03e5Sespie 126*c87b03e5Sespie cur_context = this_context; 127*c87b03e5Sespie code = _Unwind_RaiseException_Phase2 (exc, &cur_context); 128*c87b03e5Sespie if (code != _URC_INSTALL_CONTEXT) 129*c87b03e5Sespie return code; 130*c87b03e5Sespie 131*c87b03e5Sespie uw_install_context (&this_context, &cur_context); 132*c87b03e5Sespie} 133*c87b03e5Sespie 134*c87b03e5Sespie 135*c87b03e5Sespie/* Subroutine of _Unwind_ForcedUnwind also invoked from _Unwind_Resume. */ 136*c87b03e5Sespie 137*c87b03e5Sespiestatic _Unwind_Reason_Code 138*c87b03e5Sespie_Unwind_ForcedUnwind_Phase2(struct _Unwind_Exception *exc, 139*c87b03e5Sespie struct _Unwind_Context *context) 140*c87b03e5Sespie{ 141*c87b03e5Sespie _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) (_Unwind_Ptr) exc->private_1; 142*c87b03e5Sespie void *stop_argument = (void *) (_Unwind_Ptr) exc->private_2; 143*c87b03e5Sespie _Unwind_Reason_Code code, stop_code; 144*c87b03e5Sespie 145*c87b03e5Sespie while (1) 146*c87b03e5Sespie { 147*c87b03e5Sespie _Unwind_FrameState fs; 148*c87b03e5Sespie int action; 149*c87b03e5Sespie 150*c87b03e5Sespie /* Set up fs to describe the FDE for the caller of cur_context. */ 151*c87b03e5Sespie code = uw_frame_state_for (context, &fs); 152*c87b03e5Sespie if (code != _URC_NO_REASON && code != _URC_END_OF_STACK) 153*c87b03e5Sespie return _URC_FATAL_PHASE2_ERROR; 154*c87b03e5Sespie 155*c87b03e5Sespie /* Unwind successful. */ 156*c87b03e5Sespie action = _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE; 157*c87b03e5Sespie if (code == _URC_END_OF_STACK) 158*c87b03e5Sespie action |= _UA_END_OF_STACK; 159*c87b03e5Sespie stop_code = (*stop) (1, action, exc->exception_class, exc, 160*c87b03e5Sespie context, stop_argument); 161*c87b03e5Sespie if (stop_code != _URC_NO_REASON) 162*c87b03e5Sespie return _URC_FATAL_PHASE2_ERROR; 163*c87b03e5Sespie 164*c87b03e5Sespie /* Stop didn't want to do anything. Invoke the personality 165*c87b03e5Sespie handler, if applicable, to run cleanups. */ 166*c87b03e5Sespie if (code == _URC_END_OF_STACK) 167*c87b03e5Sespie break; 168*c87b03e5Sespie 169*c87b03e5Sespie if (fs.personality) 170*c87b03e5Sespie { 171*c87b03e5Sespie code = (*fs.personality) (1, _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE, 172*c87b03e5Sespie exc->exception_class, exc, context); 173*c87b03e5Sespie if (code == _URC_INSTALL_CONTEXT) 174*c87b03e5Sespie break; 175*c87b03e5Sespie if (code != _URC_CONTINUE_UNWIND) 176*c87b03e5Sespie return _URC_FATAL_PHASE2_ERROR; 177*c87b03e5Sespie } 178*c87b03e5Sespie 179*c87b03e5Sespie /* Update cur_context to describe the same frame as fs. */ 180*c87b03e5Sespie uw_update_context (context, &fs); 181*c87b03e5Sespie } 182*c87b03e5Sespie 183*c87b03e5Sespie return code; 184*c87b03e5Sespie} 185*c87b03e5Sespie 186*c87b03e5Sespie 187*c87b03e5Sespie/* Raise an exception for forced unwinding. */ 188*c87b03e5Sespie 189*c87b03e5Sespie_Unwind_Reason_Code 190*c87b03e5Sespie_Unwind_ForcedUnwind (struct _Unwind_Exception *exc, 191*c87b03e5Sespie _Unwind_Stop_Fn stop, void * stop_argument) 192*c87b03e5Sespie{ 193*c87b03e5Sespie struct _Unwind_Context this_context, cur_context; 194*c87b03e5Sespie _Unwind_Reason_Code code; 195*c87b03e5Sespie 196*c87b03e5Sespie uw_init_context (&this_context); 197*c87b03e5Sespie cur_context = this_context; 198*c87b03e5Sespie 199*c87b03e5Sespie exc->private_1 = (_Unwind_Ptr) stop; 200*c87b03e5Sespie exc->private_2 = (_Unwind_Ptr) stop_argument; 201*c87b03e5Sespie 202*c87b03e5Sespie code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context); 203*c87b03e5Sespie if (code != _URC_INSTALL_CONTEXT) 204*c87b03e5Sespie return code; 205*c87b03e5Sespie 206*c87b03e5Sespie uw_install_context (&this_context, &cur_context); 207*c87b03e5Sespie} 208*c87b03e5Sespie 209*c87b03e5Sespie 210*c87b03e5Sespie/* Resume propagation of an existing exception. This is used after 211*c87b03e5Sespie e.g. executing cleanup code, and not to implement rethrowing. */ 212*c87b03e5Sespie 213*c87b03e5Sespievoid 214*c87b03e5Sespie_Unwind_Resume (struct _Unwind_Exception *exc) 215*c87b03e5Sespie{ 216*c87b03e5Sespie struct _Unwind_Context this_context, cur_context; 217*c87b03e5Sespie _Unwind_Reason_Code code; 218*c87b03e5Sespie 219*c87b03e5Sespie uw_init_context (&this_context); 220*c87b03e5Sespie cur_context = this_context; 221*c87b03e5Sespie 222*c87b03e5Sespie /* Choose between continuing to process _Unwind_RaiseException 223*c87b03e5Sespie or _Unwind_ForcedUnwind. */ 224*c87b03e5Sespie if (exc->private_1 == 0) 225*c87b03e5Sespie code = _Unwind_RaiseException_Phase2 (exc, &cur_context); 226*c87b03e5Sespie else 227*c87b03e5Sespie code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context); 228*c87b03e5Sespie 229*c87b03e5Sespie if (code != _URC_INSTALL_CONTEXT) 230*c87b03e5Sespie abort (); 231*c87b03e5Sespie 232*c87b03e5Sespie uw_install_context (&this_context, &cur_context); 233*c87b03e5Sespie} 234*c87b03e5Sespie 235*c87b03e5Sespie 236*c87b03e5Sespie/* Resume propagation of an FORCE_UNWIND exception, or to rethrow 237*c87b03e5Sespie a normal exception that was handled. */ 238*c87b03e5Sespie 239*c87b03e5Sespie_Unwind_Reason_Code 240*c87b03e5Sespie_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc) 241*c87b03e5Sespie{ 242*c87b03e5Sespie struct _Unwind_Context this_context, cur_context; 243*c87b03e5Sespie _Unwind_Reason_Code code; 244*c87b03e5Sespie 245*c87b03e5Sespie /* Choose between continuing to process _Unwind_RaiseException 246*c87b03e5Sespie or _Unwind_ForcedUnwind. */ 247*c87b03e5Sespie if (exc->private_1 == 0) 248*c87b03e5Sespie return _Unwind_RaiseException (exc); 249*c87b03e5Sespie 250*c87b03e5Sespie uw_init_context (&this_context); 251*c87b03e5Sespie cur_context = this_context; 252*c87b03e5Sespie 253*c87b03e5Sespie code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context); 254*c87b03e5Sespie 255*c87b03e5Sespie if (code != _URC_INSTALL_CONTEXT) 256*c87b03e5Sespie abort (); 257*c87b03e5Sespie 258*c87b03e5Sespie uw_install_context (&this_context, &cur_context); 259*c87b03e5Sespie} 260*c87b03e5Sespie 261*c87b03e5Sespie 262*c87b03e5Sespie/* A convenience function that calls the exception_cleanup field. */ 263*c87b03e5Sespie 264*c87b03e5Sespievoid 265*c87b03e5Sespie_Unwind_DeleteException (struct _Unwind_Exception *exc) 266*c87b03e5Sespie{ 267*c87b03e5Sespie if (exc->exception_cleanup) 268*c87b03e5Sespie (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc); 269*c87b03e5Sespie} 270*c87b03e5Sespie 271*c87b03e5Sespie 272*c87b03e5Sespie/* Perform stack backtrace through unwind data. */ 273*c87b03e5Sespie 274*c87b03e5Sespie_Unwind_Reason_Code 275*c87b03e5Sespie_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument) 276*c87b03e5Sespie{ 277*c87b03e5Sespie struct _Unwind_Context context; 278*c87b03e5Sespie _Unwind_Reason_Code code; 279*c87b03e5Sespie 280*c87b03e5Sespie uw_init_context (&context); 281*c87b03e5Sespie 282*c87b03e5Sespie while (1) 283*c87b03e5Sespie { 284*c87b03e5Sespie _Unwind_FrameState fs; 285*c87b03e5Sespie 286*c87b03e5Sespie /* Set up fs to describe the FDE for the caller of context. */ 287*c87b03e5Sespie code = uw_frame_state_for (&context, &fs); 288*c87b03e5Sespie if (code != _URC_NO_REASON && code != _URC_END_OF_STACK) 289*c87b03e5Sespie return _URC_FATAL_PHASE1_ERROR; 290*c87b03e5Sespie 291*c87b03e5Sespie /* Call trace function. */ 292*c87b03e5Sespie if ((*trace) (&context, trace_argument) != _URC_NO_REASON) 293*c87b03e5Sespie return _URC_FATAL_PHASE1_ERROR; 294*c87b03e5Sespie 295*c87b03e5Sespie /* We're done at end of stack. */ 296*c87b03e5Sespie if (code == _URC_END_OF_STACK) 297*c87b03e5Sespie break; 298*c87b03e5Sespie 299*c87b03e5Sespie /* Update context to describe the same frame as fs. */ 300*c87b03e5Sespie uw_update_context (&context, &fs); 301*c87b03e5Sespie } 302*c87b03e5Sespie 303*c87b03e5Sespie return code; 304*c87b03e5Sespie} 305