1 /* Everything about signal catchpoints, for GDB.
3 Copyright (C) 2011-2022 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 "cli/cli-style.h"
32 #include "cli/cli-decode.h"
36 #define INTERNAL_SIGNAL(x) ((x) == GDB_SIGNAL_TRAP || (x) == GDB_SIGNAL_INT)
38 /* An instance of this type is used to represent a signal
41 struct signal_catchpoint
: public breakpoint
43 int insert_location (struct bp_location
*) override
;
44 int remove_location (struct bp_location
*,
45 enum remove_bp_reason reason
) override
;
46 int breakpoint_hit (const struct bp_location
*bl
,
47 const address_space
*aspace
,
49 const target_waitstatus
&ws
) override
;
50 enum print_stop_action
print_it (struct bpstat
*bs
) override
;
51 bool print_one (struct bp_location
**) override
;
52 void print_mention () override
;
53 void print_recreate (struct ui_file
*fp
) override
;
54 int explains_signal (enum gdb_signal
) override
;
56 /* Signal numbers used for the 'catch signal' feature. If no signal
57 has been specified for filtering, it is empty. Otherwise,
58 it holds a list of all signals to be caught. */
60 std::vector
<gdb_signal
> signals_to_be_caught
;
62 /* If SIGNALS_TO_BE_CAUGHT is empty, then all "ordinary" signals are
63 caught. If CATCH_ALL is true, then internal signals are caught
64 as well. If SIGNALS_TO_BE_CAUGHT is not empty, then this field
70 /* Count of each signal. */
72 static unsigned int signal_catch_counts
[GDB_SIGNAL_LAST
];
76 /* A convenience wrapper for gdb_signal_to_name that returns the
77 integer value if the name is not known. */
80 signal_to_name_or_int (enum gdb_signal sig
)
82 const char *result
= gdb_signal_to_name (sig
);
84 if (strcmp (result
, "?") == 0)
85 result
= plongest (sig
);
92 /* Implement the "insert_location" method for signal catchpoints. */
95 signal_catchpoint::insert_location (struct bp_location
*bl
)
97 struct signal_catchpoint
*c
= (struct signal_catchpoint
*) bl
->owner
;
99 if (!c
->signals_to_be_caught
.empty ())
101 for (gdb_signal iter
: c
->signals_to_be_caught
)
102 ++signal_catch_counts
[iter
];
106 for (int i
= 0; i
< GDB_SIGNAL_LAST
; ++i
)
108 if (c
->catch_all
|| !INTERNAL_SIGNAL (i
))
109 ++signal_catch_counts
[i
];
113 signal_catch_update (signal_catch_counts
);
118 /* Implement the "remove_location" method for signal catchpoints. */
121 signal_catchpoint::remove_location (struct bp_location
*bl
,
122 enum remove_bp_reason reason
)
124 struct signal_catchpoint
*c
= (struct signal_catchpoint
*) bl
->owner
;
126 if (!c
->signals_to_be_caught
.empty ())
128 for (gdb_signal iter
: c
->signals_to_be_caught
)
130 gdb_assert (signal_catch_counts
[iter
] > 0);
131 --signal_catch_counts
[iter
];
136 for (int i
= 0; i
< GDB_SIGNAL_LAST
; ++i
)
138 if (c
->catch_all
|| !INTERNAL_SIGNAL (i
))
140 gdb_assert (signal_catch_counts
[i
] > 0);
141 --signal_catch_counts
[i
];
146 signal_catch_update (signal_catch_counts
);
151 /* Implement the "breakpoint_hit" method for signal catchpoints. */
154 signal_catchpoint::breakpoint_hit (const struct bp_location
*bl
,
155 const address_space
*aspace
,
157 const target_waitstatus
&ws
)
159 const struct signal_catchpoint
*c
160 = (const struct signal_catchpoint
*) bl
->owner
;
161 gdb_signal signal_number
;
163 if (ws
.kind () != TARGET_WAITKIND_STOPPED
)
166 signal_number
= ws
.sig ();
168 /* If we are catching specific signals in this breakpoint, then we
169 must guarantee that the called signal is the same signal we are
171 if (!c
->signals_to_be_caught
.empty ())
173 for (gdb_signal iter
: c
->signals_to_be_caught
)
174 if (signal_number
== iter
)
180 return c
->catch_all
|| !INTERNAL_SIGNAL (signal_number
);
183 /* Implement the "print_it" method for signal catchpoints. */
185 enum print_stop_action
186 signal_catchpoint::print_it (bpstat
*bs
)
188 struct target_waitstatus last
;
189 const char *signal_name
;
190 struct ui_out
*uiout
= current_uiout
;
192 get_last_target_status (nullptr, nullptr, &last
);
194 signal_name
= signal_to_name_or_int (last
.sig ());
196 annotate_catchpoint (number
);
197 maybe_print_thread_hit_breakpoint (uiout
);
199 gdb_printf (_("Catchpoint %d (signal %s), "), number
, signal_name
);
201 return PRINT_SRC_AND_LOC
;
204 /* Implement the "print_one" method for signal catchpoints. */
207 signal_catchpoint::print_one (struct bp_location
**last_loc
)
209 struct value_print_options opts
;
210 struct ui_out
*uiout
= current_uiout
;
212 get_user_print_options (&opts
);
214 /* Field 4, the address, is omitted (which makes the columns
215 not line up too nicely with the headers, but the effect
216 is relatively readable). */
217 if (opts
.addressprint
)
218 uiout
->field_skip ("addr");
221 if (signals_to_be_caught
.size () > 1)
222 uiout
->text ("signals \"");
224 uiout
->text ("signal \"");
226 if (!signals_to_be_caught
.empty ())
231 for (gdb_signal iter
: signals_to_be_caught
)
233 const char *name
= signal_to_name_or_int (iter
);
241 uiout
->field_string ("what", text
);
244 uiout
->field_string ("what",
245 catch_all
? "<any signal>" : "<standard signals>",
246 metadata_style
.style ());
249 if (uiout
->is_mi_like_p ())
250 uiout
->field_string ("catch-type", "signal");
255 /* Implement the "print_mention" method for signal catchpoints. */
258 signal_catchpoint::print_mention ()
260 if (!signals_to_be_caught
.empty ())
262 if (signals_to_be_caught
.size () > 1)
263 gdb_printf (_("Catchpoint %d (signals"), number
);
265 gdb_printf (_("Catchpoint %d (signal"), number
);
267 for (gdb_signal iter
: signals_to_be_caught
)
269 const char *name
= signal_to_name_or_int (iter
);
271 gdb_printf (" %s", name
);
276 gdb_printf (_("Catchpoint %d (any signal)"), number
);
278 gdb_printf (_("Catchpoint %d (standard signals)"), number
);
281 /* Implement the "print_recreate" method for signal catchpoints. */
284 signal_catchpoint::print_recreate (struct ui_file
*fp
)
286 gdb_printf (fp
, "catch signal");
288 if (!signals_to_be_caught
.empty ())
290 for (gdb_signal iter
: signals_to_be_caught
)
291 gdb_printf (fp
, " %s", signal_to_name_or_int (iter
));
294 gdb_printf (fp
, " all");
298 /* Implement the "explains_signal" method for signal catchpoints. */
301 signal_catchpoint::explains_signal (enum gdb_signal sig
)
306 /* Create a new signal catchpoint. TEMPFLAG is true if this should be
307 a temporary catchpoint. FILTER is the list of signals to catch; it
308 can be empty, meaning all signals. CATCH_ALL is a flag indicating
309 whether signals used internally by gdb should be caught; it is only
310 valid if FILTER is NULL. If FILTER is empty and CATCH_ALL is zero,
311 then internal signals like SIGTRAP are not caught. */
314 create_signal_catchpoint (int tempflag
, std::vector
<gdb_signal
> &&filter
,
317 struct gdbarch
*gdbarch
= get_current_arch ();
319 std::unique_ptr
<signal_catchpoint
> c (new signal_catchpoint ());
320 init_catchpoint (c
.get (), gdbarch
, tempflag
, NULL
, &vtable_breakpoint_ops
);
321 c
->signals_to_be_caught
= std::move (filter
);
322 c
->catch_all
= catch_all
;
324 install_breakpoint (0, std::move (c
), 1);
328 /* Splits the argument using space as delimiter. Returns a filter
329 list, which is empty if no filtering is required. */
331 static std::vector
<gdb_signal
>
332 catch_signal_split_args (const char *arg
, bool *catch_all
)
334 std::vector
<gdb_signal
> result
;
340 gdb_signal signal_number
;
343 std::string one_arg
= extract_arg (&arg
);
344 if (one_arg
.empty ())
347 /* Check for the special flag "all". */
348 if (one_arg
== "all")
350 arg
= skip_spaces (arg
);
351 if (*arg
!= '\0' || !first
)
352 error (_("'all' cannot be caught with other signals"));
354 gdb_assert (result
.empty ());
360 /* Check if the user provided a signal name or a number. */
361 num
= (int) strtol (one_arg
.c_str (), &endptr
, 0);
363 signal_number
= gdb_signal_from_command (num
);
366 signal_number
= gdb_signal_from_name (one_arg
.c_str ());
367 if (signal_number
== GDB_SIGNAL_UNKNOWN
)
368 error (_("Unknown signal name '%s'."), one_arg
.c_str ());
371 result
.push_back (signal_number
);
374 result
.shrink_to_fit ();
378 /* Implement the "catch signal" command. */
381 catch_signal_command (const char *arg
, int from_tty
,
382 struct cmd_list_element
*command
)
385 bool catch_all
= false;
386 std::vector
<gdb_signal
> filter
;
388 tempflag
= command
->context () == CATCH_TEMPORARY
;
390 arg
= skip_spaces (arg
);
392 /* The allowed syntax is:
394 catch signal <name | number> [<name | number> ... <name | number>]
396 Let's check if there's a signal name. */
399 filter
= catch_signal_split_args (arg
, &catch_all
);
401 create_signal_catchpoint (tempflag
, std::move (filter
), catch_all
);
404 void _initialize_break_catch_sig ();
406 _initialize_break_catch_sig ()
408 add_catch_command ("signal", _("\
409 Catch signals by their names and/or numbers.\n\
410 Usage: catch signal [[NAME|NUMBER] [NAME|NUMBER]...|all]\n\
411 Arguments say which signals to catch. If no arguments\n\
412 are given, every \"normal\" signal will be caught.\n\
413 The argument \"all\" means to also catch signals used by GDB.\n\
414 Arguments, if given, should be one or more signal names\n\
415 (if your system supports that), or signal numbers."),
416 catch_signal_command
,