148596154Schristos /* Everything about signal catchpoints, for GDB.
248596154Schristos
3*1424dfb3Schristos Copyright (C) 2011-2020 Free Software Foundation, Inc.
448596154Schristos
548596154Schristos This file is part of GDB.
648596154Schristos
748596154Schristos This program is free software; you can redistribute it and/or modify
848596154Schristos it under the terms of the GNU General Public License as published by
948596154Schristos the Free Software Foundation; either version 3 of the License, or
1048596154Schristos (at your option) any later version.
1148596154Schristos
1248596154Schristos This program is distributed in the hope that it will be useful,
1348596154Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
1448596154Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1548596154Schristos GNU General Public License for more details.
1648596154Schristos
1748596154Schristos You should have received a copy of the GNU General Public License
1848596154Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */
1948596154Schristos
2048596154Schristos #include "defs.h"
2148596154Schristos #include "arch-utils.h"
2248596154Schristos #include <ctype.h>
2348596154Schristos #include "breakpoint.h"
2448596154Schristos #include "gdbcmd.h"
2548596154Schristos #include "inferior.h"
2626a53354Schristos #include "infrun.h"
2748596154Schristos #include "annotate.h"
2848596154Schristos #include "valprint.h"
2948596154Schristos #include "cli/cli-utils.h"
3048596154Schristos #include "completer.h"
31*1424dfb3Schristos #include "cli/cli-style.h"
321c468f90Schristos
331c468f90Schristos #include <string>
3448596154Schristos
3548596154Schristos #define INTERNAL_SIGNAL(x) ((x) == GDB_SIGNAL_TRAP || (x) == GDB_SIGNAL_INT)
3648596154Schristos
3748596154Schristos /* An instance of this type is used to represent a signal catchpoint.
3807163879Schristos A breakpoint is really of this type iff its ops pointer points to
3948596154Schristos SIGNAL_CATCHPOINT_OPS. */
4048596154Schristos
4107163879Schristos struct signal_catchpoint : public breakpoint
4248596154Schristos {
4348596154Schristos /* Signal numbers used for the 'catch signal' feature. If no signal
4407163879Schristos has been specified for filtering, it is empty. Otherwise,
4548596154Schristos it holds a list of all signals to be caught. */
4648596154Schristos
4707163879Schristos std::vector<gdb_signal> signals_to_be_caught;
4848596154Schristos
4907163879Schristos /* If SIGNALS_TO_BE_CAUGHT is empty, then all "ordinary" signals are
5007163879Schristos caught. If CATCH_ALL is true, then internal signals are caught
5107163879Schristos as well. If SIGNALS_TO_BE_CAUGHT is not empty, then this field
5207163879Schristos is ignored. */
5348596154Schristos
5407163879Schristos bool catch_all;
5548596154Schristos };
5648596154Schristos
5748596154Schristos /* The breakpoint_ops structure to be used in signal catchpoints. */
5848596154Schristos
5948596154Schristos static struct breakpoint_ops signal_catchpoint_ops;
6048596154Schristos
6148596154Schristos /* Count of each signal. */
6248596154Schristos
6348596154Schristos static unsigned int *signal_catch_counts;
6448596154Schristos
6548596154Schristos
6648596154Schristos
6748596154Schristos /* A convenience wrapper for gdb_signal_to_name that returns the
6848596154Schristos integer value if the name is not known. */
6948596154Schristos
7048596154Schristos static const char *
signal_to_name_or_int(enum gdb_signal sig)7148596154Schristos signal_to_name_or_int (enum gdb_signal sig)
7248596154Schristos {
7348596154Schristos const char *result = gdb_signal_to_name (sig);
7448596154Schristos
7548596154Schristos if (strcmp (result, "?") == 0)
7648596154Schristos result = plongest (sig);
7748596154Schristos
7848596154Schristos return result;
7948596154Schristos }
8048596154Schristos
8148596154Schristos
8248596154Schristos
8348596154Schristos /* Implement the "insert_location" breakpoint_ops method for signal
8448596154Schristos catchpoints. */
8548596154Schristos
8648596154Schristos static int
signal_catchpoint_insert_location(struct bp_location * bl)8748596154Schristos signal_catchpoint_insert_location (struct bp_location *bl)
8848596154Schristos {
89c03b94e9Schristos struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
9048596154Schristos
9107163879Schristos if (!c->signals_to_be_caught.empty ())
9248596154Schristos {
9307163879Schristos for (gdb_signal iter : c->signals_to_be_caught)
9448596154Schristos ++signal_catch_counts[iter];
9548596154Schristos }
9648596154Schristos else
9748596154Schristos {
9807163879Schristos for (int i = 0; i < GDB_SIGNAL_LAST; ++i)
9948596154Schristos {
10048596154Schristos if (c->catch_all || !INTERNAL_SIGNAL (i))
10148596154Schristos ++signal_catch_counts[i];
10248596154Schristos }
10348596154Schristos }
10448596154Schristos
10548596154Schristos signal_catch_update (signal_catch_counts);
10648596154Schristos
10748596154Schristos return 0;
10848596154Schristos }
10948596154Schristos
11048596154Schristos /* Implement the "remove_location" breakpoint_ops method for signal
11148596154Schristos catchpoints. */
11248596154Schristos
11348596154Schristos static int
signal_catchpoint_remove_location(struct bp_location * bl,enum remove_bp_reason reason)114c03b94e9Schristos signal_catchpoint_remove_location (struct bp_location *bl,
115c03b94e9Schristos enum remove_bp_reason reason)
11648596154Schristos {
117c03b94e9Schristos struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
11848596154Schristos
11907163879Schristos if (!c->signals_to_be_caught.empty ())
12048596154Schristos {
12107163879Schristos for (gdb_signal iter : c->signals_to_be_caught)
12248596154Schristos {
12348596154Schristos gdb_assert (signal_catch_counts[iter] > 0);
12448596154Schristos --signal_catch_counts[iter];
12548596154Schristos }
12648596154Schristos }
12748596154Schristos else
12848596154Schristos {
12907163879Schristos for (int i = 0; i < GDB_SIGNAL_LAST; ++i)
13048596154Schristos {
13148596154Schristos if (c->catch_all || !INTERNAL_SIGNAL (i))
13248596154Schristos {
13348596154Schristos gdb_assert (signal_catch_counts[i] > 0);
13448596154Schristos --signal_catch_counts[i];
13548596154Schristos }
13648596154Schristos }
13748596154Schristos }
13848596154Schristos
13948596154Schristos signal_catch_update (signal_catch_counts);
14048596154Schristos
14148596154Schristos return 0;
14248596154Schristos }
14348596154Schristos
14448596154Schristos /* Implement the "breakpoint_hit" breakpoint_ops method for signal
14548596154Schristos catchpoints. */
14648596154Schristos
14748596154Schristos static int
signal_catchpoint_breakpoint_hit(const struct bp_location * bl,const address_space * aspace,CORE_ADDR bp_addr,const struct target_waitstatus * ws)14848596154Schristos signal_catchpoint_breakpoint_hit (const struct bp_location *bl,
14907163879Schristos const address_space *aspace,
15048596154Schristos CORE_ADDR bp_addr,
15148596154Schristos const struct target_waitstatus *ws)
15248596154Schristos {
153c03b94e9Schristos const struct signal_catchpoint *c
154c03b94e9Schristos = (const struct signal_catchpoint *) bl->owner;
15507163879Schristos gdb_signal signal_number;
15648596154Schristos
15748596154Schristos if (ws->kind != TARGET_WAITKIND_STOPPED)
15848596154Schristos return 0;
15948596154Schristos
16048596154Schristos signal_number = ws->value.sig;
16148596154Schristos
16248596154Schristos /* If we are catching specific signals in this breakpoint, then we
16348596154Schristos must guarantee that the called signal is the same signal we are
16448596154Schristos catching. */
16507163879Schristos if (!c->signals_to_be_caught.empty ())
16648596154Schristos {
16707163879Schristos for (gdb_signal iter : c->signals_to_be_caught)
16848596154Schristos if (signal_number == iter)
1697af5a897Schristos return 1;
17048596154Schristos /* Not the same. */
17148596154Schristos return 0;
17248596154Schristos }
1737af5a897Schristos else
17448596154Schristos return c->catch_all || !INTERNAL_SIGNAL (signal_number);
17548596154Schristos }
17648596154Schristos
17748596154Schristos /* Implement the "print_it" breakpoint_ops method for signal
17848596154Schristos catchpoints. */
17948596154Schristos
18048596154Schristos static enum print_stop_action
signal_catchpoint_print_it(bpstat bs)18148596154Schristos signal_catchpoint_print_it (bpstat bs)
18248596154Schristos {
18348596154Schristos struct breakpoint *b = bs->breakpoint_at;
18448596154Schristos struct target_waitstatus last;
18548596154Schristos const char *signal_name;
186c03b94e9Schristos struct ui_out *uiout = current_uiout;
18748596154Schristos
188*1424dfb3Schristos get_last_target_status (nullptr, nullptr, &last);
18948596154Schristos
19048596154Schristos signal_name = signal_to_name_or_int (last.value.sig);
19148596154Schristos
19248596154Schristos annotate_catchpoint (b->number);
193c03b94e9Schristos maybe_print_thread_hit_breakpoint (uiout);
19448596154Schristos
195c03b94e9Schristos printf_filtered (_("Catchpoint %d (signal %s), "), b->number, signal_name);
19648596154Schristos
19748596154Schristos return PRINT_SRC_AND_LOC;
19848596154Schristos }
19948596154Schristos
20048596154Schristos /* Implement the "print_one" breakpoint_ops method for signal
20148596154Schristos catchpoints. */
20248596154Schristos
20348596154Schristos static void
signal_catchpoint_print_one(struct breakpoint * b,struct bp_location ** last_loc)20448596154Schristos signal_catchpoint_print_one (struct breakpoint *b,
20548596154Schristos struct bp_location **last_loc)
20648596154Schristos {
207c03b94e9Schristos struct signal_catchpoint *c = (struct signal_catchpoint *) b;
20848596154Schristos struct value_print_options opts;
20948596154Schristos struct ui_out *uiout = current_uiout;
21048596154Schristos
21148596154Schristos get_user_print_options (&opts);
21248596154Schristos
21348596154Schristos /* Field 4, the address, is omitted (which makes the columns
21448596154Schristos not line up too nicely with the headers, but the effect
21548596154Schristos is relatively readable). */
21648596154Schristos if (opts.addressprint)
2171c468f90Schristos uiout->field_skip ("addr");
21848596154Schristos annotate_field (5);
21948596154Schristos
22007163879Schristos if (c->signals_to_be_caught.size () > 1)
2211c468f90Schristos uiout->text ("signals \"");
22248596154Schristos else
2231c468f90Schristos uiout->text ("signal \"");
22448596154Schristos
22507163879Schristos if (!c->signals_to_be_caught.empty ())
22648596154Schristos {
2271c468f90Schristos std::string text;
22848596154Schristos
22907163879Schristos bool first = true;
23007163879Schristos for (gdb_signal iter : c->signals_to_be_caught)
23148596154Schristos {
23248596154Schristos const char *name = signal_to_name_or_int (iter);
23348596154Schristos
23407163879Schristos if (!first)
2351c468f90Schristos text += " ";
23607163879Schristos first = false;
23707163879Schristos
2381c468f90Schristos text += name;
23948596154Schristos }
2401c468f90Schristos uiout->field_string ("what", text.c_str ());
24148596154Schristos }
24248596154Schristos else
2431c468f90Schristos uiout->field_string ("what",
244*1424dfb3Schristos c->catch_all ? "<any signal>" : "<standard signals>",
245*1424dfb3Schristos metadata_style.style ());
2461c468f90Schristos uiout->text ("\" ");
24748596154Schristos
2481c468f90Schristos if (uiout->is_mi_like_p ())
2491c468f90Schristos uiout->field_string ("catch-type", "signal");
25048596154Schristos }
25148596154Schristos
25248596154Schristos /* Implement the "print_mention" breakpoint_ops method for signal
25348596154Schristos catchpoints. */
25448596154Schristos
25548596154Schristos static void
signal_catchpoint_print_mention(struct breakpoint * b)25648596154Schristos signal_catchpoint_print_mention (struct breakpoint *b)
25748596154Schristos {
258c03b94e9Schristos struct signal_catchpoint *c = (struct signal_catchpoint *) b;
25948596154Schristos
26007163879Schristos if (!c->signals_to_be_caught.empty ())
26148596154Schristos {
26207163879Schristos if (c->signals_to_be_caught.size () > 1)
26348596154Schristos printf_filtered (_("Catchpoint %d (signals"), b->number);
26448596154Schristos else
26548596154Schristos printf_filtered (_("Catchpoint %d (signal"), b->number);
26648596154Schristos
26707163879Schristos for (gdb_signal iter : c->signals_to_be_caught)
26848596154Schristos {
26948596154Schristos const char *name = signal_to_name_or_int (iter);
27048596154Schristos
27148596154Schristos printf_filtered (" %s", name);
27248596154Schristos }
27348596154Schristos printf_filtered (")");
27448596154Schristos }
27548596154Schristos else if (c->catch_all)
27648596154Schristos printf_filtered (_("Catchpoint %d (any signal)"), b->number);
27748596154Schristos else
27848596154Schristos printf_filtered (_("Catchpoint %d (standard signals)"), b->number);
27948596154Schristos }
28048596154Schristos
28148596154Schristos /* Implement the "print_recreate" breakpoint_ops method for signal
28248596154Schristos catchpoints. */
28348596154Schristos
28448596154Schristos static void
signal_catchpoint_print_recreate(struct breakpoint * b,struct ui_file * fp)28548596154Schristos signal_catchpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
28648596154Schristos {
287c03b94e9Schristos struct signal_catchpoint *c = (struct signal_catchpoint *) b;
28848596154Schristos
28948596154Schristos fprintf_unfiltered (fp, "catch signal");
29048596154Schristos
29107163879Schristos if (!c->signals_to_be_caught.empty ())
29248596154Schristos {
29307163879Schristos for (gdb_signal iter : c->signals_to_be_caught)
29448596154Schristos fprintf_unfiltered (fp, " %s", signal_to_name_or_int (iter));
29548596154Schristos }
29648596154Schristos else if (c->catch_all)
29748596154Schristos fprintf_unfiltered (fp, " all");
29826a53354Schristos fputc_unfiltered ('\n', fp);
29948596154Schristos }
30048596154Schristos
30148596154Schristos /* Implement the "explains_signal" breakpoint_ops method for signal
30248596154Schristos catchpoints. */
30348596154Schristos
3047af5a897Schristos static int
signal_catchpoint_explains_signal(struct breakpoint * b,enum gdb_signal sig)30548596154Schristos signal_catchpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
30648596154Schristos {
3077af5a897Schristos return 1;
30848596154Schristos }
30948596154Schristos
31048596154Schristos /* Create a new signal catchpoint. TEMPFLAG is true if this should be
31148596154Schristos a temporary catchpoint. FILTER is the list of signals to catch; it
31207163879Schristos can be empty, meaning all signals. CATCH_ALL is a flag indicating
31348596154Schristos whether signals used internally by gdb should be caught; it is only
31407163879Schristos valid if FILTER is NULL. If FILTER is empty and CATCH_ALL is zero,
31548596154Schristos then internal signals like SIGTRAP are not caught. */
31648596154Schristos
31748596154Schristos static void
create_signal_catchpoint(int tempflag,std::vector<gdb_signal> && filter,bool catch_all)31807163879Schristos create_signal_catchpoint (int tempflag, std::vector<gdb_signal> &&filter,
31907163879Schristos bool catch_all)
32048596154Schristos {
32148596154Schristos struct gdbarch *gdbarch = get_current_arch ();
32248596154Schristos
32307163879Schristos std::unique_ptr<signal_catchpoint> c (new signal_catchpoint ());
32407163879Schristos init_catchpoint (c.get (), gdbarch, tempflag, NULL, &signal_catchpoint_ops);
32507163879Schristos c->signals_to_be_caught = std::move (filter);
32648596154Schristos c->catch_all = catch_all;
32748596154Schristos
32807163879Schristos install_breakpoint (0, std::move (c), 1);
32948596154Schristos }
33048596154Schristos
33148596154Schristos
33207163879Schristos /* Splits the argument using space as delimiter. Returns a filter
33307163879Schristos list, which is empty if no filtering is required. */
33448596154Schristos
33507163879Schristos static std::vector<gdb_signal>
catch_signal_split_args(const char * arg,bool * catch_all)33607163879Schristos catch_signal_split_args (const char *arg, bool *catch_all)
33748596154Schristos {
33807163879Schristos std::vector<gdb_signal> result;
33907163879Schristos bool first = true;
34048596154Schristos
34148596154Schristos while (*arg != '\0')
34248596154Schristos {
34348596154Schristos int num;
34407163879Schristos gdb_signal signal_number;
34507163879Schristos char *endptr;
34648596154Schristos
34707163879Schristos std::string one_arg = extract_arg (&arg);
34807163879Schristos if (one_arg.empty ())
34948596154Schristos break;
35048596154Schristos
35148596154Schristos /* Check for the special flag "all". */
35207163879Schristos if (one_arg == "all")
35348596154Schristos {
35448596154Schristos arg = skip_spaces (arg);
35548596154Schristos if (*arg != '\0' || !first)
35648596154Schristos error (_("'all' cannot be caught with other signals"));
35707163879Schristos *catch_all = true;
35807163879Schristos gdb_assert (result.empty ());
35907163879Schristos return result;
36048596154Schristos }
36148596154Schristos
36207163879Schristos first = false;
36348596154Schristos
36448596154Schristos /* Check if the user provided a signal name or a number. */
36507163879Schristos num = (int) strtol (one_arg.c_str (), &endptr, 0);
36648596154Schristos if (*endptr == '\0')
36748596154Schristos signal_number = gdb_signal_from_command (num);
36848596154Schristos else
36948596154Schristos {
37007163879Schristos signal_number = gdb_signal_from_name (one_arg.c_str ());
37148596154Schristos if (signal_number == GDB_SIGNAL_UNKNOWN)
37207163879Schristos error (_("Unknown signal name '%s'."), one_arg.c_str ());
37348596154Schristos }
37448596154Schristos
37507163879Schristos result.push_back (signal_number);
37648596154Schristos }
37748596154Schristos
37807163879Schristos result.shrink_to_fit ();
37948596154Schristos return result;
38048596154Schristos }
38148596154Schristos
38248596154Schristos /* Implement the "catch signal" command. */
38348596154Schristos
38448596154Schristos static void
catch_signal_command(const char * arg,int from_tty,struct cmd_list_element * command)38507163879Schristos catch_signal_command (const char *arg, int from_tty,
38648596154Schristos struct cmd_list_element *command)
38748596154Schristos {
38807163879Schristos int tempflag;
38907163879Schristos bool catch_all = false;
39007163879Schristos std::vector<gdb_signal> filter;
39148596154Schristos
39248596154Schristos tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
39348596154Schristos
39448596154Schristos arg = skip_spaces (arg);
39548596154Schristos
39648596154Schristos /* The allowed syntax is:
39748596154Schristos catch signal
39848596154Schristos catch signal <name | number> [<name | number> ... <name | number>]
39948596154Schristos
40048596154Schristos Let's check if there's a signal name. */
40148596154Schristos
40248596154Schristos if (arg != NULL)
40348596154Schristos filter = catch_signal_split_args (arg, &catch_all);
40448596154Schristos
40507163879Schristos create_signal_catchpoint (tempflag, std::move (filter), catch_all);
40648596154Schristos }
40748596154Schristos
40848596154Schristos static void
initialize_signal_catchpoint_ops(void)40948596154Schristos initialize_signal_catchpoint_ops (void)
41048596154Schristos {
41148596154Schristos struct breakpoint_ops *ops;
41248596154Schristos
41348596154Schristos initialize_breakpoint_ops ();
41448596154Schristos
41548596154Schristos ops = &signal_catchpoint_ops;
41648596154Schristos *ops = base_breakpoint_ops;
41748596154Schristos ops->insert_location = signal_catchpoint_insert_location;
41848596154Schristos ops->remove_location = signal_catchpoint_remove_location;
41948596154Schristos ops->breakpoint_hit = signal_catchpoint_breakpoint_hit;
42048596154Schristos ops->print_it = signal_catchpoint_print_it;
42148596154Schristos ops->print_one = signal_catchpoint_print_one;
42248596154Schristos ops->print_mention = signal_catchpoint_print_mention;
42348596154Schristos ops->print_recreate = signal_catchpoint_print_recreate;
42448596154Schristos ops->explains_signal = signal_catchpoint_explains_signal;
42548596154Schristos }
42648596154Schristos
427*1424dfb3Schristos void _initialize_break_catch_sig ();
42848596154Schristos void
_initialize_break_catch_sig()429*1424dfb3Schristos _initialize_break_catch_sig ()
43048596154Schristos {
43148596154Schristos initialize_signal_catchpoint_ops ();
43248596154Schristos
43348596154Schristos signal_catch_counts = XCNEWVEC (unsigned int, GDB_SIGNAL_LAST);
43448596154Schristos
43548596154Schristos add_catch_command ("signal", _("\
43648596154Schristos Catch signals by their names and/or numbers.\n\
43748596154Schristos Usage: catch signal [[NAME|NUMBER] [NAME|NUMBER]...|all]\n\
43848596154Schristos Arguments say which signals to catch. If no arguments\n\
43948596154Schristos are given, every \"normal\" signal will be caught.\n\
44048596154Schristos The argument \"all\" means to also catch signals used by GDB.\n\
44148596154Schristos Arguments, if given, should be one or more signal names\n\
44248596154Schristos (if your system supports that), or signal numbers."),
44348596154Schristos catch_signal_command,
44448596154Schristos signal_completer,
44548596154Schristos CATCH_PERMANENT,
44648596154Schristos CATCH_TEMPORARY);
44748596154Schristos }
448