aix: Support libsupc++ as a FAT library
[official-gcc.git] / libgcc / unwind.inc
blob9acead33ffc01e892d6feda2aaeffd9d04e56e74
1 /* Exception handling and frame unwind runtime interface routines. -*- C -*-
2    Copyright (C) 2001-2020 Free Software Foundation, Inc.
4    This file is part of GCC.
6    GCC is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
11    GCC is distributed in the hope that it will be useful, but WITHOUT
12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14    License for more details.
16    Under Section 7 of GPL version 3, you are granted additional
17    permissions described in the GCC Runtime Library Exception, version
18    3.1, as published by the Free Software Foundation.
20    You should have received a copy of the GNU General Public License and
21    a copy of the GCC Runtime Library Exception along with this program;
22    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23    <http://www.gnu.org/licenses/>.  */
25 /* This is derived from the C++ ABI for IA-64.  Where we diverge
26    for cross-architecture compatibility are noted with "@@@".  
27    This file is included from unwind-dw2.c, unwind-sjlj.c or
28    unwind-ia64.c.  */
30 /* Subroutine of _Unwind_RaiseException also invoked from _Unwind_Resume. 
32    Unwind the stack calling the personality routine to find both the
33    exception handler and intermediary cleanup code.  We'll only locate
34    the first such frame here.  Cleanup code will call back into
35    _Unwind_Resume and we'll continue Phase 2 there.  */
37 static _Unwind_Reason_Code
38 _Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc,
39                               struct _Unwind_Context *context,
40                               unsigned long *frames_p)
42   _Unwind_Reason_Code code;
43   unsigned long frames = 1;
45   while (1)
46     {
47       _Unwind_FrameState fs;
48       int match_handler;
50       code = uw_frame_state_for (context, &fs);
52       /* Identify when we've reached the designated handler context.  */
53       match_handler = (uw_identify_context (context) == exc->private_2
54                        ? _UA_HANDLER_FRAME : 0);
56       if (code != _URC_NO_REASON)
57         /* Some error encountered.  Usually the unwinder doesn't
58            diagnose these and merely crashes.  */
59         return _URC_FATAL_PHASE2_ERROR;
61       /* Unwind successful.  Run the personality routine, if any.  */
62       if (fs.personality)
63         {
64           code = (*fs.personality) (1, _UA_CLEANUP_PHASE | match_handler,
65                                     exc->exception_class, exc, context);
66           if (code == _URC_INSTALL_CONTEXT)
67             break;
68           if (code != _URC_CONTINUE_UNWIND) 
69             return _URC_FATAL_PHASE2_ERROR;
70         }
72       /* Don't let us unwind past the handler context.  */
73       gcc_assert (!match_handler);
75       uw_update_context (context, &fs);
76       _Unwind_Frames_Increment (context, frames);
77     }
79   *frames_p = frames;
80   return code;
83 /* Raise an exception, passing along the given exception object.  */
85 _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
86 _Unwind_RaiseException(struct _Unwind_Exception *exc)
88   struct _Unwind_Context this_context, cur_context;
89   _Unwind_Reason_Code code;
90   unsigned long frames;
92   /* Set up this_context to describe the current stack frame.  */
93   uw_init_context (&this_context);
94   cur_context = this_context;
96   /* Phase 1: Search.  Unwind the stack, calling the personality routine
97      with the _UA_SEARCH_PHASE flag set.  Do not modify the stack yet.  */
98   while (1)
99     {
100       _Unwind_FrameState fs;
102       /* Set up fs to describe the FDE for the caller of cur_context.  The
103          first time through the loop, that means __cxa_throw.  */
104       code = uw_frame_state_for (&cur_context, &fs);
106       if (code == _URC_END_OF_STACK)
107         /* Hit end of stack with no handler found.  */
108         return _URC_END_OF_STACK;
110       if (code != _URC_NO_REASON)
111         /* Some error encountered.  Usually the unwinder doesn't
112            diagnose these and merely crashes.  */
113         return _URC_FATAL_PHASE1_ERROR;
115       /* Unwind successful.  Run the personality routine, if any.  */
116       if (fs.personality)
117         {
118           code = (*fs.personality) (1, _UA_SEARCH_PHASE, exc->exception_class,
119                                     exc, &cur_context);
120           if (code == _URC_HANDLER_FOUND)
121             break;
122           else if (code != _URC_CONTINUE_UNWIND)
123             return _URC_FATAL_PHASE1_ERROR;
124         }
126       /* Update cur_context to describe the same frame as fs.  */
127       uw_update_context (&cur_context, &fs);
128     }
130   /* Indicate to _Unwind_Resume and associated subroutines that this
131      is not a forced unwind.  Further, note where we found a handler.  */
132   exc->private_1 = 0;
133   exc->private_2 = uw_identify_context (&cur_context);
135   cur_context = this_context;
136   code = _Unwind_RaiseException_Phase2 (exc, &cur_context, &frames);
137   if (code != _URC_INSTALL_CONTEXT)
138     return code;
140   uw_install_context (&this_context, &cur_context, frames);
144 /* Subroutine of _Unwind_ForcedUnwind also invoked from _Unwind_Resume.  */
146 static _Unwind_Reason_Code
147 _Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc,
148                              struct _Unwind_Context *context,
149                              unsigned long *frames_p)
151   _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) (_Unwind_Ptr) exc->private_1;
152   void *stop_argument = (void *) (_Unwind_Ptr) exc->private_2;
153   _Unwind_Reason_Code code, stop_code;
154   unsigned long frames = 1;
156   while (1)
157     {
158       _Unwind_FrameState fs;
159       int action;
161       /* Set up fs to describe the FDE for the caller of cur_context.  */
162       code = uw_frame_state_for (context, &fs);
163       if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
164         return _URC_FATAL_PHASE2_ERROR;
166       /* Unwind successful.  */
167       action = _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE;
168       if (code == _URC_END_OF_STACK)
169         action |= _UA_END_OF_STACK;
170       stop_code = (*stop) (1, action, exc->exception_class, exc,
171                            context, stop_argument);
172       if (stop_code != _URC_NO_REASON)
173         return _URC_FATAL_PHASE2_ERROR;
175       /* Stop didn't want to do anything.  Invoke the personality
176          handler, if applicable, to run cleanups.  */
177       if (code == _URC_END_OF_STACK)
178         break;
179         
180       if (fs.personality)
181         {
182           code = (*fs.personality) (1, _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE,
183                                     exc->exception_class, exc, context);
184           if (code == _URC_INSTALL_CONTEXT)
185             break;
186           if (code != _URC_CONTINUE_UNWIND) 
187             return _URC_FATAL_PHASE2_ERROR;
188         }
190       /* Update cur_context to describe the same frame as fs, and discard
191          the previous context if necessary.  */
192       uw_advance_context (context, &fs);
193       _Unwind_Frames_Increment (context, frames);
194     }
196   *frames_p = frames;
197   return code;
201 /* Raise an exception for forced unwinding.  */
203 _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
204 _Unwind_ForcedUnwind (struct _Unwind_Exception *exc,
205                       _Unwind_Stop_Fn stop, void * stop_argument)
207   struct _Unwind_Context this_context, cur_context;
208   _Unwind_Reason_Code code;
209   unsigned long frames;
211   uw_init_context (&this_context);
212   cur_context = this_context;
214   exc->private_1 = (_Unwind_Ptr) stop;
215   exc->private_2 = (_Unwind_Ptr) stop_argument;
217   code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context, &frames);
218   if (code != _URC_INSTALL_CONTEXT)
219     return code;
221   uw_install_context (&this_context, &cur_context, frames);
225 /* Resume propagation of an existing exception.  This is used after
226    e.g. executing cleanup code, and not to implement rethrowing.  */
228 void LIBGCC2_UNWIND_ATTRIBUTE
229 _Unwind_Resume (struct _Unwind_Exception *exc)
231   struct _Unwind_Context this_context, cur_context;
232   _Unwind_Reason_Code code;
233   unsigned long frames;
235   uw_init_context (&this_context);
236   cur_context = this_context;
238   /* Choose between continuing to process _Unwind_RaiseException
239      or _Unwind_ForcedUnwind.  */
240   if (exc->private_1 == 0)
241     code = _Unwind_RaiseException_Phase2 (exc, &cur_context, &frames);
242   else
243     code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context, &frames);
245   gcc_assert (code == _URC_INSTALL_CONTEXT);
247   uw_install_context (&this_context, &cur_context, frames);
251 /* Resume propagation of an FORCE_UNWIND exception, or to rethrow
252    a normal exception that was handled.  */
254 _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
255 _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc)
257   struct _Unwind_Context this_context, cur_context;
258   _Unwind_Reason_Code code;
259   unsigned long frames;
261   /* Choose between continuing to process _Unwind_RaiseException
262      or _Unwind_ForcedUnwind.  */
263   if (exc->private_1 == 0)
264     return _Unwind_RaiseException (exc);
266   uw_init_context (&this_context);
267   cur_context = this_context;
269   code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context, &frames);
271   gcc_assert (code == _URC_INSTALL_CONTEXT);
273   uw_install_context (&this_context, &cur_context, frames);
277 /* A convenience function that calls the exception_cleanup field.  */
279 void
280 _Unwind_DeleteException (struct _Unwind_Exception *exc)
282   if (exc->exception_cleanup)
283     (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
287 /* Perform stack backtrace through unwind data.  */
289 _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
290 _Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument)
292   struct _Unwind_Context context;
293   _Unwind_Reason_Code code;
295   uw_init_context (&context);
297   while (1)
298     {
299       _Unwind_FrameState fs;
301       /* Set up fs to describe the FDE for the caller of context.  */
302       code = uw_frame_state_for (&context, &fs);
303       if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
304         return _URC_FATAL_PHASE1_ERROR;
306       /* Call trace function.  */
307       if ((*trace) (&context, trace_argument) != _URC_NO_REASON)
308         return _URC_FATAL_PHASE1_ERROR;
310       /* We're done at end of stack.  */        
311       if (code == _URC_END_OF_STACK)
312         break;
314       /* Update context to describe the same frame as fs.  */
315       uw_update_context (&context, &fs);
316     }
318   return code;