2005-01-13 Andrew Cagney <cagney@gnu.org>
[deliverable/binutils-gdb.git] / gdb / exceptions.c
CommitLineData
60250e8b
AC
1/* Exception (throw catch) mechanism, for GDB, the GNU debugger.
2
3 Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
4 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
5 Foundation, Inc.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
24#include "defs.h"
25#include "exceptions.h"
26#include <setjmp.h>
27#include "breakpoint.h"
28#include "target.h"
29#include "inferior.h"
30#include "annotate.h"
31#include "ui-out.h"
32#include "gdb_assert.h"
db5f402d 33#include "gdb_string.h"
60250e8b 34
c1043fc2
AC
35const struct exception exception_none = { 0, NO_ERROR, NULL };
36
60250e8b
AC
37/* One should use catch_errors rather than manipulating these
38 directly. */
39#if defined(HAVE_SIGSETJMP)
40#define SIGJMP_BUF sigjmp_buf
41#define SIGSETJMP(buf) sigsetjmp((buf), 1)
42#define SIGLONGJMP(buf,val) siglongjmp((buf), (val))
43#else
44#define SIGJMP_BUF jmp_buf
45#define SIGSETJMP(buf) setjmp(buf)
46#define SIGLONGJMP(buf,val) longjmp((buf), (val))
47#endif
48
db5f402d
AC
49/* Possible catcher states. */
50enum catcher_state {
51 /* Initial state, a new catcher has just been created. */
52 CATCHER_CREATED,
53 /* The catch code is running. */
54 CATCHER_RUNNING,
55 CATCHER_RUNNING_1,
56 /* The catch code threw an exception. */
57 CATCHER_ABORTING
58};
59
60/* Possible catcher actions. */
61enum catcher_action {
62 CATCH_ITER,
63 CATCH_ITER_1,
64 CATCH_THROWING
65};
66
67struct catcher
68{
69 enum catcher_state state;
2a78bfb5 70 /* Jump buffer pointing back at the exception handler. */
db5f402d 71 SIGJMP_BUF buf;
2a78bfb5
AC
72 /* Status buffer belonging to that exception handler. */
73 volatile struct exception *exception;
db5f402d
AC
74 /* Saved/current state. */
75 int mask;
76 char *saved_error_pre_print;
77 char *saved_quit_pre_print;
78 struct ui_out *saved_uiout;
79 struct cleanup *saved_cleanup_chain;
db5f402d
AC
80 /* Back link. */
81 struct catcher *prev;
82};
83
60250e8b 84/* Where to go for throw_exception(). */
db5f402d
AC
85static struct catcher *current_catcher;
86
87static SIGJMP_BUF *
88catcher_init (struct ui_out *func_uiout,
89 char *errstring,
2a78bfb5 90 volatile struct exception *exception,
db5f402d
AC
91 return_mask mask)
92{
93 struct catcher *new_catcher = XZALLOC (struct catcher);
94
2a78bfb5
AC
95 /* Start with no exception, save it's address. */
96 exception->reason = 0;
97 exception->error = NO_ERROR;
98 exception->message = NULL;
99 new_catcher->exception = exception;
100
db5f402d
AC
101 new_catcher->mask = mask;
102
103 /* Override error/quit messages during FUNC. */
104 new_catcher->saved_error_pre_print = error_pre_print;
105 new_catcher->saved_quit_pre_print = quit_pre_print;
106 if (mask & RETURN_MASK_ERROR)
107 error_pre_print = errstring;
108 if (mask & RETURN_MASK_QUIT)
109 quit_pre_print = errstring;
110
111 /* Override the global ``struct ui_out'' builder. */
112 new_catcher->saved_uiout = uiout;
113 uiout = func_uiout;
114
115 /* Prevent error/quit during FUNC from calling cleanups established
116 prior to here. */
117 new_catcher->saved_cleanup_chain = save_cleanups ();
118
119 /* Push this new catcher on the top. */
120 new_catcher->prev = current_catcher;
121 current_catcher = new_catcher;
122 new_catcher->state = CATCHER_CREATED;
123
124 return &new_catcher->buf;
125}
126
127static void
128catcher_pop (void)
129{
130 struct catcher *old_catcher = current_catcher;
131 current_catcher = old_catcher->prev;
132
133 /* Restore the cleanup chain, the error/quit messages, and the uiout
134 builder, to their original states. */
135
136 restore_cleanups (old_catcher->saved_cleanup_chain);
137
138 uiout = old_catcher->saved_uiout;
139
140 quit_pre_print = old_catcher->saved_quit_pre_print;
141 error_pre_print = old_catcher->saved_error_pre_print;
142
143 xfree (old_catcher);
144}
145
146/* Catcher state machine. Returns non-zero if the m/c should be run
147 again, zero if it should abort. */
148
149int
150catcher_state_machine (enum catcher_action action)
151{
152 switch (current_catcher->state)
153 {
154 case CATCHER_CREATED:
155 switch (action)
156 {
157 case CATCH_ITER:
158 /* Allow the code to run the catcher. */
159 current_catcher->state = CATCHER_RUNNING;
160 return 1;
161 default:
162 internal_error (__FILE__, __LINE__, "bad state");
163 }
164 case CATCHER_RUNNING:
165 switch (action)
166 {
167 case CATCH_ITER:
168 /* No error/quit has occured. Just clean up. */
169 catcher_pop ();
170 return 0;
171 case CATCH_ITER_1:
172 current_catcher->state = CATCHER_RUNNING_1;
173 return 1;
174 case CATCH_THROWING:
175 current_catcher->state = CATCHER_ABORTING;
176 /* See also throw_exception. */
177 return 1;
178 default:
179 internal_error (__FILE__, __LINE__, "bad switch");
180 }
181 case CATCHER_RUNNING_1:
182 switch (action)
183 {
184 case CATCH_ITER:
185 /* The did a "break" from the inner while loop. */
186 catcher_pop ();
187 return 0;
188 case CATCH_ITER_1:
189 current_catcher->state = CATCHER_RUNNING;
190 return 0;
191 case CATCH_THROWING:
192 current_catcher->state = CATCHER_ABORTING;
193 /* See also throw_exception. */
194 return 1;
195 default:
196 internal_error (__FILE__, __LINE__, "bad switch");
197 }
198 case CATCHER_ABORTING:
199 switch (action)
200 {
201 case CATCH_ITER:
202 {
2a78bfb5
AC
203 struct exception exception = *current_catcher->exception;
204 if (current_catcher->mask & RETURN_MASK (exception.reason))
db5f402d
AC
205 {
206 /* Exit normally if this catcher can handle this
207 exception. The caller analyses the func return
208 values. */
209 catcher_pop ();
210 return 0;
211 }
212 /* The caller didn't request that the event be caught,
213 relay the event to the next containing
214 catch_errors(). */
215 catcher_pop ();
2a78bfb5 216 throw_exception (exception);
db5f402d
AC
217 }
218 default:
219 internal_error (__FILE__, __LINE__, "bad state");
220 }
221 default:
222 internal_error (__FILE__, __LINE__, "bad switch");
223 }
224}
60250e8b 225
2a78bfb5 226/* Return EXCEPTION to the nearest containing catch_errors(). */
60250e8b
AC
227
228NORETURN void
2a78bfb5 229throw_exception (struct exception exception)
60250e8b
AC
230{
231 quit_flag = 0;
232 immediate_quit = 0;
233
234 /* Perhaps it would be cleaner to do this via the cleanup chain (not sure
235 I can think of a reason why that is vital, though). */
236 bpstat_clear_actions (stop_bpstat); /* Clear queued breakpoint commands */
237
238 disable_current_display ();
239 do_cleanups (ALL_CLEANUPS);
240 if (target_can_async_p () && !target_executing)
241 do_exec_cleanups (ALL_CLEANUPS);
242 if (sync_execution)
243 do_exec_error_cleanups (ALL_CLEANUPS);
244
245 if (annotation_level > 1)
2a78bfb5 246 switch (exception.reason)
60250e8b
AC
247 {
248 case RETURN_QUIT:
249 annotate_quit ();
250 break;
251 case RETURN_ERROR:
2a78bfb5 252 /* Assume that these are all errors. */
60250e8b
AC
253 annotate_error ();
254 break;
2a78bfb5
AC
255 default:
256 internal_error (__FILE__, __LINE__, "Bad switch.");
60250e8b
AC
257 }
258
259 /* Jump to the containing catch_errors() call, communicating REASON
260 to that call via setjmp's return value. Note that REASON can't
261 be zero, by definition in defs.h. */
db5f402d 262 catcher_state_machine (CATCH_THROWING);
2a78bfb5
AC
263 *current_catcher->exception = exception;
264 SIGLONGJMP (current_catcher->buf, exception.reason);
265}
266
6b1b7650
AC
267static char *last_message;
268
2a78bfb5
AC
269NORETURN void
270throw_reason (enum return_reason reason)
271{
272 struct exception exception;
273 memset (&exception, 0, sizeof exception);
274
275 exception.reason = reason;
276 switch (reason)
277 {
278 case RETURN_QUIT:
279 break;
280 case RETURN_ERROR:
281 exception.error = GENERIC_ERROR;
6b1b7650 282 exception.message = last_message;
2a78bfb5
AC
283 break;
284 default:
285 internal_error (__FILE__, __LINE__, "bad switch");
286 }
287
288 throw_exception (exception);
60250e8b
AC
289}
290
6b1b7650
AC
291static void
292do_write (void *data, const char *buffer, long length_buffer)
293{
294 ui_file_write (data, buffer, length_buffer);
295}
296
297
298NORETURN static void
299print_and_throw (enum return_reason reason, enum errors error,
300 const char *prefix, const char *fmt,
301 va_list ap) ATTR_NORETURN;
302NORETURN static void
303print_and_throw (enum return_reason reason, enum errors error,
304 const char *prefix, const char *fmt, va_list ap)
305{
306 /* FIXME: cagney/2005-01-13: While xstrvprintf is simpler it alters
307 GDB's output. Instead of the message being printed
308 line-at-a-time the message comes out all at once. The problem is
309 that the MI testsuite is checks for line-at-a-time messages and
310 changing this behavior means updating the testsuite. */
311
312 struct exception e;
313 struct ui_file *tmp_stream;
314 long len;
315
316 /* Convert the message into a print stream. */
317 tmp_stream = mem_fileopen ();
318 make_cleanup_ui_file_delete (tmp_stream);
319 vfprintf_unfiltered (tmp_stream, fmt, ap);
320
321 /* Save the message. */
322 xfree (last_message);
323 last_message = ui_file_xstrdup (tmp_stream, &len);
324
325 if (deprecated_error_begin_hook)
326 deprecated_error_begin_hook ();
327
328 /* Write the message plus any pre_print to gdb_stderr. */
329 target_terminal_ours ();
330 wrap_here (""); /* Force out any buffered output */
331 gdb_flush (gdb_stdout);
332 annotate_error_begin ();
333 if (error_pre_print)
334 fputs_filtered (error_pre_print, gdb_stderr);
335 ui_file_put (tmp_stream, do_write, gdb_stderr);
336 fprintf_filtered (gdb_stderr, "\n");
337
338 /* Throw the exception. */
339 e.reason = reason;
340 e.error = error;
341 e.message = last_message;
342 throw_exception (e);
343}
344
345NORETURN void
346throw_verror (enum errors error, const char *fmt, va_list ap)
347{
348 print_and_throw (RETURN_ERROR, error, error_pre_print, fmt, ap);
349}
350
351NORETURN void
352throw_vfatal (const char *fmt, va_list ap)
353{
354 print_and_throw (RETURN_QUIT, NO_ERROR, quit_pre_print, fmt, ap);
355}
356
357NORETURN void
358throw_vsilent (const char *fmt, va_list ap)
359{
360 struct exception e;
361 e.reason = RETURN_ERROR;
362 e.error = GENERIC_ERROR;
363 xfree (last_message);
364 last_message = xstrvprintf (fmt, ap);
365 e.message = last_message;
366 throw_exception (e);
367}
368
60250e8b
AC
369/* Call FUNC() with args FUNC_UIOUT and FUNC_ARGS, catching any
370 errors. Set FUNC_CAUGHT to an ``enum return_reason'' if the
371 function is aborted (using throw_exception() or zero if the
372 function returns normally. Set FUNC_VAL to the value returned by
373 the function or 0 if the function was aborted.
374
375 Must not be called with immediate_quit in effect (bad things might
376 happen, say we got a signal in the middle of a memcpy to quit_return).
377 This is an OK restriction; with very few exceptions immediate_quit can
378 be replaced by judicious use of QUIT.
379
380 MASK specifies what to catch; it is normally set to
381 RETURN_MASK_ALL, if for no other reason than that the code which
382 calls catch_errors might not be set up to deal with a quit which
383 isn't caught. But if the code can deal with it, it generally
384 should be RETURN_MASK_ERROR, unless for some reason it is more
385 useful to abort only the portion of the operation inside the
386 catch_errors. Note that quit should return to the command line
387 fairly quickly, even if some further processing is being done. */
388
389/* MAYBE: cagney/1999-11-05: catch_errors() in conjunction with
390 error() et.al. could maintain a set of flags that indicate the the
391 current state of each of the longjmp buffers. This would give the
392 longjmp code the chance to detect a longjmp botch (before it gets
393 to longjmperror()). Prior to 1999-11-05 this wasn't possible as
394 code also randomly used a SET_TOP_LEVEL macro that directly
395 initialize the longjmp buffers. */
396
397/* MAYBE: cagney/1999-11-05: Should the catch_errors and cleanups code
398 be consolidated into a single file instead of being distributed
399 between utils.c and top.c? */
400
60250e8b
AC
401int
402catch_exceptions (struct ui_out *uiout,
403 catch_exceptions_ftype *func,
404 void *func_args,
405 char *errstring,
406 return_mask mask)
407{
db5f402d
AC
408 return catch_exceptions_with_msg (uiout, func, func_args, errstring,
409 NULL, mask);
60250e8b
AC
410}
411
2a78bfb5
AC
412struct exception
413catch_exception (struct ui_out *uiout,
414 catch_exception_ftype *func,
415 void *func_args,
416 return_mask mask)
417{
418 volatile struct exception exception;
419 SIGJMP_BUF *catch;
420 catch = catcher_init (uiout, NULL, &exception, mask);
421 for (SIGSETJMP ((*catch));
422 catcher_state_machine (CATCH_ITER);)
423 (*func) (uiout, func_args);
424 return exception;
425}
426
60250e8b
AC
427int
428catch_exceptions_with_msg (struct ui_out *uiout,
429 catch_exceptions_ftype *func,
430 void *func_args,
431 char *errstring,
432 char **gdberrmsg,
433 return_mask mask)
434{
2a78bfb5
AC
435 volatile struct exception exception;
436 volatile int val = 0;
437 SIGJMP_BUF *catch = catcher_init (uiout, errstring, &exception, mask);
438 for (SIGSETJMP ((*catch)); catcher_state_machine (CATCH_ITER);)
db5f402d 439 val = (*func) (uiout, func_args);
60250e8b 440 gdb_assert (val >= 0);
2a78bfb5
AC
441 gdb_assert (exception.reason <= 0);
442 if (exception.reason < 0)
443 {
444 /* If caller wants a copy of the low-level error message, make
445 one. This is used in the case of a silent error whereby the
446 caller may optionally want to issue the message. */
447 if (gdberrmsg != NULL)
6b1b7650
AC
448 {
449 if (exception.message != NULL)
450 *gdberrmsg = xstrdup (exception.message);
451 else
452 *gdberrmsg = NULL;
453 }
2a78bfb5
AC
454 return exception.reason;
455 }
60250e8b
AC
456 return val;
457}
458
60250e8b
AC
459int
460catch_errors (catch_errors_ftype *func, void *func_args, char *errstring,
461 return_mask mask)
462{
2a78bfb5
AC
463 volatile int val = 0;
464 volatile struct exception exception;
465 SIGJMP_BUF *catch = catcher_init (uiout, errstring, &exception, mask);
db5f402d
AC
466 /* This illustrates how it is possible to nest the mechanism and
467 hence catch "break". Of course this doesn't address the need to
468 also catch "return". */
2a78bfb5
AC
469 for (SIGSETJMP ((*catch)); catcher_state_machine (CATCH_ITER);)
470 val = func (func_args);
471 if (exception.reason != 0)
60250e8b
AC
472 return 0;
473 return val;
474}
475
476struct captured_command_args
477 {
478 catch_command_errors_ftype *command;
479 char *arg;
480 int from_tty;
481 };
482
483static int
484do_captured_command (void *data)
485{
486 struct captured_command_args *context = data;
487 context->command (context->arg, context->from_tty);
488 /* FIXME: cagney/1999-11-07: Technically this do_cleanups() call
489 isn't needed. Instead an assertion check could be made that
490 simply confirmed that the called function correctly cleaned up
491 after itself. Unfortunately, old code (prior to 1999-11-04) in
492 main.c was calling SET_TOP_LEVEL(), calling the command function,
493 and then *always* calling do_cleanups(). For the moment we
494 remain ``bug compatible'' with that old code.. */
495 do_cleanups (ALL_CLEANUPS);
496 return 1;
497}
498
499int
500catch_command_errors (catch_command_errors_ftype * command,
501 char *arg, int from_tty, return_mask mask)
502{
503 struct captured_command_args args;
504 args.command = command;
505 args.arg = arg;
506 args.from_tty = from_tty;
507 return catch_errors (do_captured_command, &args, "", mask);
508}
This page took 0.043695 seconds and 4 git commands to generate.