1 /* Everything about signal catchpoints, for GDB.
3 Copyright (C) 2011-2016 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/>. */
21 #include "arch-utils.h"
23 #include "breakpoint.h"
29 #include "cli/cli-utils.h"
30 #include "completer.h"
31 #include "gdb_obstack.h"
33 #define INTERNAL_SIGNAL(x) ((x) == GDB_SIGNAL_TRAP || (x) == GDB_SIGNAL_INT)
35 typedef enum gdb_signal gdb_signal_type;
37 DEF_VEC_I (gdb_signal_type);
39 /* An instance of this type is used to represent a signal catchpoint.
40 It includes a "struct breakpoint" as a kind of base class; users
41 downcast to "struct breakpoint *" when needed. A breakpoint is
42 really of this type iff its ops pointer points to
43 SIGNAL_CATCHPOINT_OPS. */
45 struct signal_catchpoint
49 struct breakpoint base;
51 /* Signal numbers used for the 'catch signal' feature. If no signal
52 has been specified for filtering, its value is NULL. Otherwise,
53 it holds a list of all signals to be caught. */
55 VEC (gdb_signal_type) *signals_to_be_caught;
57 /* If SIGNALS_TO_BE_CAUGHT is NULL, then all "ordinary" signals are
58 caught. If CATCH_ALL is non-zero, then internal signals are
59 caught as well. If SIGNALS_TO_BE_CAUGHT is non-NULL, then this
65 /* The breakpoint_ops structure to be used in signal catchpoints. */
67 static struct breakpoint_ops signal_catchpoint_ops;
69 /* Count of each signal. */
71 static unsigned int *signal_catch_counts;
75 /* A convenience wrapper for gdb_signal_to_name that returns the
76 integer value if the name is not known. */
79 signal_to_name_or_int (enum gdb_signal sig)
81 const char *result = gdb_signal_to_name (sig);
83 if (strcmp (result, "?") == 0)
84 result = plongest (sig);
91 /* Implement the "dtor" breakpoint_ops method for signal
95 signal_catchpoint_dtor (struct breakpoint *b)
97 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
99 VEC_free (gdb_signal_type, c->signals_to_be_caught);
101 base_breakpoint_ops.dtor (b);
104 /* Implement the "insert_location" breakpoint_ops method for signal
108 signal_catchpoint_insert_location (struct bp_location *bl)
110 struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
113 if (c->signals_to_be_caught != NULL)
115 gdb_signal_type iter;
118 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
120 ++signal_catch_counts[iter];
124 for (i = 0; i < GDB_SIGNAL_LAST; ++i)
126 if (c->catch_all || !INTERNAL_SIGNAL (i))
127 ++signal_catch_counts[i];
131 signal_catch_update (signal_catch_counts);
136 /* Implement the "remove_location" breakpoint_ops method for signal
140 signal_catchpoint_remove_location (struct bp_location *bl)
142 struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
145 if (c->signals_to_be_caught != NULL)
147 gdb_signal_type iter;
150 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
153 gdb_assert (signal_catch_counts[iter] > 0);
154 --signal_catch_counts[iter];
159 for (i = 0; i < GDB_SIGNAL_LAST; ++i)
161 if (c->catch_all || !INTERNAL_SIGNAL (i))
163 gdb_assert (signal_catch_counts[i] > 0);
164 --signal_catch_counts[i];
169 signal_catch_update (signal_catch_counts);
174 /* Implement the "breakpoint_hit" breakpoint_ops method for signal
178 signal_catchpoint_breakpoint_hit (const struct bp_location *bl,
179 struct address_space *aspace,
181 const struct target_waitstatus *ws)
183 const struct signal_catchpoint *c
184 = (const struct signal_catchpoint *) bl->owner;
185 gdb_signal_type signal_number;
187 if (ws->kind != TARGET_WAITKIND_STOPPED)
190 signal_number = ws->value.sig;
192 /* If we are catching specific signals in this breakpoint, then we
193 must guarantee that the called signal is the same signal we are
195 if (c->signals_to_be_caught)
198 gdb_signal_type iter;
201 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
203 if (signal_number == iter)
210 return c->catch_all || !INTERNAL_SIGNAL (signal_number);
213 /* Implement the "print_it" breakpoint_ops method for signal
216 static enum print_stop_action
217 signal_catchpoint_print_it (bpstat bs)
219 struct breakpoint *b = bs->breakpoint_at;
221 struct target_waitstatus last;
222 const char *signal_name;
223 struct ui_out *uiout = current_uiout;
225 get_last_target_status (&ptid, &last);
227 signal_name = signal_to_name_or_int (last.value.sig);
229 annotate_catchpoint (b->number);
230 maybe_print_thread_hit_breakpoint (uiout);
232 printf_filtered (_("Catchpoint %d (signal %s), "), b->number, signal_name);
234 return PRINT_SRC_AND_LOC;
237 /* Implement the "print_one" breakpoint_ops method for signal
241 signal_catchpoint_print_one (struct breakpoint *b,
242 struct bp_location **last_loc)
244 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
245 struct value_print_options opts;
246 struct ui_out *uiout = current_uiout;
248 get_user_print_options (&opts);
250 /* Field 4, the address, is omitted (which makes the columns
251 not line up too nicely with the headers, but the effect
252 is relatively readable). */
253 if (opts.addressprint)
254 ui_out_field_skip (uiout, "addr");
257 if (c->signals_to_be_caught
258 && VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
259 ui_out_text (uiout, "signals \"");
261 ui_out_text (uiout, "signal \"");
263 if (c->signals_to_be_caught)
266 gdb_signal_type iter;
268 struct cleanup *cleanup;
270 obstack_init (&text);
271 cleanup = make_cleanup_obstack_free (&text);
274 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
277 const char *name = signal_to_name_or_int (iter);
280 obstack_grow (&text, " ", 1);
281 obstack_grow (&text, name, strlen (name));
283 obstack_grow (&text, "", 1);
284 ui_out_field_string (uiout, "what", (const char *) obstack_base (&text));
285 do_cleanups (cleanup);
288 ui_out_field_string (uiout, "what",
289 c->catch_all ? "<any signal>" : "<standard signals>");
290 ui_out_text (uiout, "\" ");
292 if (ui_out_is_mi_like_p (uiout))
293 ui_out_field_string (uiout, "catch-type", "signal");
296 /* Implement the "print_mention" breakpoint_ops method for signal
300 signal_catchpoint_print_mention (struct breakpoint *b)
302 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
304 if (c->signals_to_be_caught)
307 gdb_signal_type iter;
309 if (VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
310 printf_filtered (_("Catchpoint %d (signals"), b->number);
312 printf_filtered (_("Catchpoint %d (signal"), b->number);
315 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
318 const char *name = signal_to_name_or_int (iter);
320 printf_filtered (" %s", name);
322 printf_filtered (")");
324 else if (c->catch_all)
325 printf_filtered (_("Catchpoint %d (any signal)"), b->number);
327 printf_filtered (_("Catchpoint %d (standard signals)"), b->number);
330 /* Implement the "print_recreate" breakpoint_ops method for signal
334 signal_catchpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
336 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
338 fprintf_unfiltered (fp, "catch signal");
340 if (c->signals_to_be_caught)
343 gdb_signal_type iter;
346 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
348 fprintf_unfiltered (fp, " %s", signal_to_name_or_int (iter));
350 else if (c->catch_all)
351 fprintf_unfiltered (fp, " all");
352 fputc_unfiltered ('\n', fp);
355 /* Implement the "explains_signal" breakpoint_ops method for signal
359 signal_catchpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
364 /* Create a new signal catchpoint. TEMPFLAG is true if this should be
365 a temporary catchpoint. FILTER is the list of signals to catch; it
366 can be NULL, meaning all signals. CATCH_ALL is a flag indicating
367 whether signals used internally by gdb should be caught; it is only
368 valid if FILTER is NULL. If FILTER is NULL and CATCH_ALL is zero,
369 then internal signals like SIGTRAP are not caught. */
372 create_signal_catchpoint (int tempflag, VEC (gdb_signal_type) *filter,
375 struct signal_catchpoint *c;
376 struct gdbarch *gdbarch = get_current_arch ();
378 c = XNEW (struct signal_catchpoint);
379 init_catchpoint (&c->base, gdbarch, tempflag, NULL, &signal_catchpoint_ops);
380 c->signals_to_be_caught = filter;
381 c->catch_all = catch_all;
383 install_breakpoint (0, &c->base, 1);
387 /* Splits the argument using space as delimiter. Returns an xmalloc'd
388 filter list, or NULL if no filtering is required. */
390 static VEC (gdb_signal_type) *
391 catch_signal_split_args (char *arg, int *catch_all)
393 VEC (gdb_signal_type) *result = NULL;
394 struct cleanup *cleanup = make_cleanup (VEC_cleanup (gdb_signal_type),
401 gdb_signal_type signal_number;
402 char *one_arg, *endptr;
403 struct cleanup *inner_cleanup;
405 one_arg = extract_arg (&arg);
408 inner_cleanup = make_cleanup (xfree, one_arg);
410 /* Check for the special flag "all". */
411 if (strcmp (one_arg, "all") == 0)
413 arg = skip_spaces (arg);
414 if (*arg != '\0' || !first)
415 error (_("'all' cannot be caught with other signals"));
417 gdb_assert (result == NULL);
418 do_cleanups (inner_cleanup);
419 discard_cleanups (cleanup);
425 /* Check if the user provided a signal name or a number. */
426 num = (int) strtol (one_arg, &endptr, 0);
428 signal_number = gdb_signal_from_command (num);
431 signal_number = gdb_signal_from_name (one_arg);
432 if (signal_number == GDB_SIGNAL_UNKNOWN)
433 error (_("Unknown signal name '%s'."), one_arg);
436 VEC_safe_push (gdb_signal_type, result, signal_number);
437 do_cleanups (inner_cleanup);
440 discard_cleanups (cleanup);
444 /* Implement the "catch signal" command. */
447 catch_signal_command (char *arg, int from_tty,
448 struct cmd_list_element *command)
450 int tempflag, catch_all = 0;
451 VEC (gdb_signal_type) *filter;
453 tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
455 arg = skip_spaces (arg);
457 /* The allowed syntax is:
459 catch signal <name | number> [<name | number> ... <name | number>]
461 Let's check if there's a signal name. */
464 filter = catch_signal_split_args (arg, &catch_all);
468 create_signal_catchpoint (tempflag, filter, catch_all);
472 initialize_signal_catchpoint_ops (void)
474 struct breakpoint_ops *ops;
476 initialize_breakpoint_ops ();
478 ops = &signal_catchpoint_ops;
479 *ops = base_breakpoint_ops;
480 ops->dtor = signal_catchpoint_dtor;
481 ops->insert_location = signal_catchpoint_insert_location;
482 ops->remove_location = signal_catchpoint_remove_location;
483 ops->breakpoint_hit = signal_catchpoint_breakpoint_hit;
484 ops->print_it = signal_catchpoint_print_it;
485 ops->print_one = signal_catchpoint_print_one;
486 ops->print_mention = signal_catchpoint_print_mention;
487 ops->print_recreate = signal_catchpoint_print_recreate;
488 ops->explains_signal = signal_catchpoint_explains_signal;
491 initialize_file_ftype _initialize_break_catch_sig;
494 _initialize_break_catch_sig (void)
496 initialize_signal_catchpoint_ops ();
498 signal_catch_counts = XCNEWVEC (unsigned int, GDB_SIGNAL_LAST);
500 add_catch_command ("signal", _("\
501 Catch signals by their names and/or numbers.\n\
502 Usage: catch signal [[NAME|NUMBER] [NAME|NUMBER]...|all]\n\
503 Arguments say which signals to catch. If no arguments\n\
504 are given, every \"normal\" signal will be caught.\n\
505 The argument \"all\" means to also catch signals used by GDB.\n\
506 Arguments, if given, should be one or more signal names\n\
507 (if your system supports that), or signal numbers."),
508 catch_signal_command,