C++ify breakpoint class hierarchy (destructors only)
[deliverable/binutils-gdb.git] / gdb / break-catch-sig.c
1 /* Everything about signal catchpoints, for GDB.
2
3 Copyright (C) 2011-2017 Free Software Foundation, Inc.
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"
21 #include "arch-utils.h"
22 #include <ctype.h>
23 #include "breakpoint.h"
24 #include "gdbcmd.h"
25 #include "inferior.h"
26 #include "infrun.h"
27 #include "annotate.h"
28 #include "valprint.h"
29 #include "cli/cli-utils.h"
30 #include "completer.h"
31
32 #include <string>
33
34 #define INTERNAL_SIGNAL(x) ((x) == GDB_SIGNAL_TRAP || (x) == GDB_SIGNAL_INT)
35
36 typedef enum gdb_signal gdb_signal_type;
37
38 DEF_VEC_I (gdb_signal_type);
39
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. */
43
44 struct signal_catchpoint : public breakpoint
45 {
46 ~signal_catchpoint () override;
47
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. */
51
52 VEC (gdb_signal_type) *signals_to_be_caught;
53
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
57 field is ignored. */
58
59 int catch_all;
60 };
61
62 /* The breakpoint_ops structure to be used in signal catchpoints. */
63
64 static struct breakpoint_ops signal_catchpoint_ops;
65
66 /* Count of each signal. */
67
68 static unsigned int *signal_catch_counts;
69
70 \f
71
72 /* A convenience wrapper for gdb_signal_to_name that returns the
73 integer value if the name is not known. */
74
75 static const char *
76 signal_to_name_or_int (enum gdb_signal sig)
77 {
78 const char *result = gdb_signal_to_name (sig);
79
80 if (strcmp (result, "?") == 0)
81 result = plongest (sig);
82
83 return result;
84 }
85
86 \f
87
88 /* signal_catchpoint destructor. */
89
90 signal_catchpoint::~signal_catchpoint ()
91 {
92 VEC_free (gdb_signal_type, this->signals_to_be_caught);
93 }
94
95 /* Implement the "insert_location" breakpoint_ops method for signal
96 catchpoints. */
97
98 static int
99 signal_catchpoint_insert_location (struct bp_location *bl)
100 {
101 struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
102 int i;
103
104 if (c->signals_to_be_caught != NULL)
105 {
106 gdb_signal_type iter;
107
108 for (i = 0;
109 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
110 i++)
111 ++signal_catch_counts[iter];
112 }
113 else
114 {
115 for (i = 0; i < GDB_SIGNAL_LAST; ++i)
116 {
117 if (c->catch_all || !INTERNAL_SIGNAL (i))
118 ++signal_catch_counts[i];
119 }
120 }
121
122 signal_catch_update (signal_catch_counts);
123
124 return 0;
125 }
126
127 /* Implement the "remove_location" breakpoint_ops method for signal
128 catchpoints. */
129
130 static int
131 signal_catchpoint_remove_location (struct bp_location *bl,
132 enum remove_bp_reason reason)
133 {
134 struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
135 int i;
136
137 if (c->signals_to_be_caught != NULL)
138 {
139 gdb_signal_type iter;
140
141 for (i = 0;
142 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
143 i++)
144 {
145 gdb_assert (signal_catch_counts[iter] > 0);
146 --signal_catch_counts[iter];
147 }
148 }
149 else
150 {
151 for (i = 0; i < GDB_SIGNAL_LAST; ++i)
152 {
153 if (c->catch_all || !INTERNAL_SIGNAL (i))
154 {
155 gdb_assert (signal_catch_counts[i] > 0);
156 --signal_catch_counts[i];
157 }
158 }
159 }
160
161 signal_catch_update (signal_catch_counts);
162
163 return 0;
164 }
165
166 /* Implement the "breakpoint_hit" breakpoint_ops method for signal
167 catchpoints. */
168
169 static int
170 signal_catchpoint_breakpoint_hit (const struct bp_location *bl,
171 struct address_space *aspace,
172 CORE_ADDR bp_addr,
173 const struct target_waitstatus *ws)
174 {
175 const struct signal_catchpoint *c
176 = (const struct signal_catchpoint *) bl->owner;
177 gdb_signal_type signal_number;
178
179 if (ws->kind != TARGET_WAITKIND_STOPPED)
180 return 0;
181
182 signal_number = ws->value.sig;
183
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
186 catching. */
187 if (c->signals_to_be_caught)
188 {
189 int i;
190 gdb_signal_type iter;
191
192 for (i = 0;
193 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
194 i++)
195 if (signal_number == iter)
196 return 1;
197 /* Not the same. */
198 gdb_assert (!iter);
199 return 0;
200 }
201 else
202 return c->catch_all || !INTERNAL_SIGNAL (signal_number);
203 }
204
205 /* Implement the "print_it" breakpoint_ops method for signal
206 catchpoints. */
207
208 static enum print_stop_action
209 signal_catchpoint_print_it (bpstat bs)
210 {
211 struct breakpoint *b = bs->breakpoint_at;
212 ptid_t ptid;
213 struct target_waitstatus last;
214 const char *signal_name;
215 struct ui_out *uiout = current_uiout;
216
217 get_last_target_status (&ptid, &last);
218
219 signal_name = signal_to_name_or_int (last.value.sig);
220
221 annotate_catchpoint (b->number);
222 maybe_print_thread_hit_breakpoint (uiout);
223
224 printf_filtered (_("Catchpoint %d (signal %s), "), b->number, signal_name);
225
226 return PRINT_SRC_AND_LOC;
227 }
228
229 /* Implement the "print_one" breakpoint_ops method for signal
230 catchpoints. */
231
232 static void
233 signal_catchpoint_print_one (struct breakpoint *b,
234 struct bp_location **last_loc)
235 {
236 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
237 struct value_print_options opts;
238 struct ui_out *uiout = current_uiout;
239
240 get_user_print_options (&opts);
241
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");
247 annotate_field (5);
248
249 if (c->signals_to_be_caught
250 && VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
251 uiout->text ("signals \"");
252 else
253 uiout->text ("signal \"");
254
255 if (c->signals_to_be_caught)
256 {
257 int i;
258 gdb_signal_type iter;
259 std::string text;
260
261 for (i = 0;
262 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
263 i++)
264 {
265 const char *name = signal_to_name_or_int (iter);
266
267 if (i > 0)
268 text += " ";
269 text += name;
270 }
271 uiout->field_string ("what", text.c_str ());
272 }
273 else
274 uiout->field_string ("what",
275 c->catch_all ? "<any signal>" : "<standard signals>");
276 uiout->text ("\" ");
277
278 if (uiout->is_mi_like_p ())
279 uiout->field_string ("catch-type", "signal");
280 }
281
282 /* Implement the "print_mention" breakpoint_ops method for signal
283 catchpoints. */
284
285 static void
286 signal_catchpoint_print_mention (struct breakpoint *b)
287 {
288 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
289
290 if (c->signals_to_be_caught)
291 {
292 int i;
293 gdb_signal_type iter;
294
295 if (VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
296 printf_filtered (_("Catchpoint %d (signals"), b->number);
297 else
298 printf_filtered (_("Catchpoint %d (signal"), b->number);
299
300 for (i = 0;
301 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
302 i++)
303 {
304 const char *name = signal_to_name_or_int (iter);
305
306 printf_filtered (" %s", name);
307 }
308 printf_filtered (")");
309 }
310 else if (c->catch_all)
311 printf_filtered (_("Catchpoint %d (any signal)"), b->number);
312 else
313 printf_filtered (_("Catchpoint %d (standard signals)"), b->number);
314 }
315
316 /* Implement the "print_recreate" breakpoint_ops method for signal
317 catchpoints. */
318
319 static void
320 signal_catchpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
321 {
322 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
323
324 fprintf_unfiltered (fp, "catch signal");
325
326 if (c->signals_to_be_caught)
327 {
328 int i;
329 gdb_signal_type iter;
330
331 for (i = 0;
332 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
333 i++)
334 fprintf_unfiltered (fp, " %s", signal_to_name_or_int (iter));
335 }
336 else if (c->catch_all)
337 fprintf_unfiltered (fp, " all");
338 fputc_unfiltered ('\n', fp);
339 }
340
341 /* Implement the "explains_signal" breakpoint_ops method for signal
342 catchpoints. */
343
344 static int
345 signal_catchpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
346 {
347 return 1;
348 }
349
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. */
356
357 static void
358 create_signal_catchpoint (int tempflag, VEC (gdb_signal_type) *filter,
359 int catch_all)
360 {
361 struct signal_catchpoint *c;
362 struct gdbarch *gdbarch = get_current_arch ();
363
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;
368
369 install_breakpoint (0, c, 1);
370 }
371
372
373 /* Splits the argument using space as delimiter. Returns an xmalloc'd
374 filter list, or NULL if no filtering is required. */
375
376 static VEC (gdb_signal_type) *
377 catch_signal_split_args (char *arg, int *catch_all)
378 {
379 VEC (gdb_signal_type) *result = NULL;
380 struct cleanup *cleanup = make_cleanup (VEC_cleanup (gdb_signal_type),
381 &result);
382 int first = 1;
383
384 while (*arg != '\0')
385 {
386 int num;
387 gdb_signal_type signal_number;
388 char *one_arg, *endptr;
389 struct cleanup *inner_cleanup;
390
391 one_arg = extract_arg (&arg);
392 if (one_arg == NULL)
393 break;
394 inner_cleanup = make_cleanup (xfree, one_arg);
395
396 /* Check for the special flag "all". */
397 if (strcmp (one_arg, "all") == 0)
398 {
399 arg = skip_spaces (arg);
400 if (*arg != '\0' || !first)
401 error (_("'all' cannot be caught with other signals"));
402 *catch_all = 1;
403 gdb_assert (result == NULL);
404 do_cleanups (inner_cleanup);
405 discard_cleanups (cleanup);
406 return NULL;
407 }
408
409 first = 0;
410
411 /* Check if the user provided a signal name or a number. */
412 num = (int) strtol (one_arg, &endptr, 0);
413 if (*endptr == '\0')
414 signal_number = gdb_signal_from_command (num);
415 else
416 {
417 signal_number = gdb_signal_from_name (one_arg);
418 if (signal_number == GDB_SIGNAL_UNKNOWN)
419 error (_("Unknown signal name '%s'."), one_arg);
420 }
421
422 VEC_safe_push (gdb_signal_type, result, signal_number);
423 do_cleanups (inner_cleanup);
424 }
425
426 discard_cleanups (cleanup);
427 return result;
428 }
429
430 /* Implement the "catch signal" command. */
431
432 static void
433 catch_signal_command (char *arg, int from_tty,
434 struct cmd_list_element *command)
435 {
436 int tempflag, catch_all = 0;
437 VEC (gdb_signal_type) *filter;
438
439 tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
440
441 arg = skip_spaces (arg);
442
443 /* The allowed syntax is:
444 catch signal
445 catch signal <name | number> [<name | number> ... <name | number>]
446
447 Let's check if there's a signal name. */
448
449 if (arg != NULL)
450 filter = catch_signal_split_args (arg, &catch_all);
451 else
452 filter = NULL;
453
454 create_signal_catchpoint (tempflag, filter, catch_all);
455 }
456
457 static void
458 initialize_signal_catchpoint_ops (void)
459 {
460 struct breakpoint_ops *ops;
461
462 initialize_breakpoint_ops ();
463
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;
474 }
475
476 initialize_file_ftype _initialize_break_catch_sig;
477
478 void
479 _initialize_break_catch_sig (void)
480 {
481 initialize_signal_catchpoint_ops ();
482
483 signal_catch_counts = XCNEWVEC (unsigned int, GDB_SIGNAL_LAST);
484
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,
494 signal_completer,
495 CATCH_PERMANENT,
496 CATCH_TEMPORARY);
497 }
This page took 0.0398 seconds and 5 git commands to generate.