]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/unwind.inc
reload1: Change return type of predicate function from int to bool
[thirdparty/gcc.git] / libgcc / unwind.inc
CommitLineData
89797976 1/* Exception handling and frame unwind runtime interface routines. -*- C -*-
83ffe9cd 2 Copyright (C) 2001-2023 Free Software Foundation, Inc.
52a11cbf 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
748086b7 8 the Free Software Foundation; either version 3, or (at your option)
52a11cbf
RH
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 15
748086b7
JJ
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.
19
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/>. */
52a11cbf
RH
24
25/* This is derived from the C++ ABI for IA-64. Where we diverge
26 for cross-architecture compatibility are noted with "@@@".
cb96cf3b
BE
27 This file is included from unwind-dw2.c, unwind-sjlj.c or
28 unwind-ia64.c. */
52a11cbf
RH
29
30/* Subroutine of _Unwind_RaiseException also invoked from _Unwind_Resume.
31
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. */
36
37static _Unwind_Reason_Code
38_Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc,
6a10fff4
IT
39 struct _Unwind_Context *context,
40 unsigned long *frames_p)
52a11cbf
RH
41{
42 _Unwind_Reason_Code code;
6a10fff4 43 unsigned long frames = 1;
52a11cbf
RH
44
45 while (1)
46 {
47 _Unwind_FrameState fs;
48 int match_handler;
49
50 code = uw_frame_state_for (context, &fs);
51
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);
55
56 if (code != _URC_NO_REASON)
e3aafbad 57 /* Some error encountered. Usually the unwinder doesn't
52a11cbf
RH
58 diagnose these and merely crashes. */
59 return _URC_FATAL_PHASE2_ERROR;
60
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 }
71
72 /* Don't let us unwind past the handler context. */
79d0dfa3 73 gcc_assert (!match_handler);
52a11cbf
RH
74
75 uw_update_context (context, &fs);
9072db9d 76 _Unwind_Frames_Increment (exc, context, frames);
52a11cbf
RH
77 }
78
6a10fff4 79 *frames_p = frames;
52a11cbf
RH
80 return code;
81}
82
52a11cbf
RH
83/* Raise an exception, passing along the given exception object. */
84
56e449d3 85_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
52a11cbf
RH
86_Unwind_RaiseException(struct _Unwind_Exception *exc)
87{
88 struct _Unwind_Context this_context, cur_context;
89 _Unwind_Reason_Code code;
6a10fff4 90 unsigned long frames;
52a11cbf 91
81a60e6c 92 /* Set up this_context to describe the current stack frame. */
52a11cbf
RH
93 uw_init_context (&this_context);
94 cur_context = this_context;
95
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;
101
81a60e6c
JM
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. */
52a11cbf
RH
104 code = uw_frame_state_for (&cur_context, &fs);
105
106 if (code == _URC_END_OF_STACK)
107 /* Hit end of stack with no handler found. */
108 return _URC_END_OF_STACK;
109
110 if (code != _URC_NO_REASON)
fa10beec 111 /* Some error encountered. Usually the unwinder doesn't
52a11cbf
RH
112 diagnose these and merely crashes. */
113 return _URC_FATAL_PHASE1_ERROR;
114
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 }
125
81a60e6c 126 /* Update cur_context to describe the same frame as fs. */
52a11cbf
RH
127 uw_update_context (&cur_context, &fs);
128 }
129
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);
134
135 cur_context = this_context;
6a10fff4 136 code = _Unwind_RaiseException_Phase2 (exc, &cur_context, &frames);
52a11cbf
RH
137 if (code != _URC_INSTALL_CONTEXT)
138 return code;
139
6a10fff4 140 uw_install_context (&this_context, &cur_context, frames);
52a11cbf
RH
141}
142
143
144/* Subroutine of _Unwind_ForcedUnwind also invoked from _Unwind_Resume. */
145
146static _Unwind_Reason_Code
79d0dfa3 147_Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc,
6a10fff4
IT
148 struct _Unwind_Context *context,
149 unsigned long *frames_p)
52a11cbf 150{
9e800206
RH
151 _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) (_Unwind_Ptr) exc->private_1;
152 void *stop_argument = (void *) (_Unwind_Ptr) exc->private_2;
52a11cbf 153 _Unwind_Reason_Code code, stop_code;
6a10fff4 154 unsigned long frames = 1;
52a11cbf
RH
155
156 while (1)
157 {
158 _Unwind_FrameState fs;
4c21ef03 159 int action;
52a11cbf 160
81a60e6c 161 /* Set up fs to describe the FDE for the caller of cur_context. */
52a11cbf 162 code = uw_frame_state_for (context, &fs);
8d71d3a3
RMZ
163 if (code != _URC_NO_REASON && code != _URC_END_OF_STACK
164 && code != _URC_NORMAL_STOP)
52a11cbf
RH
165 return _URC_FATAL_PHASE2_ERROR;
166
167 /* Unwind successful. */
4c21ef03 168 action = _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE;
8d71d3a3 169 if (code == _URC_END_OF_STACK || code == _URC_NORMAL_STOP)
4c21ef03
RH
170 action |= _UA_END_OF_STACK;
171 stop_code = (*stop) (1, action, exc->exception_class, exc,
172 context, stop_argument);
52a11cbf
RH
173 if (stop_code != _URC_NO_REASON)
174 return _URC_FATAL_PHASE2_ERROR;
175
176 /* Stop didn't want to do anything. Invoke the personality
177 handler, if applicable, to run cleanups. */
178 if (code == _URC_END_OF_STACK)
179 break;
180
181 if (fs.personality)
182 {
183 code = (*fs.personality) (1, _UA_FORCE_UNWIND | _UA_CLEANUP_PHASE,
184 exc->exception_class, exc, context);
185 if (code == _URC_INSTALL_CONTEXT)
186 break;
187 if (code != _URC_CONTINUE_UNWIND)
188 return _URC_FATAL_PHASE2_ERROR;
189 }
190
60aef23e
DJ
191 /* Update cur_context to describe the same frame as fs, and discard
192 the previous context if necessary. */
193 uw_advance_context (context, &fs);
9072db9d 194 _Unwind_Frames_Increment (exc, context, frames);
52a11cbf
RH
195 }
196
6a10fff4 197 *frames_p = frames;
52a11cbf
RH
198 return code;
199}
200
201
202/* Raise an exception for forced unwinding. */
203
56e449d3 204_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
52a11cbf
RH
205_Unwind_ForcedUnwind (struct _Unwind_Exception *exc,
206 _Unwind_Stop_Fn stop, void * stop_argument)
207{
208 struct _Unwind_Context this_context, cur_context;
209 _Unwind_Reason_Code code;
6a10fff4 210 unsigned long frames;
52a11cbf
RH
211
212 uw_init_context (&this_context);
213 cur_context = this_context;
214
215 exc->private_1 = (_Unwind_Ptr) stop;
216 exc->private_2 = (_Unwind_Ptr) stop_argument;
217
6a10fff4 218 code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context, &frames);
52a11cbf
RH
219 if (code != _URC_INSTALL_CONTEXT)
220 return code;
221
6a10fff4 222 uw_install_context (&this_context, &cur_context, frames);
52a11cbf
RH
223}
224
225
226/* Resume propagation of an existing exception. This is used after
227 e.g. executing cleanup code, and not to implement rethrowing. */
228
56e449d3 229void LIBGCC2_UNWIND_ATTRIBUTE
52a11cbf
RH
230_Unwind_Resume (struct _Unwind_Exception *exc)
231{
232 struct _Unwind_Context this_context, cur_context;
233 _Unwind_Reason_Code code;
6a10fff4 234 unsigned long frames;
52a11cbf
RH
235
236 uw_init_context (&this_context);
237 cur_context = this_context;
238
239 /* Choose between continuing to process _Unwind_RaiseException
240 or _Unwind_ForcedUnwind. */
241 if (exc->private_1 == 0)
6a10fff4 242 code = _Unwind_RaiseException_Phase2 (exc, &cur_context, &frames);
52a11cbf 243 else
6a10fff4 244 code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context, &frames);
52a11cbf 245
79d0dfa3 246 gcc_assert (code == _URC_INSTALL_CONTEXT);
52a11cbf 247
6a10fff4 248 uw_install_context (&this_context, &cur_context, frames);
52a11cbf
RH
249}
250
a944ceb9
RH
251
252/* Resume propagation of an FORCE_UNWIND exception, or to rethrow
253 a normal exception that was handled. */
254
56e449d3 255_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
a944ceb9
RH
256_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc)
257{
258 struct _Unwind_Context this_context, cur_context;
259 _Unwind_Reason_Code code;
6a10fff4 260 unsigned long frames;
a944ceb9
RH
261
262 /* Choose between continuing to process _Unwind_RaiseException
263 or _Unwind_ForcedUnwind. */
264 if (exc->private_1 == 0)
265 return _Unwind_RaiseException (exc);
266
267 uw_init_context (&this_context);
268 cur_context = this_context;
269
6a10fff4 270 code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context, &frames);
a944ceb9 271
79d0dfa3 272 gcc_assert (code == _URC_INSTALL_CONTEXT);
a944ceb9 273
6a10fff4 274 uw_install_context (&this_context, &cur_context, frames);
a944ceb9
RH
275}
276
277
52a11cbf
RH
278/* A convenience function that calls the exception_cleanup field. */
279
280void
281_Unwind_DeleteException (struct _Unwind_Exception *exc)
282{
a944ceb9
RH
283 if (exc->exception_cleanup)
284 (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
52a11cbf 285}
7344f3d7
UW
286
287
288/* Perform stack backtrace through unwind data. */
289
56e449d3 290_Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE
7344f3d7
UW
291_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument)
292{
293 struct _Unwind_Context context;
294 _Unwind_Reason_Code code;
295
296 uw_init_context (&context);
297
298 while (1)
299 {
300 _Unwind_FrameState fs;
301
302 /* Set up fs to describe the FDE for the caller of context. */
303 code = uw_frame_state_for (&context, &fs);
b7561b5d
RMZ
304 if (code != _URC_NO_REASON && code != _URC_END_OF_STACK
305 && code != _URC_NORMAL_STOP)
7344f3d7
UW
306 return _URC_FATAL_PHASE1_ERROR;
307
308 /* Call trace function. */
309 if ((*trace) (&context, trace_argument) != _URC_NO_REASON)
310 return _URC_FATAL_PHASE1_ERROR;
311
b7561b5d
RMZ
312#ifdef MD_BACKCHAIN_FALLBACK
313 /* Do a backchain if there is no DWARF data. */
314 if (code == _URC_NORMAL_STOP)
315 {
316 MD_BACKCHAIN_FALLBACK(&context, trace_argument);
317 break;
318 }
319#endif
320
321 /* We're done at end of stack. */
7344f3d7
UW
322 if (code == _URC_END_OF_STACK)
323 break;
324
325 /* Update context to describe the same frame as fs. */
326 uw_update_context (&context, &fs);
327 }
328
329 return code;
330}