Eliminate prepare_to_throw_exception
[deliverable/binutils-gdb.git] / gdb / common / common-exceptions.c
CommitLineData
ff55e1b5
GB
1/* Exception (throw catch) mechanism, for GDB, the GNU debugger.
2
618f726f 3 Copyright (C) 1986-2016 Free Software Foundation, Inc.
ff55e1b5
GB
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#include "common-defs.h"
21#include "common-exceptions.h"
ff55e1b5 22
44a8b4df 23const struct gdb_exception exception_none = { (enum return_reason) 0, GDB_NO_ERROR, NULL };
ad6aff7d 24
eec461d0 25#if GDB_XCPT == GDB_XCPT_SJMP
72df25b2 26
ff55e1b5
GB
27/* Possible catcher states. */
28enum catcher_state {
29 /* Initial state, a new catcher has just been created. */
30 CATCHER_CREATED,
31 /* The catch code is running. */
32 CATCHER_RUNNING,
33 CATCHER_RUNNING_1,
34 /* The catch code threw an exception. */
35 CATCHER_ABORTING
36};
37
38/* Possible catcher actions. */
39enum catcher_action {
40 CATCH_ITER,
41 CATCH_ITER_1,
42 CATCH_THROWING
43};
44
45struct catcher
46{
47 enum catcher_state state;
48 /* Jump buffer pointing back at the exception handler. */
49 SIGJMP_BUF buf;
50 /* Status buffer belonging to the exception handler. */
492d29ea 51 struct gdb_exception exception;
ff55e1b5
GB
52 struct cleanup *saved_cleanup_chain;
53 /* Back link. */
54 struct catcher *prev;
55};
56
57/* Where to go for throw_exception(). */
58static struct catcher *current_catcher;
59
60/* Return length of current_catcher list. */
61
62static int
63catcher_list_size (void)
64{
65 int size;
66 struct catcher *catcher;
67
68 for (size = 0, catcher = current_catcher;
69 catcher != NULL;
70 catcher = catcher->prev)
71 ++size;
72
73 return size;
74}
75
76SIGJMP_BUF *
492d29ea 77exceptions_state_mc_init (void)
ff55e1b5
GB
78{
79 struct catcher *new_catcher = XCNEW (struct catcher);
80
492d29ea
PA
81 /* Start with no exception. */
82 new_catcher->exception = exception_none;
ff55e1b5
GB
83
84 /* Prevent error/quit during FUNC from calling cleanups established
85 prior to here. */
86 new_catcher->saved_cleanup_chain = save_cleanups ();
87
88 /* Push this new catcher on the top. */
89 new_catcher->prev = current_catcher;
90 current_catcher = new_catcher;
91 new_catcher->state = CATCHER_CREATED;
92
93 return &new_catcher->buf;
94}
95
96static void
97catcher_pop (void)
98{
99 struct catcher *old_catcher = current_catcher;
100
101 current_catcher = old_catcher->prev;
102
103 /* Restore the cleanup chain, the error/quit messages, and the uiout
104 builder, to their original states. */
105
106 restore_cleanups (old_catcher->saved_cleanup_chain);
107
108 xfree (old_catcher);
109}
110
111/* Catcher state machine. Returns non-zero if the m/c should be run
112 again, zero if it should abort. */
113
114static int
115exceptions_state_mc (enum catcher_action action)
116{
117 switch (current_catcher->state)
118 {
119 case CATCHER_CREATED:
120 switch (action)
121 {
122 case CATCH_ITER:
123 /* Allow the code to run the catcher. */
124 current_catcher->state = CATCHER_RUNNING;
125 return 1;
126 default:
127 internal_error (__FILE__, __LINE__, _("bad state"));
128 }
129 case CATCHER_RUNNING:
130 switch (action)
131 {
132 case CATCH_ITER:
492d29ea 133 /* No error/quit has occured. */
ff55e1b5
GB
134 return 0;
135 case CATCH_ITER_1:
136 current_catcher->state = CATCHER_RUNNING_1;
137 return 1;
138 case CATCH_THROWING:
139 current_catcher->state = CATCHER_ABORTING;
140 /* See also throw_exception. */
141 return 1;
142 default:
143 internal_error (__FILE__, __LINE__, _("bad switch"));
144 }
145 case CATCHER_RUNNING_1:
146 switch (action)
147 {
148 case CATCH_ITER:
149 /* The did a "break" from the inner while loop. */
ff55e1b5
GB
150 return 0;
151 case CATCH_ITER_1:
152 current_catcher->state = CATCHER_RUNNING;
153 return 0;
154 case CATCH_THROWING:
155 current_catcher->state = CATCHER_ABORTING;
156 /* See also throw_exception. */
157 return 1;
158 default:
159 internal_error (__FILE__, __LINE__, _("bad switch"));
160 }
161 case CATCHER_ABORTING:
162 switch (action)
163 {
164 case CATCH_ITER:
165 {
492d29ea
PA
166 /* Exit normally if this catcher can handle this
167 exception. The caller analyses the func return
168 values. */
169 return 0;
ff55e1b5
GB
170 }
171 default:
172 internal_error (__FILE__, __LINE__, _("bad state"));
173 }
174 default:
175 internal_error (__FILE__, __LINE__, _("bad switch"));
176 }
177}
178
492d29ea
PA
179int
180exceptions_state_mc_catch (struct gdb_exception *exception,
181 int mask)
182{
183 *exception = current_catcher->exception;
184 catcher_pop ();
185
186 if (exception->reason < 0)
187 {
188 if (mask & RETURN_MASK (exception->reason))
189 {
72df25b2 190 /* Exit normally and let the caller handle the
492d29ea
PA
191 exception. */
192 return 1;
193 }
194
195 /* The caller didn't request that the event be caught, relay the
196 event to the next exception_catch/CATCH. */
197 throw_exception (*exception);
198 }
199
200 /* No exception was thrown. */
201 return 0;
202}
203
ff55e1b5
GB
204int
205exceptions_state_mc_action_iter (void)
206{
207 return exceptions_state_mc (CATCH_ITER);
208}
209
210int
211exceptions_state_mc_action_iter_1 (void)
212{
213 return exceptions_state_mc (CATCH_ITER_1);
214}
215
eec461d0 216#else /* !GDB_XCPT_SJMP */
72df25b2
PA
217
218/* How many nested TRY blocks we have. See exception_messages and
219 throw_it. */
220
221static int try_scope_depth;
222
223/* Called on entry to a TRY scope. */
224
225void *
226exception_try_scope_entry (void)
227{
228 ++try_scope_depth;
229 return (void *) save_cleanups ();
230}
231
232/* Called on exit of a TRY scope, either normal exit or exception
233 exit. */
234
235void
236exception_try_scope_exit (void *saved_state)
237{
238 restore_cleanups ((struct cleanup *) saved_state);
239 --try_scope_depth;
240}
241
242/* Called by the default catch block. IOW, we'll get here before
243 jumping out to the next outermost scope an exception if a GDB
244 exception is not caught. */
245
246void
247exception_rethrow (void)
248{
249 /* Run this scope's cleanups before re-throwing to the next
250 outermost scope. */
72df25b2
PA
251 do_cleanups (all_cleanups ());
252 throw;
253}
254
255/* Copy the 'gdb_exception' portion of FROM to TO. */
256
257static void
258gdb_exception_sliced_copy (struct gdb_exception *to, const struct gdb_exception *from)
259{
260 *to = *from;
261}
262
eec461d0 263#endif /* !GDB_XCPT_SJMP */
72df25b2 264
ff55e1b5
GB
265/* Return EXCEPTION to the nearest containing catch_errors(). */
266
267void
268throw_exception (struct gdb_exception exception)
269{
ff55e1b5
GB
270 do_cleanups (all_cleanups ());
271
eec461d0 272#if GDB_XCPT == GDB_XCPT_SJMP
ff55e1b5
GB
273 /* Jump to the containing catch_errors() call, communicating REASON
274 to that call via setjmp's return value. Note that REASON can't
275 be zero, by definition in defs.h. */
276 exceptions_state_mc (CATCH_THROWING);
492d29ea 277 current_catcher->exception = exception;
ff55e1b5 278 SIGLONGJMP (current_catcher->buf, exception.reason);
72df25b2
PA
279#else
280 if (exception.reason == RETURN_QUIT)
281 {
282 gdb_exception_RETURN_MASK_QUIT ex;
283
284 gdb_exception_sliced_copy (&ex, &exception);
285 throw ex;
286 }
287 else if (exception.reason == RETURN_ERROR)
288 {
289 gdb_exception_RETURN_MASK_ERROR ex;
290
291 gdb_exception_sliced_copy (&ex, &exception);
292 throw ex;
293 }
294 else
295 gdb_assert_not_reached ("invalid return reason");
296#endif
ff55e1b5
GB
297}
298
299/* A stack of exception messages.
300 This is needed to handle nested calls to throw_it: we don't want to
301 xfree space for a message before it's used.
302 This can happen if we throw an exception during a cleanup:
303 An outer TRY_CATCH may have an exception message it wants to print,
304 but while doing cleanups further calls to throw_it are made.
305
306 This is indexed by the size of the current_catcher list.
307 It is a dynamically allocated array so that we don't care how deeply
308 GDB nests its TRY_CATCHs. */
309static char **exception_messages;
310
311/* The number of currently allocated entries in exception_messages. */
312static int exception_messages_size;
313
314static void ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 0)
315throw_it (enum return_reason reason, enum errors error, const char *fmt,
316 va_list ap)
317{
318 struct gdb_exception e;
319 char *new_message;
eec461d0 320#if GDB_XCPT == GDB_XCPT_SJMP
ff55e1b5 321 int depth = catcher_list_size ();
72df25b2
PA
322#else
323 int depth = try_scope_depth;
324#endif
ff55e1b5
GB
325
326 gdb_assert (depth > 0);
327
328 /* Note: The new message may use an old message's text. */
329 new_message = xstrvprintf (fmt, ap);
330
331 if (depth > exception_messages_size)
332 {
333 int old_size = exception_messages_size;
334
335 exception_messages_size = depth + 10;
8d749320
SM
336 exception_messages = XRESIZEVEC (char *, exception_messages,
337 exception_messages_size);
ff55e1b5
GB
338 memset (exception_messages + old_size, 0,
339 (exception_messages_size - old_size) * sizeof (char *));
340 }
341
342 xfree (exception_messages[depth - 1]);
343 exception_messages[depth - 1] = new_message;
344
345 /* Create the exception. */
346 e.reason = reason;
347 e.error = error;
348 e.message = new_message;
349
350 /* Throw the exception. */
351 throw_exception (e);
352}
353
354void
355throw_verror (enum errors error, const char *fmt, va_list ap)
356{
357 throw_it (RETURN_ERROR, error, fmt, ap);
358}
359
360void
361throw_vquit (const char *fmt, va_list ap)
362{
363 throw_it (RETURN_QUIT, GDB_NO_ERROR, fmt, ap);
364}
365
366void
367throw_error (enum errors error, const char *fmt, ...)
368{
369 va_list args;
370
371 va_start (args, fmt);
372 throw_verror (error, fmt, args);
373 va_end (args);
374}
375
376void
377throw_quit (const char *fmt, ...)
378{
379 va_list args;
380
381 va_start (args, fmt);
382 throw_vquit (fmt, args);
383 va_end (args);
384}
This page took 0.144978 seconds and 4 git commands to generate.