1 /* Everything about signal catchpoints, for GDB.
3 Copyright (C) 2011-2017 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"
34 #define INTERNAL_SIGNAL(x) ((x) == GDB_SIGNAL_TRAP || (x) == GDB_SIGNAL_INT)
36 typedef enum gdb_signal gdb_signal_type
;
38 DEF_VEC_I (gdb_signal_type
);
40 /* An instance of this type is used to represent a signal catchpoint.
41 A breakpoint is really of this type iff its ops pointer points to
42 SIGNAL_CATCHPOINT_OPS. */
44 struct signal_catchpoint
: public breakpoint
46 ~signal_catchpoint () override
;
48 /* Signal numbers used for the 'catch signal' feature. If no signal
49 has been specified for filtering, its value is NULL. Otherwise,
50 it holds a list of all signals to be caught. */
52 VEC (gdb_signal_type
) *signals_to_be_caught
;
54 /* If SIGNALS_TO_BE_CAUGHT is NULL, then all "ordinary" signals are
55 caught. If CATCH_ALL is non-zero, then internal signals are
56 caught as well. If SIGNALS_TO_BE_CAUGHT is non-NULL, then this
62 /* The breakpoint_ops structure to be used in signal catchpoints. */
64 static struct breakpoint_ops signal_catchpoint_ops
;
66 /* Count of each signal. */
68 static unsigned int *signal_catch_counts
;
72 /* A convenience wrapper for gdb_signal_to_name that returns the
73 integer value if the name is not known. */
76 signal_to_name_or_int (enum gdb_signal sig
)
78 const char *result
= gdb_signal_to_name (sig
);
80 if (strcmp (result
, "?") == 0)
81 result
= plongest (sig
);
88 /* signal_catchpoint destructor. */
90 signal_catchpoint::~signal_catchpoint ()
92 VEC_free (gdb_signal_type
, this->signals_to_be_caught
);
95 /* Implement the "insert_location" breakpoint_ops method for signal
99 signal_catchpoint_insert_location (struct bp_location
*bl
)
101 struct signal_catchpoint
*c
= (struct signal_catchpoint
*) bl
->owner
;
104 if (c
->signals_to_be_caught
!= NULL
)
106 gdb_signal_type iter
;
109 VEC_iterate (gdb_signal_type
, c
->signals_to_be_caught
, i
, iter
);
111 ++signal_catch_counts
[iter
];
115 for (i
= 0; i
< GDB_SIGNAL_LAST
; ++i
)
117 if (c
->catch_all
|| !INTERNAL_SIGNAL (i
))
118 ++signal_catch_counts
[i
];
122 signal_catch_update (signal_catch_counts
);
127 /* Implement the "remove_location" breakpoint_ops method for signal
131 signal_catchpoint_remove_location (struct bp_location
*bl
,
132 enum remove_bp_reason reason
)
134 struct signal_catchpoint
*c
= (struct signal_catchpoint
*) bl
->owner
;
137 if (c
->signals_to_be_caught
!= NULL
)
139 gdb_signal_type iter
;
142 VEC_iterate (gdb_signal_type
, c
->signals_to_be_caught
, i
, iter
);
145 gdb_assert (signal_catch_counts
[iter
] > 0);
146 --signal_catch_counts
[iter
];
151 for (i
= 0; i
< GDB_SIGNAL_LAST
; ++i
)
153 if (c
->catch_all
|| !INTERNAL_SIGNAL (i
))
155 gdb_assert (signal_catch_counts
[i
] > 0);
156 --signal_catch_counts
[i
];
161 signal_catch_update (signal_catch_counts
);
166 /* Implement the "breakpoint_hit" breakpoint_ops method for signal
170 signal_catchpoint_breakpoint_hit (const struct bp_location
*bl
,
171 struct address_space
*aspace
,
173 const struct target_waitstatus
*ws
)
175 const struct signal_catchpoint
*c
176 = (const struct signal_catchpoint
*) bl
->owner
;
177 gdb_signal_type signal_number
;
179 if (ws
->kind
!= TARGET_WAITKIND_STOPPED
)
182 signal_number
= ws
->value
.sig
;
184 /* If we are catching specific signals in this breakpoint, then we
185 must guarantee that the called signal is the same signal we are
187 if (c
->signals_to_be_caught
)
190 gdb_signal_type iter
;
193 VEC_iterate (gdb_signal_type
, c
->signals_to_be_caught
, i
, iter
);
195 if (signal_number
== iter
)
202 return c
->catch_all
|| !INTERNAL_SIGNAL (signal_number
);
205 /* Implement the "print_it" breakpoint_ops method for signal
208 static enum print_stop_action
209 signal_catchpoint_print_it (bpstat bs
)
211 struct breakpoint
*b
= bs
->breakpoint_at
;
213 struct target_waitstatus last
;
214 const char *signal_name
;
215 struct ui_out
*uiout
= current_uiout
;
217 get_last_target_status (&ptid
, &last
);
219 signal_name
= signal_to_name_or_int (last
.value
.sig
);
221 annotate_catchpoint (b
->number
);
222 maybe_print_thread_hit_breakpoint (uiout
);
224 printf_filtered (_("Catchpoint %d (signal %s), "), b
->number
, signal_name
);
226 return PRINT_SRC_AND_LOC
;
229 /* Implement the "print_one" breakpoint_ops method for signal
233 signal_catchpoint_print_one (struct breakpoint
*b
,
234 struct bp_location
**last_loc
)
236 struct signal_catchpoint
*c
= (struct signal_catchpoint
*) b
;
237 struct value_print_options opts
;
238 struct ui_out
*uiout
= current_uiout
;
240 get_user_print_options (&opts
);
242 /* Field 4, the address, is omitted (which makes the columns
243 not line up too nicely with the headers, but the effect
244 is relatively readable). */
245 if (opts
.addressprint
)
246 uiout
->field_skip ("addr");
249 if (c
->signals_to_be_caught
250 && VEC_length (gdb_signal_type
, c
->signals_to_be_caught
) > 1)
251 uiout
->text ("signals \"");
253 uiout
->text ("signal \"");
255 if (c
->signals_to_be_caught
)
258 gdb_signal_type iter
;
262 VEC_iterate (gdb_signal_type
, c
->signals_to_be_caught
, i
, iter
);
265 const char *name
= signal_to_name_or_int (iter
);
271 uiout
->field_string ("what", text
.c_str ());
274 uiout
->field_string ("what",
275 c
->catch_all
? "<any signal>" : "<standard signals>");
278 if (uiout
->is_mi_like_p ())
279 uiout
->field_string ("catch-type", "signal");
282 /* Implement the "print_mention" breakpoint_ops method for signal
286 signal_catchpoint_print_mention (struct breakpoint
*b
)
288 struct signal_catchpoint
*c
= (struct signal_catchpoint
*) b
;
290 if (c
->signals_to_be_caught
)
293 gdb_signal_type iter
;
295 if (VEC_length (gdb_signal_type
, c
->signals_to_be_caught
) > 1)
296 printf_filtered (_("Catchpoint %d (signals"), b
->number
);
298 printf_filtered (_("Catchpoint %d (signal"), b
->number
);
301 VEC_iterate (gdb_signal_type
, c
->signals_to_be_caught
, i
, iter
);
304 const char *name
= signal_to_name_or_int (iter
);
306 printf_filtered (" %s", name
);
308 printf_filtered (")");
310 else if (c
->catch_all
)
311 printf_filtered (_("Catchpoint %d (any signal)"), b
->number
);
313 printf_filtered (_("Catchpoint %d (standard signals)"), b
->number
);
316 /* Implement the "print_recreate" breakpoint_ops method for signal
320 signal_catchpoint_print_recreate (struct breakpoint
*b
, struct ui_file
*fp
)
322 struct signal_catchpoint
*c
= (struct signal_catchpoint
*) b
;
324 fprintf_unfiltered (fp
, "catch signal");
326 if (c
->signals_to_be_caught
)
329 gdb_signal_type iter
;
332 VEC_iterate (gdb_signal_type
, c
->signals_to_be_caught
, i
, iter
);
334 fprintf_unfiltered (fp
, " %s", signal_to_name_or_int (iter
));
336 else if (c
->catch_all
)
337 fprintf_unfiltered (fp
, " all");
338 fputc_unfiltered ('\n', fp
);
341 /* Implement the "explains_signal" breakpoint_ops method for signal
345 signal_catchpoint_explains_signal (struct breakpoint
*b
, enum gdb_signal sig
)
350 /* Create a new signal catchpoint. TEMPFLAG is true if this should be
351 a temporary catchpoint. FILTER is the list of signals to catch; it
352 can be NULL, meaning all signals. CATCH_ALL is a flag indicating
353 whether signals used internally by gdb should be caught; it is only
354 valid if FILTER is NULL. If FILTER is NULL and CATCH_ALL is zero,
355 then internal signals like SIGTRAP are not caught. */
358 create_signal_catchpoint (int tempflag
, VEC (gdb_signal_type
) *filter
,
361 struct signal_catchpoint
*c
;
362 struct gdbarch
*gdbarch
= get_current_arch ();
364 c
= new signal_catchpoint ();
365 init_catchpoint (c
, gdbarch
, tempflag
, NULL
, &signal_catchpoint_ops
);
366 c
->signals_to_be_caught
= filter
;
367 c
->catch_all
= catch_all
;
369 install_breakpoint (0, c
, 1);
373 /* Splits the argument using space as delimiter. Returns an xmalloc'd
374 filter list, or NULL if no filtering is required. */
376 static VEC (gdb_signal_type
) *
377 catch_signal_split_args (char *arg
, int *catch_all
)
379 VEC (gdb_signal_type
) *result
= NULL
;
380 struct cleanup
*cleanup
= make_cleanup (VEC_cleanup (gdb_signal_type
),
387 gdb_signal_type signal_number
;
388 char *one_arg
, *endptr
;
389 struct cleanup
*inner_cleanup
;
391 one_arg
= extract_arg (&arg
);
394 inner_cleanup
= make_cleanup (xfree
, one_arg
);
396 /* Check for the special flag "all". */
397 if (strcmp (one_arg
, "all") == 0)
399 arg
= skip_spaces (arg
);
400 if (*arg
!= '\0' || !first
)
401 error (_("'all' cannot be caught with other signals"));
403 gdb_assert (result
== NULL
);
404 do_cleanups (inner_cleanup
);
405 discard_cleanups (cleanup
);
411 /* Check if the user provided a signal name or a number. */
412 num
= (int) strtol (one_arg
, &endptr
, 0);
414 signal_number
= gdb_signal_from_command (num
);
417 signal_number
= gdb_signal_from_name (one_arg
);
418 if (signal_number
== GDB_SIGNAL_UNKNOWN
)
419 error (_("Unknown signal name '%s'."), one_arg
);
422 VEC_safe_push (gdb_signal_type
, result
, signal_number
);
423 do_cleanups (inner_cleanup
);
426 discard_cleanups (cleanup
);
430 /* Implement the "catch signal" command. */
433 catch_signal_command (char *arg
, int from_tty
,
434 struct cmd_list_element
*command
)
436 int tempflag
, catch_all
= 0;
437 VEC (gdb_signal_type
) *filter
;
439 tempflag
= get_cmd_context (command
) == CATCH_TEMPORARY
;
441 arg
= skip_spaces (arg
);
443 /* The allowed syntax is:
445 catch signal <name | number> [<name | number> ... <name | number>]
447 Let's check if there's a signal name. */
450 filter
= catch_signal_split_args (arg
, &catch_all
);
454 create_signal_catchpoint (tempflag
, filter
, catch_all
);
458 initialize_signal_catchpoint_ops (void)
460 struct breakpoint_ops
*ops
;
462 initialize_breakpoint_ops ();
464 ops
= &signal_catchpoint_ops
;
465 *ops
= base_breakpoint_ops
;
466 ops
->insert_location
= signal_catchpoint_insert_location
;
467 ops
->remove_location
= signal_catchpoint_remove_location
;
468 ops
->breakpoint_hit
= signal_catchpoint_breakpoint_hit
;
469 ops
->print_it
= signal_catchpoint_print_it
;
470 ops
->print_one
= signal_catchpoint_print_one
;
471 ops
->print_mention
= signal_catchpoint_print_mention
;
472 ops
->print_recreate
= signal_catchpoint_print_recreate
;
473 ops
->explains_signal
= signal_catchpoint_explains_signal
;
476 initialize_file_ftype _initialize_break_catch_sig
;
479 _initialize_break_catch_sig (void)
481 initialize_signal_catchpoint_ops ();
483 signal_catch_counts
= XCNEWVEC (unsigned int, GDB_SIGNAL_LAST
);
485 add_catch_command ("signal", _("\
486 Catch signals by their names and/or numbers.\n\
487 Usage: catch signal [[NAME|NUMBER] [NAME|NUMBER]...|all]\n\
488 Arguments say which signals to catch. If no arguments\n\
489 are given, every \"normal\" signal will be caught.\n\
490 The argument \"all\" means to also catch signals used by GDB.\n\
491 Arguments, if given, should be one or more signal names\n\
492 (if your system supports that), or signal numbers."),
493 catch_signal_command
,