1 /* Everything about signal catchpoints, for GDB.
3 Copyright (C) 2011-2019 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/>. */
22 /* Standard C includes. */
25 /* Standard C++ includes. */
28 /* Local non-gdb includes. */
30 #include "arch-utils.h"
31 #include "breakpoint.h"
32 #include "cli/cli-utils.h"
33 #include "completer.h"
39 #define INTERNAL_SIGNAL(x) ((x) == GDB_SIGNAL_TRAP || (x) == GDB_SIGNAL_INT)
41 /* An instance of this type is used to represent a signal catchpoint.
42 A breakpoint is really of this type iff its ops pointer points to
43 SIGNAL_CATCHPOINT_OPS. */
45 struct signal_catchpoint
: public breakpoint
47 /* Signal numbers used for the 'catch signal' feature. If no signal
48 has been specified for filtering, it is empty. Otherwise,
49 it holds a list of all signals to be caught. */
51 std::vector
<gdb_signal
> signals_to_be_caught
;
53 /* If SIGNALS_TO_BE_CAUGHT is empty, then all "ordinary" signals are
54 caught. If CATCH_ALL is true, then internal signals are caught
55 as well. If SIGNALS_TO_BE_CAUGHT is not empty, then this field
61 /* The breakpoint_ops structure to be used in signal catchpoints. */
63 static struct breakpoint_ops signal_catchpoint_ops
;
65 /* Count of each signal. */
67 static unsigned int *signal_catch_counts
;
71 /* A convenience wrapper for gdb_signal_to_name that returns the
72 integer value if the name is not known. */
75 signal_to_name_or_int (enum gdb_signal sig
)
77 const char *result
= gdb_signal_to_name (sig
);
79 if (strcmp (result
, "?") == 0)
80 result
= plongest (sig
);
87 /* Implement the "insert_location" breakpoint_ops method for signal
91 signal_catchpoint_insert_location (struct bp_location
*bl
)
93 struct signal_catchpoint
*c
= (struct signal_catchpoint
*) bl
->owner
;
95 if (!c
->signals_to_be_caught
.empty ())
97 for (gdb_signal iter
: c
->signals_to_be_caught
)
98 ++signal_catch_counts
[iter
];
102 for (int i
= 0; i
< GDB_SIGNAL_LAST
; ++i
)
104 if (c
->catch_all
|| !INTERNAL_SIGNAL (i
))
105 ++signal_catch_counts
[i
];
109 signal_catch_update (signal_catch_counts
);
114 /* Implement the "remove_location" breakpoint_ops method for signal
118 signal_catchpoint_remove_location (struct bp_location
*bl
,
119 enum remove_bp_reason reason
)
121 struct signal_catchpoint
*c
= (struct signal_catchpoint
*) bl
->owner
;
123 if (!c
->signals_to_be_caught
.empty ())
125 for (gdb_signal iter
: c
->signals_to_be_caught
)
127 gdb_assert (signal_catch_counts
[iter
] > 0);
128 --signal_catch_counts
[iter
];
133 for (int i
= 0; i
< GDB_SIGNAL_LAST
; ++i
)
135 if (c
->catch_all
|| !INTERNAL_SIGNAL (i
))
137 gdb_assert (signal_catch_counts
[i
] > 0);
138 --signal_catch_counts
[i
];
143 signal_catch_update (signal_catch_counts
);
148 /* Implement the "breakpoint_hit" breakpoint_ops method for signal
152 signal_catchpoint_breakpoint_hit (const struct bp_location
*bl
,
153 const address_space
*aspace
,
155 const struct target_waitstatus
*ws
)
157 const struct signal_catchpoint
*c
158 = (const struct signal_catchpoint
*) bl
->owner
;
159 gdb_signal signal_number
;
161 if (ws
->kind
!= TARGET_WAITKIND_STOPPED
)
164 signal_number
= ws
->value
.sig
;
166 /* If we are catching specific signals in this breakpoint, then we
167 must guarantee that the called signal is the same signal we are
169 if (!c
->signals_to_be_caught
.empty ())
171 for (gdb_signal iter
: c
->signals_to_be_caught
)
172 if (signal_number
== iter
)
178 return c
->catch_all
|| !INTERNAL_SIGNAL (signal_number
);
181 /* Implement the "print_it" breakpoint_ops method for signal
184 static enum print_stop_action
185 signal_catchpoint_print_it (bpstat bs
)
187 struct breakpoint
*b
= bs
->breakpoint_at
;
189 struct target_waitstatus last
;
190 const char *signal_name
;
191 struct ui_out
*uiout
= current_uiout
;
193 get_last_target_status (&ptid
, &last
);
195 signal_name
= signal_to_name_or_int (last
.value
.sig
);
197 annotate_catchpoint (b
->number
);
198 maybe_print_thread_hit_breakpoint (uiout
);
200 printf_filtered (_("Catchpoint %d (signal %s), "), b
->number
, signal_name
);
202 return PRINT_SRC_AND_LOC
;
205 /* Implement the "print_one" breakpoint_ops method for signal
209 signal_catchpoint_print_one (struct breakpoint
*b
,
210 struct bp_location
**last_loc
)
212 struct signal_catchpoint
*c
= (struct signal_catchpoint
*) b
;
213 struct value_print_options opts
;
214 struct ui_out
*uiout
= current_uiout
;
216 get_user_print_options (&opts
);
218 /* Field 4, the address, is omitted (which makes the columns
219 not line up too nicely with the headers, but the effect
220 is relatively readable). */
221 if (opts
.addressprint
)
222 uiout
->field_skip ("addr");
225 if (c
->signals_to_be_caught
.size () > 1)
226 uiout
->text ("signals \"");
228 uiout
->text ("signal \"");
230 if (!c
->signals_to_be_caught
.empty ())
235 for (gdb_signal iter
: c
->signals_to_be_caught
)
237 const char *name
= signal_to_name_or_int (iter
);
245 uiout
->field_string ("what", text
.c_str ());
248 uiout
->field_string ("what",
249 c
->catch_all
? "<any signal>" : "<standard signals>");
252 if (uiout
->is_mi_like_p ())
253 uiout
->field_string ("catch-type", "signal");
256 /* Implement the "print_mention" breakpoint_ops method for signal
260 signal_catchpoint_print_mention (struct breakpoint
*b
)
262 struct signal_catchpoint
*c
= (struct signal_catchpoint
*) b
;
264 if (!c
->signals_to_be_caught
.empty ())
266 if (c
->signals_to_be_caught
.size () > 1)
267 printf_filtered (_("Catchpoint %d (signals"), b
->number
);
269 printf_filtered (_("Catchpoint %d (signal"), b
->number
);
271 for (gdb_signal iter
: c
->signals_to_be_caught
)
273 const char *name
= signal_to_name_or_int (iter
);
275 printf_filtered (" %s", name
);
277 printf_filtered (")");
279 else if (c
->catch_all
)
280 printf_filtered (_("Catchpoint %d (any signal)"), b
->number
);
282 printf_filtered (_("Catchpoint %d (standard signals)"), b
->number
);
285 /* Implement the "print_recreate" breakpoint_ops method for signal
289 signal_catchpoint_print_recreate (struct breakpoint
*b
, struct ui_file
*fp
)
291 struct signal_catchpoint
*c
= (struct signal_catchpoint
*) b
;
293 fprintf_unfiltered (fp
, "catch signal");
295 if (!c
->signals_to_be_caught
.empty ())
297 for (gdb_signal iter
: c
->signals_to_be_caught
)
298 fprintf_unfiltered (fp
, " %s", signal_to_name_or_int (iter
));
300 else if (c
->catch_all
)
301 fprintf_unfiltered (fp
, " all");
302 fputc_unfiltered ('\n', fp
);
305 /* Implement the "explains_signal" breakpoint_ops method for signal
309 signal_catchpoint_explains_signal (struct breakpoint
*b
, enum gdb_signal sig
)
314 /* Create a new signal catchpoint. TEMPFLAG is true if this should be
315 a temporary catchpoint. FILTER is the list of signals to catch; it
316 can be empty, meaning all signals. CATCH_ALL is a flag indicating
317 whether signals used internally by gdb should be caught; it is only
318 valid if FILTER is NULL. If FILTER is empty and CATCH_ALL is zero,
319 then internal signals like SIGTRAP are not caught. */
322 create_signal_catchpoint (int tempflag
, std::vector
<gdb_signal
> &&filter
,
325 struct gdbarch
*gdbarch
= get_current_arch ();
327 std::unique_ptr
<signal_catchpoint
> c (new signal_catchpoint ());
328 init_catchpoint (c
.get (), gdbarch
, tempflag
, NULL
, &signal_catchpoint_ops
);
329 c
->signals_to_be_caught
= std::move (filter
);
330 c
->catch_all
= catch_all
;
332 install_breakpoint (0, std::move (c
), 1);
336 /* Splits the argument using space as delimiter. Returns a filter
337 list, which is empty if no filtering is required. */
339 static std::vector
<gdb_signal
>
340 catch_signal_split_args (const char *arg
, bool *catch_all
)
342 std::vector
<gdb_signal
> result
;
348 gdb_signal signal_number
;
351 std::string one_arg
= extract_arg (&arg
);
352 if (one_arg
.empty ())
355 /* Check for the special flag "all". */
356 if (one_arg
== "all")
358 arg
= skip_spaces (arg
);
359 if (*arg
!= '\0' || !first
)
360 error (_("'all' cannot be caught with other signals"));
362 gdb_assert (result
.empty ());
368 /* Check if the user provided a signal name or a number. */
369 num
= (int) strtol (one_arg
.c_str (), &endptr
, 0);
371 signal_number
= gdb_signal_from_command (num
);
374 signal_number
= gdb_signal_from_name (one_arg
.c_str ());
375 if (signal_number
== GDB_SIGNAL_UNKNOWN
)
376 error (_("Unknown signal name '%s'."), one_arg
.c_str ());
379 result
.push_back (signal_number
);
382 result
.shrink_to_fit ();
386 /* Implement the "catch signal" command. */
389 catch_signal_command (const char *arg
, int from_tty
,
390 struct cmd_list_element
*command
)
393 bool catch_all
= false;
394 std::vector
<gdb_signal
> filter
;
396 tempflag
= get_cmd_context (command
) == CATCH_TEMPORARY
;
398 arg
= skip_spaces (arg
);
400 /* The allowed syntax is:
402 catch signal <name | number> [<name | number> ... <name | number>]
404 Let's check if there's a signal name. */
407 filter
= catch_signal_split_args (arg
, &catch_all
);
409 create_signal_catchpoint (tempflag
, std::move (filter
), catch_all
);
413 initialize_signal_catchpoint_ops (void)
415 struct breakpoint_ops
*ops
;
417 initialize_breakpoint_ops ();
419 ops
= &signal_catchpoint_ops
;
420 *ops
= base_breakpoint_ops
;
421 ops
->insert_location
= signal_catchpoint_insert_location
;
422 ops
->remove_location
= signal_catchpoint_remove_location
;
423 ops
->breakpoint_hit
= signal_catchpoint_breakpoint_hit
;
424 ops
->print_it
= signal_catchpoint_print_it
;
425 ops
->print_one
= signal_catchpoint_print_one
;
426 ops
->print_mention
= signal_catchpoint_print_mention
;
427 ops
->print_recreate
= signal_catchpoint_print_recreate
;
428 ops
->explains_signal
= signal_catchpoint_explains_signal
;
432 _initialize_break_catch_sig (void)
434 initialize_signal_catchpoint_ops ();
436 signal_catch_counts
= XCNEWVEC (unsigned int, GDB_SIGNAL_LAST
);
438 add_catch_command ("signal", _("\
439 Catch signals by their names and/or numbers.\n\
440 Usage: catch signal [[NAME|NUMBER] [NAME|NUMBER]...|all]\n\
441 Arguments say which signals to catch. If no arguments\n\
442 are given, every \"normal\" signal will be caught.\n\
443 The argument \"all\" means to also catch signals used by GDB.\n\
444 Arguments, if given, should be one or more signal names\n\
445 (if your system supports that), or signal numbers."),
446 catch_signal_command
,