]> gcc.gnu.org Git - gcc.git/blame - gcc/unwind.inc
asprintf.c: Don't define USE_STDARG.
[gcc.git] / gcc / unwind.inc
CommitLineData
89797976 1/* Exception handling and frame unwind runtime interface routines. -*- C -*-
52a11cbf
RH
2 Copyright (C) 2001 Free Software Foundation, Inc.
3
1322177d 4 This file is part of GCC.
52a11cbf 5
1322177d
LB
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
52a11cbf
RH
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
1322177d
LB
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.
52a11cbf
RH
15
16 You should have received a copy of the GNU General Public License
1322177d
LB
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
52a11cbf
RH
20
21/* This is derived from the C++ ABI for IA-64. Where we diverge
22 for cross-architecture compatibility are noted with "@@@".
23 This file is included from unwind-dw2.c or unwind-ia64.c. */
24
25/* Subroutine of _Unwind_RaiseException also invoked from _Unwind_Resume.
26
27 Unwind the stack calling the personality routine to find both the
28 exception handler and intermediary cleanup code. We'll only locate
29 the first such frame here. Cleanup code will call back into
30 _Unwind_Resume and we'll continue Phase 2 there. */
31
32static _Unwind_Reason_Code
33_Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc,
34 struct _Unwind_Context *context)
35{
36 _Unwind_Reason_Code code;
37
38 while (1)
39 {
40 _Unwind_FrameState fs;
41 int match_handler;
42
43 code = uw_frame_state_for (context, &fs);
44
45 /* Identify when we've reached the designated handler context. */
46 match_handler = (uw_identify_context (context) == exc->private_2
47 ? _UA_HANDLER_FRAME : 0);
48
49 if (code != _URC_NO_REASON)
50 /* Some error encountered. Ususally the unwinder doesn't
51 diagnose these and merely crashes. */
52 return _URC_FATAL_PHASE2_ERROR;
53
54 /* Unwind successful. Run the personality routine, if any. */
55 if (fs.personality)
56 {
57 code = (*fs.personality) (1, _UA_CLEANUP_PHASE | match_handler,
58 exc->exception_class, exc, context);
59 if (code == _URC_INSTALL_CONTEXT)
60 break;
61 if (code != _URC_CONTINUE_UNWIND)
62 return _URC_FATAL_PHASE2_ERROR;
63 }
64
65 /* Don't let us unwind past the handler context. */
66 if (match_handler)
67 abort ();
68
69 uw_update_context (context, &fs);
70 }
71
72 return code;
73}
74
75
76/* Raise an exception, passing along the given exception object. */
77
78_Unwind_Reason_Code
79_Unwind_RaiseException(struct _Unwind_Exception *exc)
80{
81 struct _Unwind_Context this_context, cur_context;
82 _Unwind_Reason_Code code;
83
84 uw_init_context (&this_context);
85 cur_context = this_context;
86
87 /* Phase 1: Search. Unwind the stack, calling the personality routine
88 with the _UA_SEARCH_PHASE flag set. Do not modify the stack yet. */
89 while (1)
90 {
91 _Unwind_FrameState fs;
92
93 code = uw_frame_state_for (&cur_context, &fs);
94
95 if (code == _URC_END_OF_STACK)
96 /* Hit end of stack with no handler found. */
97 return _URC_END_OF_STACK;
98
99 if (code != _URC_NO_REASON)
100 /* Some error encountered. Ususally the unwinder doesn't
101 diagnose these and merely crashes. */
102 return _URC_FATAL_PHASE1_ERROR;
103
104 /* Unwind successful. Run the personality routine, if any. */
105 if (fs.personality)
106 {
107 code = (*fs.personality) (1, _UA_SEARCH_PHASE, exc->exception_class,
108 exc, &cur_context);
109 if (code == _URC_HANDLER_FOUND)
110 break;
111 else if (code != _URC_CONTINUE_UNWIND)
112 return _URC_FATAL_PHASE1_ERROR;
113 }
114
115 uw_update_context (&cur_context, &fs);
116 }
117
118 /* Indicate to _Unwind_Resume and associated subroutines that this
119 is not a forced unwind. Further, note where we found a handler. */
120 exc->private_1 = 0;
121 exc->private_2 = uw_identify_context (&cur_context);
122
123 cur_context = this_context;
124 code = _Unwind_RaiseException_Phase2 (exc, &cur_context);
125 if (code != _URC_INSTALL_CONTEXT)
126 return code;
127
128 uw_install_context (&this_context, &cur_context);
129}
130
131
132/* Subroutine of _Unwind_ForcedUnwind also invoked from _Unwind_Resume. */
133
134static _Unwind_Reason_Code
135_Unwind_ForcedUnwind_Phase2(struct _Unwind_Exception *exc,
136 struct _Unwind_Context *context)
137{
9e800206
RH
138 _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) (_Unwind_Ptr) exc->private_1;
139 void *stop_argument = (void *) (_Unwind_Ptr) exc->private_2;
52a11cbf
RH
140 _Unwind_Reason_Code code, stop_code;
141
142 while (1)
143 {
144 _Unwind_FrameState fs;
145
146 code = uw_frame_state_for (context, &fs);
147 if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
148 return _URC_FATAL_PHASE2_ERROR;
149
150 /* Unwind successful. */
151 stop_code = (*stop) (1, _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE,
152 exc->exception_class, exc, context, stop_argument);
153 if (stop_code != _URC_NO_REASON)
154 return _URC_FATAL_PHASE2_ERROR;
155
156 /* Stop didn't want to do anything. Invoke the personality
157 handler, if applicable, to run cleanups. */
158 if (code == _URC_END_OF_STACK)
159 break;
160
161 if (fs.personality)
162 {
163 code = (*fs.personality) (1, _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE,
164 exc->exception_class, exc, context);
165 if (code == _URC_INSTALL_CONTEXT)
166 break;
167 if (code != _URC_CONTINUE_UNWIND)
168 return _URC_FATAL_PHASE2_ERROR;
169 }
170
171 uw_update_context (context, &fs);
172 }
173
174 return code;
175}
176
177
178/* Raise an exception for forced unwinding. */
179
180_Unwind_Reason_Code
181_Unwind_ForcedUnwind (struct _Unwind_Exception *exc,
182 _Unwind_Stop_Fn stop, void * stop_argument)
183{
184 struct _Unwind_Context this_context, cur_context;
185 _Unwind_Reason_Code code;
186
187 uw_init_context (&this_context);
188 cur_context = this_context;
189
190 exc->private_1 = (_Unwind_Ptr) stop;
191 exc->private_2 = (_Unwind_Ptr) stop_argument;
192
193 code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
194 if (code != _URC_INSTALL_CONTEXT)
195 return code;
196
197 uw_install_context (&this_context, &cur_context);
198}
199
200
201/* Resume propagation of an existing exception. This is used after
202 e.g. executing cleanup code, and not to implement rethrowing. */
203
204void
205_Unwind_Resume (struct _Unwind_Exception *exc)
206{
207 struct _Unwind_Context this_context, cur_context;
208 _Unwind_Reason_Code code;
209
210 uw_init_context (&this_context);
211 cur_context = this_context;
212
213 /* Choose between continuing to process _Unwind_RaiseException
214 or _Unwind_ForcedUnwind. */
215 if (exc->private_1 == 0)
216 code = _Unwind_RaiseException_Phase2 (exc, &cur_context);
217 else
218 code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
219
220 if (code != _URC_INSTALL_CONTEXT)
221 abort ();
222
223 uw_install_context (&this_context, &cur_context);
224}
225
226/* A convenience function that calls the exception_cleanup field. */
227
228void
229_Unwind_DeleteException (struct _Unwind_Exception *exc)
230{
231 (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
232}
This page took 0.198333 seconds and 5 git commands to generate.