11553Srgrimes/* Exception handling and frame unwind runtime interface routines. -*- C -*- 21553Srgrimes Copyright (C) 2001, 2003, 2008, 2009 Free Software Foundation, Inc. 31553Srgrimes 41553Srgrimes This file is part of GCC. 51553Srgrimes 61553Srgrimes GCC is free software; you can redistribute it and/or modify it 71553Srgrimes under the terms of the GNU General Public License as published by 81553Srgrimes the Free Software Foundation; either version 3, or (at your option) 91553Srgrimes any later version. 101553Srgrimes 111553Srgrimes GCC is distributed in the hope that it will be useful, but WITHOUT 12263142Seadler ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 131553Srgrimes or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 141553Srgrimes License for more details. 151553Srgrimes 161553Srgrimes Under Section 7 of GPL version 3, you are granted additional 171553Srgrimes permissions described in the GCC Runtime Library Exception, version 181553Srgrimes 3.1, as published by the Free Software Foundation. 191553Srgrimes 201553Srgrimes You should have received a copy of the GNU General Public License and 211553Srgrimes a copy of the GCC Runtime Library Exception along with this program; 221553Srgrimes see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 231553Srgrimes <http://www.gnu.org/licenses/>. */ 241553Srgrimes 251553Srgrimes/* This is derived from the C++ ABI for IA-64. Where we diverge 261553Srgrimes for cross-architecture compatibility are noted with "@@@". 271553Srgrimes This file is included from unwind-dw2.c, unwind-sjlj.c or 281553Srgrimes unwind-ia64.c. */ 291553Srgrimes 301553Srgrimes/* Subroutine of _Unwind_RaiseException also invoked from _Unwind_Resume. 311553Srgrimes 321553Srgrimes Unwind the stack calling the personality routine to find both the 331553Srgrimes exception handler and intermediary cleanup code. We'll only locate 341553Srgrimes the first such frame here. Cleanup code will call back into 351553Srgrimes _Unwind_Resume and we'll continue Phase 2 there. */ 361553Srgrimes 371553Srgrimesstatic _Unwind_Reason_Code 381553Srgrimes_Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc, 391553Srgrimes struct _Unwind_Context *context) 401553Srgrimes{ 411553Srgrimes _Unwind_Reason_Code code; 421553Srgrimes 431553Srgrimes while (1) 441553Srgrimes { 451553Srgrimes _Unwind_FrameState fs; 461553Srgrimes int match_handler; 471553Srgrimes 481553Srgrimes code = uw_frame_state_for (context, &fs); 491553Srgrimes 501553Srgrimes /* Identify when we've reached the designated handler context. */ 511553Srgrimes match_handler = (uw_identify_context (context) == exc->private_2 521553Srgrimes ? _UA_HANDLER_FRAME : 0); 531553Srgrimes 541553Srgrimes if (code != _URC_NO_REASON) 551553Srgrimes /* Some error encountered. Usually the unwinder doesn't 561553Srgrimes diagnose these and merely crashes. */ 571553Srgrimes return _URC_FATAL_PHASE2_ERROR; 581553Srgrimes 591553Srgrimes /* Unwind successful. Run the personality routine, if any. */ 601553Srgrimes if (fs.personality) 611553Srgrimes { 621553Srgrimes code = (*fs.personality) (1, _UA_CLEANUP_PHASE | match_handler, 631553Srgrimes exc->exception_class, exc, context); 641553Srgrimes if (code == _URC_INSTALL_CONTEXT) 651553Srgrimes break; 661553Srgrimes if (code != _URC_CONTINUE_UNWIND) 671553Srgrimes return _URC_FATAL_PHASE2_ERROR; 681553Srgrimes } 691553Srgrimes 701553Srgrimes /* Don't let us unwind past the handler context. */ 711553Srgrimes gcc_assert (!match_handler); 721553Srgrimes 731553Srgrimes uw_update_context (context, &fs); 741553Srgrimes } 751553Srgrimes 761553Srgrimes return code; 771553Srgrimes} 781553Srgrimes 791553Srgrimes/* Raise an exception, passing along the given exception object. */ 801553Srgrimes 811553Srgrimes_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE 821553Srgrimes_Unwind_RaiseException(struct _Unwind_Exception *exc) 831553Srgrimes{ 841553Srgrimes struct _Unwind_Context this_context, cur_context; 851553Srgrimes _Unwind_Reason_Code code; 861553Srgrimes 871553Srgrimes /* Set up this_context to describe the current stack frame. */ 881553Srgrimes uw_init_context (&this_context); 891553Srgrimes cur_context = this_context; 901553Srgrimes 911553Srgrimes /* Phase 1: Search. Unwind the stack, calling the personality routine 921553Srgrimes with the _UA_SEARCH_PHASE flag set. Do not modify the stack yet. */ 931553Srgrimes while (1) 941553Srgrimes { 951553Srgrimes _Unwind_FrameState fs; 961553Srgrimes 971553Srgrimes /* Set up fs to describe the FDE for the caller of cur_context. The 981553Srgrimes first time through the loop, that means __cxa_throw. */ 991553Srgrimes code = uw_frame_state_for (&cur_context, &fs); 1001553Srgrimes 1011553Srgrimes if (code == _URC_END_OF_STACK) 1021553Srgrimes /* Hit end of stack with no handler found. */ 1031553Srgrimes return _URC_END_OF_STACK; 1041553Srgrimes 1051553Srgrimes if (code != _URC_NO_REASON) 1061553Srgrimes /* Some error encountered. Usually the unwinder doesn't 1071553Srgrimes diagnose these and merely crashes. */ 1081553Srgrimes return _URC_FATAL_PHASE1_ERROR; 1091553Srgrimes 1101553Srgrimes /* Unwind successful. Run the personality routine, if any. */ 1111553Srgrimes if (fs.personality) 1121553Srgrimes { 1131553Srgrimes code = (*fs.personality) (1, _UA_SEARCH_PHASE, exc->exception_class, 1141553Srgrimes exc, &cur_context); 1151553Srgrimes if (code == _URC_HANDLER_FOUND) 1161553Srgrimes break; 1171553Srgrimes else if (code != _URC_CONTINUE_UNWIND) 1181553Srgrimes return _URC_FATAL_PHASE1_ERROR; 1191553Srgrimes } 1201553Srgrimes 1211553Srgrimes /* Update cur_context to describe the same frame as fs. */ 1221553Srgrimes uw_update_context (&cur_context, &fs); 1231553Srgrimes } 1241553Srgrimes 1251553Srgrimes /* Indicate to _Unwind_Resume and associated subroutines that this 1261553Srgrimes is not a forced unwind. Further, note where we found a handler. */ 1271553Srgrimes exc->private_1 = 0; 1281553Srgrimes exc->private_2 = uw_identify_context (&cur_context); 1291553Srgrimes 1301553Srgrimes cur_context = this_context; 1311553Srgrimes code = _Unwind_RaiseException_Phase2 (exc, &cur_context); 1321553Srgrimes if (code != _URC_INSTALL_CONTEXT) 1331553Srgrimes return code; 1341553Srgrimes 1351553Srgrimes uw_install_context (&this_context, &cur_context); 1361553Srgrimes} 1371553Srgrimes 138 139/* Subroutine of _Unwind_ForcedUnwind also invoked from _Unwind_Resume. */ 140 141static _Unwind_Reason_Code 142_Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc, 143 struct _Unwind_Context *context) 144{ 145 _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) (_Unwind_Ptr) exc->private_1; 146 void *stop_argument = (void *) (_Unwind_Ptr) exc->private_2; 147 _Unwind_Reason_Code code, stop_code; 148 149 while (1) 150 { 151 _Unwind_FrameState fs; 152 int action; 153 154 /* Set up fs to describe the FDE for the caller of cur_context. */ 155 code = uw_frame_state_for (context, &fs); 156 if (code != _URC_NO_REASON && code != _URC_END_OF_STACK) 157 return _URC_FATAL_PHASE2_ERROR; 158 159 /* Unwind successful. */ 160 action = _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE; 161 if (code == _URC_END_OF_STACK) 162 action |= _UA_END_OF_STACK; 163 stop_code = (*stop) (1, action, exc->exception_class, exc, 164 context, stop_argument); 165 if (stop_code != _URC_NO_REASON) 166 return _URC_FATAL_PHASE2_ERROR; 167 168 /* Stop didn't want to do anything. Invoke the personality 169 handler, if applicable, to run cleanups. */ 170 if (code == _URC_END_OF_STACK) 171 break; 172 173 if (fs.personality) 174 { 175 code = (*fs.personality) (1, _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE, 176 exc->exception_class, exc, context); 177 if (code == _URC_INSTALL_CONTEXT) 178 break; 179 if (code != _URC_CONTINUE_UNWIND) 180 return _URC_FATAL_PHASE2_ERROR; 181 } 182 183 /* Update cur_context to describe the same frame as fs, and discard 184 the previous context if necessary. */ 185 uw_advance_context (context, &fs); 186 } 187 188 return code; 189} 190 191 192/* Raise an exception for forced unwinding. */ 193 194_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE 195_Unwind_ForcedUnwind (struct _Unwind_Exception *exc, 196 _Unwind_Stop_Fn stop, void * stop_argument) 197{ 198 struct _Unwind_Context this_context, cur_context; 199 _Unwind_Reason_Code code; 200 201 uw_init_context (&this_context); 202 cur_context = this_context; 203 204 exc->private_1 = (_Unwind_Ptr) stop; 205 exc->private_2 = (_Unwind_Ptr) stop_argument; 206 207 code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context); 208 if (code != _URC_INSTALL_CONTEXT) 209 return code; 210 211 uw_install_context (&this_context, &cur_context); 212} 213 214 215/* Resume propagation of an existing exception. This is used after 216 e.g. executing cleanup code, and not to implement rethrowing. */ 217 218void LIBGCC2_UNWIND_ATTRIBUTE 219_Unwind_Resume (struct _Unwind_Exception *exc) 220{ 221 struct _Unwind_Context this_context, cur_context; 222 _Unwind_Reason_Code code; 223 224 uw_init_context (&this_context); 225 cur_context = this_context; 226 227 /* Choose between continuing to process _Unwind_RaiseException 228 or _Unwind_ForcedUnwind. */ 229 if (exc->private_1 == 0) 230 code = _Unwind_RaiseException_Phase2 (exc, &cur_context); 231 else 232 code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context); 233 234 gcc_assert (code == _URC_INSTALL_CONTEXT); 235 236 uw_install_context (&this_context, &cur_context); 237} 238 239 240/* Resume propagation of an FORCE_UNWIND exception, or to rethrow 241 a normal exception that was handled. */ 242 243_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE 244_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc) 245{ 246 struct _Unwind_Context this_context, cur_context; 247 _Unwind_Reason_Code code; 248 249 /* Choose between continuing to process _Unwind_RaiseException 250 or _Unwind_ForcedUnwind. */ 251 if (exc->private_1 == 0) 252 return _Unwind_RaiseException (exc); 253 254 uw_init_context (&this_context); 255 cur_context = this_context; 256 257 code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context); 258 259 gcc_assert (code == _URC_INSTALL_CONTEXT); 260 261 uw_install_context (&this_context, &cur_context); 262} 263 264 265/* A convenience function that calls the exception_cleanup field. */ 266 267void 268_Unwind_DeleteException (struct _Unwind_Exception *exc) 269{ 270 if (exc->exception_cleanup) 271 (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc); 272} 273 274 275/* Perform stack backtrace through unwind data. */ 276 277_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE 278_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument) 279{ 280 struct _Unwind_Context context; 281 _Unwind_Reason_Code code; 282 283 uw_init_context (&context); 284 285 while (1) 286 { 287 _Unwind_FrameState fs; 288 289 /* Set up fs to describe the FDE for the caller of context. */ 290 code = uw_frame_state_for (&context, &fs); 291 if (code != _URC_NO_REASON && code != _URC_END_OF_STACK) 292 return _URC_FATAL_PHASE1_ERROR; 293 294 /* Call trace function. */ 295 if ((*trace) (&context, trace_argument) != _URC_NO_REASON) 296 return _URC_FATAL_PHASE1_ERROR; 297 298 /* We're done at end of stack. */ 299 if (code == _URC_END_OF_STACK) 300 break; 301 302 /* Update context to describe the same frame as fs. */ 303 uw_update_context (&context, &fs); 304 } 305 306 return code; 307} 308