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
= { 0, GDB_NO_ERROR
, NULL
};
25 /* Possible catcher states. */
27 /* Initial state, a new catcher has just been created. */
29 /* The catch code is running. */
32 /* The catch code threw an exception. */
36 /* Possible catcher actions. */
45 enum catcher_state state
;
46 /* Jump buffer pointing back at the exception handler. */
48 /* Status buffer belonging to the exception handler. */
49 struct gdb_exception exception
;
50 struct cleanup
*saved_cleanup_chain
;
55 /* Where to go for throw_exception(). */
56 static struct catcher
*current_catcher
;
58 /* Return length of current_catcher list. */
61 catcher_list_size (void)
64 struct catcher
*catcher
;
66 for (size
= 0, catcher
= current_catcher
;
68 catcher
= catcher
->prev
)
75 exceptions_state_mc_init (void)
77 struct catcher
*new_catcher
= XCNEW (struct catcher
);
79 /* Start with no exception. */
80 new_catcher
->exception
= exception_none
;
82 /* Prevent error/quit during FUNC from calling cleanups established
84 new_catcher
->saved_cleanup_chain
= save_cleanups ();
86 /* Push this new catcher on the top. */
87 new_catcher
->prev
= current_catcher
;
88 current_catcher
= new_catcher
;
89 new_catcher
->state
= CATCHER_CREATED
;
91 return &new_catcher
->buf
;
97 struct catcher
*old_catcher
= current_catcher
;
99 current_catcher
= old_catcher
->prev
;
101 /* Restore the cleanup chain, the error/quit messages, and the uiout
102 builder, to their original states. */
104 restore_cleanups (old_catcher
->saved_cleanup_chain
);
109 /* Catcher state machine. Returns non-zero if the m/c should be run
110 again, zero if it should abort. */
113 exceptions_state_mc (enum catcher_action action
)
115 switch (current_catcher
->state
)
117 case CATCHER_CREATED
:
121 /* Allow the code to run the catcher. */
122 current_catcher
->state
= CATCHER_RUNNING
;
125 internal_error (__FILE__
, __LINE__
, _("bad state"));
127 case CATCHER_RUNNING
:
131 /* No error/quit has occured. */
134 current_catcher
->state
= CATCHER_RUNNING_1
;
137 current_catcher
->state
= CATCHER_ABORTING
;
138 /* See also throw_exception. */
141 internal_error (__FILE__
, __LINE__
, _("bad switch"));
143 case CATCHER_RUNNING_1
:
147 /* The did a "break" from the inner while loop. */
150 current_catcher
->state
= CATCHER_RUNNING
;
153 current_catcher
->state
= CATCHER_ABORTING
;
154 /* See also throw_exception. */
157 internal_error (__FILE__
, __LINE__
, _("bad switch"));
159 case CATCHER_ABORTING
:
164 /* Exit normally if this catcher can handle this
165 exception. The caller analyses the func return
170 internal_error (__FILE__
, __LINE__
, _("bad state"));
173 internal_error (__FILE__
, __LINE__
, _("bad switch"));
178 exceptions_state_mc_catch (struct gdb_exception
*exception
,
181 *exception
= current_catcher
->exception
;
184 if (exception
->reason
< 0)
186 if (mask
& RETURN_MASK (exception
->reason
))
188 /* Exit normally and let the called handle the
193 /* The caller didn't request that the event be caught, relay the
194 event to the next exception_catch/CATCH. */
195 throw_exception (*exception
);
198 /* No exception was thrown. */
203 exceptions_state_mc_action_iter (void)
205 return exceptions_state_mc (CATCH_ITER
);
209 exceptions_state_mc_action_iter_1 (void)
211 return exceptions_state_mc (CATCH_ITER_1
);
214 /* Return EXCEPTION to the nearest containing catch_errors(). */
217 throw_exception (struct gdb_exception exception
)
219 prepare_to_throw_exception ();
221 do_cleanups (all_cleanups ());
223 /* Jump to the containing catch_errors() call, communicating REASON
224 to that call via setjmp's return value. Note that REASON can't
225 be zero, by definition in defs.h. */
226 exceptions_state_mc (CATCH_THROWING
);
227 current_catcher
->exception
= exception
;
228 SIGLONGJMP (current_catcher
->buf
, exception
.reason
);
231 /* A stack of exception messages.
232 This is needed to handle nested calls to throw_it: we don't want to
233 xfree space for a message before it's used.
234 This can happen if we throw an exception during a cleanup:
235 An outer TRY_CATCH may have an exception message it wants to print,
236 but while doing cleanups further calls to throw_it are made.
238 This is indexed by the size of the current_catcher list.
239 It is a dynamically allocated array so that we don't care how deeply
240 GDB nests its TRY_CATCHs. */
241 static char **exception_messages
;
243 /* The number of currently allocated entries in exception_messages. */
244 static int exception_messages_size
;
246 static void ATTRIBUTE_NORETURN
ATTRIBUTE_PRINTF (3, 0)
247 throw_it (enum return_reason reason
, enum errors error
, const char *fmt
,
250 struct gdb_exception e
;
252 int depth
= catcher_list_size ();
254 gdb_assert (depth
> 0);
256 /* Note: The new message may use an old message's text. */
257 new_message
= xstrvprintf (fmt
, ap
);
259 if (depth
> exception_messages_size
)
261 int old_size
= exception_messages_size
;
263 exception_messages_size
= depth
+ 10;
264 exception_messages
= (char **) xrealloc (exception_messages
,
265 exception_messages_size
267 memset (exception_messages
+ old_size
, 0,
268 (exception_messages_size
- old_size
) * sizeof (char *));
271 xfree (exception_messages
[depth
- 1]);
272 exception_messages
[depth
- 1] = new_message
;
274 /* Create the exception. */
277 e
.message
= new_message
;
279 /* Throw the exception. */
284 throw_verror (enum errors error
, const char *fmt
, va_list ap
)
286 throw_it (RETURN_ERROR
, error
, fmt
, ap
);
290 throw_vquit (const char *fmt
, va_list ap
)
292 throw_it (RETURN_QUIT
, GDB_NO_ERROR
, fmt
, ap
);
296 throw_error (enum errors error
, const char *fmt
, ...)
300 va_start (args
, fmt
);
301 throw_verror (error
, fmt
, args
);
306 throw_quit (const char *fmt
, ...)
310 va_start (args
, fmt
);
311 throw_vquit (fmt
, args
);