1 /* Exception (throw catch) mechanism, for GDB, the GNU debugger.
3 Copyright (C) 1986-2015 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
20 #include "common-defs.h"
21 #include "common-exceptions.h"
23 const struct gdb_exception exception_none = { (enum return_reason) 0, GDB_NO_ERROR, NULL };
27 /* Possible catcher states. */
29 /* Initial state, a new catcher has just been created. */
31 /* The catch code is running. */
34 /* The catch code threw an exception. */
38 /* Possible catcher actions. */
47 enum catcher_state state;
48 /* Jump buffer pointing back at the exception handler. */
50 /* Status buffer belonging to the exception handler. */
51 struct gdb_exception exception;
52 struct cleanup *saved_cleanup_chain;
57 /* Where to go for throw_exception(). */
58 static struct catcher *current_catcher;
60 /* Return length of current_catcher list. */
63 catcher_list_size (void)
66 struct catcher *catcher;
68 for (size = 0, catcher = current_catcher;
70 catcher = catcher->prev)
77 exceptions_state_mc_init (void)
79 struct catcher *new_catcher = XCNEW (struct catcher);
81 /* Start with no exception. */
82 new_catcher->exception = exception_none;
84 /* Prevent error/quit during FUNC from calling cleanups established
86 new_catcher->saved_cleanup_chain = save_cleanups ();
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;
93 return &new_catcher->buf;
99 struct catcher *old_catcher = current_catcher;
101 current_catcher = old_catcher->prev;
103 /* Restore the cleanup chain, the error/quit messages, and the uiout
104 builder, to their original states. */
106 restore_cleanups (old_catcher->saved_cleanup_chain);
111 /* Catcher state machine. Returns non-zero if the m/c should be run
112 again, zero if it should abort. */
115 exceptions_state_mc (enum catcher_action action)
117 switch (current_catcher->state)
119 case CATCHER_CREATED:
123 /* Allow the code to run the catcher. */
124 current_catcher->state = CATCHER_RUNNING;
127 internal_error (__FILE__, __LINE__, _("bad state"));
129 case CATCHER_RUNNING:
133 /* No error/quit has occured. */
136 current_catcher->state = CATCHER_RUNNING_1;
139 current_catcher->state = CATCHER_ABORTING;
140 /* See also throw_exception. */
143 internal_error (__FILE__, __LINE__, _("bad switch"));
145 case CATCHER_RUNNING_1:
149 /* The did a "break" from the inner while loop. */
152 current_catcher->state = CATCHER_RUNNING;
155 current_catcher->state = CATCHER_ABORTING;
156 /* See also throw_exception. */
159 internal_error (__FILE__, __LINE__, _("bad switch"));
161 case CATCHER_ABORTING:
166 /* Exit normally if this catcher can handle this
167 exception. The caller analyses the func return
172 internal_error (__FILE__, __LINE__, _("bad state"));
175 internal_error (__FILE__, __LINE__, _("bad switch"));
180 exceptions_state_mc_catch (struct gdb_exception *exception,
183 *exception = current_catcher->exception;
186 if (exception->reason < 0)
188 if (mask & RETURN_MASK (exception->reason))
190 /* Exit normally and let the caller handle the
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);
200 /* No exception was thrown. */
205 exceptions_state_mc_action_iter (void)
207 return exceptions_state_mc (CATCH_ITER);
211 exceptions_state_mc_action_iter_1 (void)
213 return exceptions_state_mc (CATCH_ITER_1);
216 #else /* !__cplusplus */
218 /* How many nested TRY blocks we have. See exception_messages and
221 static int try_scope_depth;
223 /* Called on entry to a TRY scope. */
226 exception_try_scope_entry (void)
229 return (void *) save_cleanups ();
232 /* Called on exit of a TRY scope, either normal exit or exception
236 exception_try_scope_exit (void *saved_state)
238 restore_cleanups ((struct cleanup *) saved_state);
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. */
247 exception_rethrow (void)
249 /* Run this scope's cleanups before re-throwing to the next
251 prepare_to_throw_exception ();
252 do_cleanups (all_cleanups ());
256 /* Copy the 'gdb_exception' portion of FROM to TO. */
259 gdb_exception_sliced_copy (struct gdb_exception *to, const struct gdb_exception *from)
264 #endif /* !__cplusplus */
266 /* Return EXCEPTION to the nearest containing catch_errors(). */
269 throw_exception (struct gdb_exception exception)
271 prepare_to_throw_exception ();
273 do_cleanups (all_cleanups ());
276 /* Jump to the containing catch_errors() call, communicating REASON
277 to that call via setjmp's return value. Note that REASON can't
278 be zero, by definition in defs.h. */
279 exceptions_state_mc (CATCH_THROWING);
280 current_catcher->exception = exception;
281 SIGLONGJMP (current_catcher->buf, exception.reason);
283 if (exception.reason == RETURN_QUIT)
285 gdb_exception_RETURN_MASK_QUIT ex;
287 gdb_exception_sliced_copy (&ex, &exception);
290 else if (exception.reason == RETURN_ERROR)
292 gdb_exception_RETURN_MASK_ERROR ex;
294 gdb_exception_sliced_copy (&ex, &exception);
298 gdb_assert_not_reached ("invalid return reason");
302 /* A stack of exception messages.
303 This is needed to handle nested calls to throw_it: we don't want to
304 xfree space for a message before it's used.
305 This can happen if we throw an exception during a cleanup:
306 An outer TRY_CATCH may have an exception message it wants to print,
307 but while doing cleanups further calls to throw_it are made.
309 This is indexed by the size of the current_catcher list.
310 It is a dynamically allocated array so that we don't care how deeply
311 GDB nests its TRY_CATCHs. */
312 static char **exception_messages;
314 /* The number of currently allocated entries in exception_messages. */
315 static int exception_messages_size;
317 static void ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 0)
318 throw_it (enum return_reason reason, enum errors error, const char *fmt,
321 struct gdb_exception e;
324 int depth = catcher_list_size ();
326 int depth = try_scope_depth;
329 gdb_assert (depth > 0);
331 /* Note: The new message may use an old message's text. */
332 new_message = xstrvprintf (fmt, ap);
334 if (depth > exception_messages_size)
336 int old_size = exception_messages_size;
338 exception_messages_size = depth + 10;
339 exception_messages = XRESIZEVEC (char *, exception_messages,
340 exception_messages_size);
341 memset (exception_messages + old_size, 0,
342 (exception_messages_size - old_size) * sizeof (char *));
345 xfree (exception_messages[depth - 1]);
346 exception_messages[depth - 1] = new_message;
348 /* Create the exception. */
351 e.message = new_message;
353 /* Throw the exception. */
358 throw_verror (enum errors error, const char *fmt, va_list ap)
360 throw_it (RETURN_ERROR, error, fmt, ap);
364 throw_vquit (const char *fmt, va_list ap)
366 throw_it (RETURN_QUIT, GDB_NO_ERROR, fmt, ap);
370 throw_error (enum errors error, const char *fmt, ...)
374 va_start (args, fmt);
375 throw_verror (error, fmt, args);
380 throw_quit (const char *fmt, ...)
384 va_start (args, fmt);
385 throw_vquit (fmt, args);