Mercurial > hg > CbC > CbC_gcc
comparison libgcc/unwind.inc @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Exception handling and frame unwind runtime interface routines. -*- C -*- | |
2 Copyright (C) 2001-2017 Free Software Foundation, Inc. | |
3 | |
4 This file is part of GCC. | |
5 | |
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. | |
10 | |
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. | |
15 | |
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/>. */ | |
24 | |
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. */ | |
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 | |
37 static _Unwind_Reason_Code | |
38 _Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc, | |
39 struct _Unwind_Context *context) | |
40 { | |
41 _Unwind_Reason_Code code; | |
42 | |
43 while (1) | |
44 { | |
45 _Unwind_FrameState fs; | |
46 int match_handler; | |
47 | |
48 code = uw_frame_state_for (context, &fs); | |
49 | |
50 /* Identify when we've reached the designated handler context. */ | |
51 match_handler = (uw_identify_context (context) == exc->private_2 | |
52 ? _UA_HANDLER_FRAME : 0); | |
53 | |
54 if (code != _URC_NO_REASON) | |
55 /* Some error encountered. Usually the unwinder doesn't | |
56 diagnose these and merely crashes. */ | |
57 return _URC_FATAL_PHASE2_ERROR; | |
58 | |
59 /* Unwind successful. Run the personality routine, if any. */ | |
60 if (fs.personality) | |
61 { | |
62 code = (*fs.personality) (1, _UA_CLEANUP_PHASE | match_handler, | |
63 exc->exception_class, exc, context); | |
64 if (code == _URC_INSTALL_CONTEXT) | |
65 break; | |
66 if (code != _URC_CONTINUE_UNWIND) | |
67 return _URC_FATAL_PHASE2_ERROR; | |
68 } | |
69 | |
70 /* Don't let us unwind past the handler context. */ | |
71 gcc_assert (!match_handler); | |
72 | |
73 uw_update_context (context, &fs); | |
74 } | |
75 | |
76 return code; | |
77 } | |
78 | |
79 /* Raise an exception, passing along the given exception object. */ | |
80 | |
81 _Unwind_Reason_Code LIBGCC2_UNWIND_ATTRIBUTE | |
82 _Unwind_RaiseException(struct _Unwind_Exception *exc) | |
83 { | |
84 struct _Unwind_Context this_context, cur_context; | |
85 _Unwind_Reason_Code code; | |
86 | |
87 /* Set up this_context to describe the current stack frame. */ | |
88 uw_init_context (&this_context); | |
89 cur_context = this_context; | |
90 | |
91 /* Phase 1: Search. Unwind the stack, calling the personality routine | |
92 with the _UA_SEARCH_PHASE flag set. Do not modify the stack yet. */ | |
93 while (1) | |
94 { | |
95 _Unwind_FrameState fs; | |
96 | |
97 /* Set up fs to describe the FDE for the caller of cur_context. The | |
98 first time through the loop, that means __cxa_throw. */ | |
99 code = uw_frame_state_for (&cur_context, &fs); | |
100 | |
101 if (code == _URC_END_OF_STACK) | |
102 /* Hit end of stack with no handler found. */ | |
103 return _URC_END_OF_STACK; | |
104 | |
105 if (code != _URC_NO_REASON) | |
106 /* Some error encountered. Usually the unwinder doesn't | |
107 diagnose these and merely crashes. */ | |
108 return _URC_FATAL_PHASE1_ERROR; | |
109 | |
110 /* Unwind successful. Run the personality routine, if any. */ | |
111 if (fs.personality) | |
112 { | |
113 code = (*fs.personality) (1, _UA_SEARCH_PHASE, exc->exception_class, | |
114 exc, &cur_context); | |
115 if (code == _URC_HANDLER_FOUND) | |
116 break; | |
117 else if (code != _URC_CONTINUE_UNWIND) | |
118 return _URC_FATAL_PHASE1_ERROR; | |
119 } | |
120 | |
121 /* Update cur_context to describe the same frame as fs. */ | |
122 uw_update_context (&cur_context, &fs); | |
123 } | |
124 | |
125 /* Indicate to _Unwind_Resume and associated subroutines that this | |
126 is not a forced unwind. Further, note where we found a handler. */ | |
127 exc->private_1 = 0; | |
128 exc->private_2 = uw_identify_context (&cur_context); | |
129 | |
130 cur_context = this_context; | |
131 code = _Unwind_RaiseException_Phase2 (exc, &cur_context); | |
132 if (code != _URC_INSTALL_CONTEXT) | |
133 return code; | |
134 | |
135 uw_install_context (&this_context, &cur_context); | |
136 } | |
137 | |
138 | |
139 /* Subroutine of _Unwind_ForcedUnwind also invoked from _Unwind_Resume. */ | |
140 | |
141 static _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 | |
218 void 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 | |
267 void | |
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 } |