Handle multiple target events before commit resume
[deliverable/binutils-gdb.git] / gdb / break-catch-sig.c
CommitLineData
ab04a2af
TT
1/* Everything about signal catchpoints, for GDB.
2
11bc5fe4 3 Copyright (C) 2011-2020 Free Software Foundation, Inc.
ab04a2af
TT
4
5 This file is part of GDB.
6
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.
11
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.
16
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/>. */
19
20#include "defs.h"
d55e5aa6 21#include "arch-utils.h"
4de283e4 22#include <ctype.h>
ab04a2af
TT
23#include "breakpoint.h"
24#include "gdbcmd.h"
25#include "inferior.h"
45741a9c 26#include "infrun.h"
4de283e4 27#include "annotate.h"
ab04a2af 28#include "valprint.h"
4de283e4
TT
29#include "cli/cli-utils.h"
30#include "completer.h"
7f6aba03 31#include "cli/cli-style.h"
4de283e4
TT
32
33#include <string>
ab04a2af
TT
34
35#define INTERNAL_SIGNAL(x) ((x) == GDB_SIGNAL_TRAP || (x) == GDB_SIGNAL_INT)
36
ab04a2af 37/* An instance of this type is used to represent a signal catchpoint.
c1fc2657 38 A breakpoint is really of this type iff its ops pointer points to
ab04a2af
TT
39 SIGNAL_CATCHPOINT_OPS. */
40
c1fc2657 41struct signal_catchpoint : public breakpoint
ab04a2af 42{
ab04a2af 43 /* Signal numbers used for the 'catch signal' feature. If no signal
f746a154 44 has been specified for filtering, it is empty. Otherwise,
ab04a2af
TT
45 it holds a list of all signals to be caught. */
46
f746a154 47 std::vector<gdb_signal> signals_to_be_caught;
ab04a2af 48
f746a154
TT
49 /* If SIGNALS_TO_BE_CAUGHT is empty, then all "ordinary" signals are
50 caught. If CATCH_ALL is true, then internal signals are caught
51 as well. If SIGNALS_TO_BE_CAUGHT is not empty, then this field
52 is ignored. */
ab04a2af 53
f746a154 54 bool catch_all;
ab04a2af
TT
55};
56
57/* The breakpoint_ops structure to be used in signal catchpoints. */
58
59static struct breakpoint_ops signal_catchpoint_ops;
60
61/* Count of each signal. */
62
63static unsigned int *signal_catch_counts;
64
65\f
66
67/* A convenience wrapper for gdb_signal_to_name that returns the
68 integer value if the name is not known. */
69
70static const char *
71signal_to_name_or_int (enum gdb_signal sig)
72{
73 const char *result = gdb_signal_to_name (sig);
74
75 if (strcmp (result, "?") == 0)
76 result = plongest (sig);
77
78 return result;
79}
80
81\f
82
ab04a2af
TT
83/* Implement the "insert_location" breakpoint_ops method for signal
84 catchpoints. */
85
86static int
87signal_catchpoint_insert_location (struct bp_location *bl)
88{
9a3c8263 89 struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
ab04a2af 90
f746a154 91 if (!c->signals_to_be_caught.empty ())
ab04a2af 92 {
f746a154 93 for (gdb_signal iter : c->signals_to_be_caught)
ab04a2af
TT
94 ++signal_catch_counts[iter];
95 }
96 else
97 {
f746a154 98 for (int i = 0; i < GDB_SIGNAL_LAST; ++i)
ab04a2af
TT
99 {
100 if (c->catch_all || !INTERNAL_SIGNAL (i))
101 ++signal_catch_counts[i];
102 }
103 }
104
105 signal_catch_update (signal_catch_counts);
106
107 return 0;
108}
109
110/* Implement the "remove_location" breakpoint_ops method for signal
111 catchpoints. */
112
113static int
73971819
PA
114signal_catchpoint_remove_location (struct bp_location *bl,
115 enum remove_bp_reason reason)
ab04a2af 116{
9a3c8263 117 struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
ab04a2af 118
f746a154 119 if (!c->signals_to_be_caught.empty ())
ab04a2af 120 {
f746a154 121 for (gdb_signal iter : c->signals_to_be_caught)
ab04a2af
TT
122 {
123 gdb_assert (signal_catch_counts[iter] > 0);
124 --signal_catch_counts[iter];
125 }
126 }
127 else
128 {
f746a154 129 for (int i = 0; i < GDB_SIGNAL_LAST; ++i)
ab04a2af
TT
130 {
131 if (c->catch_all || !INTERNAL_SIGNAL (i))
132 {
133 gdb_assert (signal_catch_counts[i] > 0);
134 --signal_catch_counts[i];
135 }
136 }
137 }
138
139 signal_catch_update (signal_catch_counts);
140
141 return 0;
142}
143
144/* Implement the "breakpoint_hit" breakpoint_ops method for signal
145 catchpoints. */
146
147static int
148signal_catchpoint_breakpoint_hit (const struct bp_location *bl,
bd522513 149 const address_space *aspace,
ab04a2af
TT
150 CORE_ADDR bp_addr,
151 const struct target_waitstatus *ws)
152{
9a3c8263
SM
153 const struct signal_catchpoint *c
154 = (const struct signal_catchpoint *) bl->owner;
f746a154 155 gdb_signal signal_number;
ab04a2af
TT
156
157 if (ws->kind != TARGET_WAITKIND_STOPPED)
158 return 0;
159
160 signal_number = ws->value.sig;
161
162 /* If we are catching specific signals in this breakpoint, then we
163 must guarantee that the called signal is the same signal we are
164 catching. */
f746a154 165 if (!c->signals_to_be_caught.empty ())
ab04a2af 166 {
f746a154 167 for (gdb_signal iter : c->signals_to_be_caught)
ab04a2af 168 if (signal_number == iter)
96f7d3f1 169 return 1;
ab04a2af 170 /* Not the same. */
96f7d3f1 171 return 0;
ab04a2af 172 }
96f7d3f1
PW
173 else
174 return c->catch_all || !INTERNAL_SIGNAL (signal_number);
ab04a2af
TT
175}
176
177/* Implement the "print_it" breakpoint_ops method for signal
178 catchpoints. */
179
180static enum print_stop_action
181signal_catchpoint_print_it (bpstat bs)
182{
183 struct breakpoint *b = bs->breakpoint_at;
184 ptid_t ptid;
185 struct target_waitstatus last;
186 const char *signal_name;
f303dbd6 187 struct ui_out *uiout = current_uiout;
ab04a2af
TT
188
189 get_last_target_status (&ptid, &last);
190
191 signal_name = signal_to_name_or_int (last.value.sig);
192
193 annotate_catchpoint (b->number);
f303dbd6 194 maybe_print_thread_hit_breakpoint (uiout);
ab04a2af 195
f303dbd6 196 printf_filtered (_("Catchpoint %d (signal %s), "), b->number, signal_name);
ab04a2af
TT
197
198 return PRINT_SRC_AND_LOC;
199}
200
201/* Implement the "print_one" breakpoint_ops method for signal
202 catchpoints. */
203
204static void
205signal_catchpoint_print_one (struct breakpoint *b,
206 struct bp_location **last_loc)
207{
9a3c8263 208 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
ab04a2af
TT
209 struct value_print_options opts;
210 struct ui_out *uiout = current_uiout;
211
212 get_user_print_options (&opts);
213
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)
112e8700 218 uiout->field_skip ("addr");
ab04a2af
TT
219 annotate_field (5);
220
f746a154 221 if (c->signals_to_be_caught.size () > 1)
112e8700 222 uiout->text ("signals \"");
ab04a2af 223 else
112e8700 224 uiout->text ("signal \"");
ab04a2af 225
f746a154 226 if (!c->signals_to_be_caught.empty ())
ab04a2af 227 {
5809899d 228 std::string text;
ab04a2af 229
f746a154
TT
230 bool first = true;
231 for (gdb_signal iter : c->signals_to_be_caught)
ab04a2af
TT
232 {
233 const char *name = signal_to_name_or_int (iter);
234
f746a154 235 if (!first)
5809899d 236 text += " ";
f746a154
TT
237 first = false;
238
5809899d 239 text += name;
ab04a2af 240 }
112e8700 241 uiout->field_string ("what", text.c_str ());
ab04a2af
TT
242 }
243 else
112e8700 244 uiout->field_string ("what",
7f6aba03
TT
245 c->catch_all ? "<any signal>" : "<standard signals>",
246 metadata_style.style ());
112e8700 247 uiout->text ("\" ");
ab04a2af 248
112e8700
SM
249 if (uiout->is_mi_like_p ())
250 uiout->field_string ("catch-type", "signal");
ab04a2af
TT
251}
252
253/* Implement the "print_mention" breakpoint_ops method for signal
254 catchpoints. */
255
256static void
257signal_catchpoint_print_mention (struct breakpoint *b)
258{
9a3c8263 259 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
ab04a2af 260
f746a154 261 if (!c->signals_to_be_caught.empty ())
ab04a2af 262 {
f746a154 263 if (c->signals_to_be_caught.size () > 1)
ab04a2af
TT
264 printf_filtered (_("Catchpoint %d (signals"), b->number);
265 else
266 printf_filtered (_("Catchpoint %d (signal"), b->number);
267
f746a154 268 for (gdb_signal iter : c->signals_to_be_caught)
ab04a2af
TT
269 {
270 const char *name = signal_to_name_or_int (iter);
271
272 printf_filtered (" %s", name);
273 }
274 printf_filtered (")");
275 }
276 else if (c->catch_all)
277 printf_filtered (_("Catchpoint %d (any signal)"), b->number);
278 else
279 printf_filtered (_("Catchpoint %d (standard signals)"), b->number);
280}
281
282/* Implement the "print_recreate" breakpoint_ops method for signal
283 catchpoints. */
284
285static void
286signal_catchpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
287{
9a3c8263 288 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
ab04a2af
TT
289
290 fprintf_unfiltered (fp, "catch signal");
291
f746a154 292 if (!c->signals_to_be_caught.empty ())
ab04a2af 293 {
f746a154 294 for (gdb_signal iter : c->signals_to_be_caught)
ab04a2af
TT
295 fprintf_unfiltered (fp, " %s", signal_to_name_or_int (iter));
296 }
297 else if (c->catch_all)
298 fprintf_unfiltered (fp, " all");
c780cc2f 299 fputc_unfiltered ('\n', fp);
ab04a2af
TT
300}
301
302/* Implement the "explains_signal" breakpoint_ops method for signal
303 catchpoints. */
304
47591c29 305static int
427cd150 306signal_catchpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
ab04a2af 307{
47591c29 308 return 1;
ab04a2af
TT
309}
310
311/* Create a new signal catchpoint. TEMPFLAG is true if this should be
312 a temporary catchpoint. FILTER is the list of signals to catch; it
f746a154 313 can be empty, meaning all signals. CATCH_ALL is a flag indicating
ab04a2af 314 whether signals used internally by gdb should be caught; it is only
f746a154 315 valid if FILTER is NULL. If FILTER is empty and CATCH_ALL is zero,
ab04a2af
TT
316 then internal signals like SIGTRAP are not caught. */
317
318static void
f746a154
TT
319create_signal_catchpoint (int tempflag, std::vector<gdb_signal> &&filter,
320 bool catch_all)
ab04a2af 321{
ab04a2af
TT
322 struct gdbarch *gdbarch = get_current_arch ();
323
b270e6f9
TT
324 std::unique_ptr<signal_catchpoint> c (new signal_catchpoint ());
325 init_catchpoint (c.get (), gdbarch, tempflag, NULL, &signal_catchpoint_ops);
2f5404b3 326 c->signals_to_be_caught = std::move (filter);
ab04a2af
TT
327 c->catch_all = catch_all;
328
b270e6f9 329 install_breakpoint (0, std::move (c), 1);
ab04a2af
TT
330}
331
332
f746a154
TT
333/* Splits the argument using space as delimiter. Returns a filter
334 list, which is empty if no filtering is required. */
ab04a2af 335
f746a154 336static std::vector<gdb_signal>
eb4c3f4a 337catch_signal_split_args (const char *arg, bool *catch_all)
ab04a2af 338{
f746a154
TT
339 std::vector<gdb_signal> result;
340 bool first = true;
ab04a2af
TT
341
342 while (*arg != '\0')
343 {
344 int num;
f746a154
TT
345 gdb_signal signal_number;
346 char *endptr;
ab04a2af 347
cb791d59
TT
348 std::string one_arg = extract_arg (&arg);
349 if (one_arg.empty ())
ab04a2af 350 break;
ab04a2af
TT
351
352 /* Check for the special flag "all". */
cb791d59 353 if (one_arg == "all")
ab04a2af
TT
354 {
355 arg = skip_spaces (arg);
356 if (*arg != '\0' || !first)
357 error (_("'all' cannot be caught with other signals"));
f746a154
TT
358 *catch_all = true;
359 gdb_assert (result.empty ());
360 return result;
ab04a2af
TT
361 }
362
f746a154 363 first = false;
ab04a2af
TT
364
365 /* Check if the user provided a signal name or a number. */
cb791d59 366 num = (int) strtol (one_arg.c_str (), &endptr, 0);
ab04a2af
TT
367 if (*endptr == '\0')
368 signal_number = gdb_signal_from_command (num);
369 else
370 {
cb791d59 371 signal_number = gdb_signal_from_name (one_arg.c_str ());
ab04a2af 372 if (signal_number == GDB_SIGNAL_UNKNOWN)
cb791d59 373 error (_("Unknown signal name '%s'."), one_arg.c_str ());
ab04a2af
TT
374 }
375
f746a154 376 result.push_back (signal_number);
ab04a2af
TT
377 }
378
f746a154 379 result.shrink_to_fit ();
ab04a2af
TT
380 return result;
381}
382
383/* Implement the "catch signal" command. */
384
385static void
eb4c3f4a 386catch_signal_command (const char *arg, int from_tty,
ab04a2af
TT
387 struct cmd_list_element *command)
388{
f746a154
TT
389 int tempflag;
390 bool catch_all = false;
391 std::vector<gdb_signal> filter;
ab04a2af
TT
392
393 tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
394
395 arg = skip_spaces (arg);
396
397 /* The allowed syntax is:
398 catch signal
399 catch signal <name | number> [<name | number> ... <name | number>]
400
401 Let's check if there's a signal name. */
402
403 if (arg != NULL)
404 filter = catch_signal_split_args (arg, &catch_all);
ab04a2af 405
f746a154 406 create_signal_catchpoint (tempflag, std::move (filter), catch_all);
ab04a2af
TT
407}
408
409static void
410initialize_signal_catchpoint_ops (void)
411{
412 struct breakpoint_ops *ops;
413
414 initialize_breakpoint_ops ();
415
416 ops = &signal_catchpoint_ops;
417 *ops = base_breakpoint_ops;
ab04a2af
TT
418 ops->insert_location = signal_catchpoint_insert_location;
419 ops->remove_location = signal_catchpoint_remove_location;
420 ops->breakpoint_hit = signal_catchpoint_breakpoint_hit;
421 ops->print_it = signal_catchpoint_print_it;
422 ops->print_one = signal_catchpoint_print_one;
423 ops->print_mention = signal_catchpoint_print_mention;
424 ops->print_recreate = signal_catchpoint_print_recreate;
425 ops->explains_signal = signal_catchpoint_explains_signal;
426}
427
ab04a2af
TT
428void
429_initialize_break_catch_sig (void)
430{
431 initialize_signal_catchpoint_ops ();
432
433 signal_catch_counts = XCNEWVEC (unsigned int, GDB_SIGNAL_LAST);
434
435 add_catch_command ("signal", _("\
436Catch signals by their names and/or numbers.\n\
437Usage: catch signal [[NAME|NUMBER] [NAME|NUMBER]...|all]\n\
438Arguments say which signals to catch. If no arguments\n\
439are given, every \"normal\" signal will be caught.\n\
440The argument \"all\" means to also catch signals used by GDB.\n\
441Arguments, if given, should be one or more signal names\n\
442(if your system supports that), or signal numbers."),
443 catch_signal_command,
444 signal_completer,
445 CATCH_PERMANENT,
446 CATCH_TEMPORARY);
447}
This page took 0.470105 seconds and 4 git commands to generate.