annotate libgcc/unwind.inc @ 158:494b0b89df80 default tip

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