]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/break-catch-sig.c
Fix PR threads/19422 - show which thread caused stop
[thirdparty/binutils-gdb.git] / gdb / break-catch-sig.c
1 /* Everything about signal catchpoints, for GDB.
2
3 Copyright (C) 2011-2016 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 #include "gdb_obstack.h"
32
33 #define INTERNAL_SIGNAL(x) ((x) == GDB_SIGNAL_TRAP || (x) == GDB_SIGNAL_INT)
34
35 typedef enum gdb_signal gdb_signal_type;
36
37 DEF_VEC_I (gdb_signal_type);
38
39 /* An instance of this type is used to represent a signal catchpoint.
40 It includes a "struct breakpoint" as a kind of base class; users
41 downcast to "struct breakpoint *" when needed. A breakpoint is
42 really of this type iff its ops pointer points to
43 SIGNAL_CATCHPOINT_OPS. */
44
45 struct signal_catchpoint
46 {
47 /* The base class. */
48
49 struct breakpoint base;
50
51 /* Signal numbers used for the 'catch signal' feature. If no signal
52 has been specified for filtering, its value is NULL. Otherwise,
53 it holds a list of all signals to be caught. */
54
55 VEC (gdb_signal_type) *signals_to_be_caught;
56
57 /* If SIGNALS_TO_BE_CAUGHT is NULL, then all "ordinary" signals are
58 caught. If CATCH_ALL is non-zero, then internal signals are
59 caught as well. If SIGNALS_TO_BE_CAUGHT is non-NULL, then this
60 field is ignored. */
61
62 int catch_all;
63 };
64
65 /* The breakpoint_ops structure to be used in signal catchpoints. */
66
67 static struct breakpoint_ops signal_catchpoint_ops;
68
69 /* Count of each signal. */
70
71 static unsigned int *signal_catch_counts;
72
73 \f
74
75 /* A convenience wrapper for gdb_signal_to_name that returns the
76 integer value if the name is not known. */
77
78 static const char *
79 signal_to_name_or_int (enum gdb_signal sig)
80 {
81 const char *result = gdb_signal_to_name (sig);
82
83 if (strcmp (result, "?") == 0)
84 result = plongest (sig);
85
86 return result;
87 }
88
89 \f
90
91 /* Implement the "dtor" breakpoint_ops method for signal
92 catchpoints. */
93
94 static void
95 signal_catchpoint_dtor (struct breakpoint *b)
96 {
97 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
98
99 VEC_free (gdb_signal_type, c->signals_to_be_caught);
100
101 base_breakpoint_ops.dtor (b);
102 }
103
104 /* Implement the "insert_location" breakpoint_ops method for signal
105 catchpoints. */
106
107 static int
108 signal_catchpoint_insert_location (struct bp_location *bl)
109 {
110 struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
111 int i;
112
113 if (c->signals_to_be_caught != NULL)
114 {
115 gdb_signal_type iter;
116
117 for (i = 0;
118 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
119 i++)
120 ++signal_catch_counts[iter];
121 }
122 else
123 {
124 for (i = 0; i < GDB_SIGNAL_LAST; ++i)
125 {
126 if (c->catch_all || !INTERNAL_SIGNAL (i))
127 ++signal_catch_counts[i];
128 }
129 }
130
131 signal_catch_update (signal_catch_counts);
132
133 return 0;
134 }
135
136 /* Implement the "remove_location" breakpoint_ops method for signal
137 catchpoints. */
138
139 static int
140 signal_catchpoint_remove_location (struct bp_location *bl)
141 {
142 struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
143 int i;
144
145 if (c->signals_to_be_caught != NULL)
146 {
147 gdb_signal_type iter;
148
149 for (i = 0;
150 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
151 i++)
152 {
153 gdb_assert (signal_catch_counts[iter] > 0);
154 --signal_catch_counts[iter];
155 }
156 }
157 else
158 {
159 for (i = 0; i < GDB_SIGNAL_LAST; ++i)
160 {
161 if (c->catch_all || !INTERNAL_SIGNAL (i))
162 {
163 gdb_assert (signal_catch_counts[i] > 0);
164 --signal_catch_counts[i];
165 }
166 }
167 }
168
169 signal_catch_update (signal_catch_counts);
170
171 return 0;
172 }
173
174 /* Implement the "breakpoint_hit" breakpoint_ops method for signal
175 catchpoints. */
176
177 static int
178 signal_catchpoint_breakpoint_hit (const struct bp_location *bl,
179 struct address_space *aspace,
180 CORE_ADDR bp_addr,
181 const struct target_waitstatus *ws)
182 {
183 const struct signal_catchpoint *c
184 = (const struct signal_catchpoint *) bl->owner;
185 gdb_signal_type signal_number;
186
187 if (ws->kind != TARGET_WAITKIND_STOPPED)
188 return 0;
189
190 signal_number = ws->value.sig;
191
192 /* If we are catching specific signals in this breakpoint, then we
193 must guarantee that the called signal is the same signal we are
194 catching. */
195 if (c->signals_to_be_caught)
196 {
197 int i;
198 gdb_signal_type iter;
199
200 for (i = 0;
201 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
202 i++)
203 if (signal_number == iter)
204 return 1;
205 /* Not the same. */
206 gdb_assert (!iter);
207 return 0;
208 }
209 else
210 return c->catch_all || !INTERNAL_SIGNAL (signal_number);
211 }
212
213 /* Implement the "print_it" breakpoint_ops method for signal
214 catchpoints. */
215
216 static enum print_stop_action
217 signal_catchpoint_print_it (bpstat bs)
218 {
219 struct breakpoint *b = bs->breakpoint_at;
220 ptid_t ptid;
221 struct target_waitstatus last;
222 const char *signal_name;
223 struct ui_out *uiout = current_uiout;
224
225 get_last_target_status (&ptid, &last);
226
227 signal_name = signal_to_name_or_int (last.value.sig);
228
229 annotate_catchpoint (b->number);
230 maybe_print_thread_hit_breakpoint (uiout);
231
232 printf_filtered (_("Catchpoint %d (signal %s), "), b->number, signal_name);
233
234 return PRINT_SRC_AND_LOC;
235 }
236
237 /* Implement the "print_one" breakpoint_ops method for signal
238 catchpoints. */
239
240 static void
241 signal_catchpoint_print_one (struct breakpoint *b,
242 struct bp_location **last_loc)
243 {
244 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
245 struct value_print_options opts;
246 struct ui_out *uiout = current_uiout;
247
248 get_user_print_options (&opts);
249
250 /* Field 4, the address, is omitted (which makes the columns
251 not line up too nicely with the headers, but the effect
252 is relatively readable). */
253 if (opts.addressprint)
254 ui_out_field_skip (uiout, "addr");
255 annotate_field (5);
256
257 if (c->signals_to_be_caught
258 && VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
259 ui_out_text (uiout, "signals \"");
260 else
261 ui_out_text (uiout, "signal \"");
262
263 if (c->signals_to_be_caught)
264 {
265 int i;
266 gdb_signal_type iter;
267 struct obstack text;
268 struct cleanup *cleanup;
269
270 obstack_init (&text);
271 cleanup = make_cleanup_obstack_free (&text);
272
273 for (i = 0;
274 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
275 i++)
276 {
277 const char *name = signal_to_name_or_int (iter);
278
279 if (i > 0)
280 obstack_grow (&text, " ", 1);
281 obstack_grow (&text, name, strlen (name));
282 }
283 obstack_grow (&text, "", 1);
284 ui_out_field_string (uiout, "what", (const char *) obstack_base (&text));
285 do_cleanups (cleanup);
286 }
287 else
288 ui_out_field_string (uiout, "what",
289 c->catch_all ? "<any signal>" : "<standard signals>");
290 ui_out_text (uiout, "\" ");
291
292 if (ui_out_is_mi_like_p (uiout))
293 ui_out_field_string (uiout, "catch-type", "signal");
294 }
295
296 /* Implement the "print_mention" breakpoint_ops method for signal
297 catchpoints. */
298
299 static void
300 signal_catchpoint_print_mention (struct breakpoint *b)
301 {
302 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
303
304 if (c->signals_to_be_caught)
305 {
306 int i;
307 gdb_signal_type iter;
308
309 if (VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
310 printf_filtered (_("Catchpoint %d (signals"), b->number);
311 else
312 printf_filtered (_("Catchpoint %d (signal"), b->number);
313
314 for (i = 0;
315 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
316 i++)
317 {
318 const char *name = signal_to_name_or_int (iter);
319
320 printf_filtered (" %s", name);
321 }
322 printf_filtered (")");
323 }
324 else if (c->catch_all)
325 printf_filtered (_("Catchpoint %d (any signal)"), b->number);
326 else
327 printf_filtered (_("Catchpoint %d (standard signals)"), b->number);
328 }
329
330 /* Implement the "print_recreate" breakpoint_ops method for signal
331 catchpoints. */
332
333 static void
334 signal_catchpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
335 {
336 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
337
338 fprintf_unfiltered (fp, "catch signal");
339
340 if (c->signals_to_be_caught)
341 {
342 int i;
343 gdb_signal_type iter;
344
345 for (i = 0;
346 VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
347 i++)
348 fprintf_unfiltered (fp, " %s", signal_to_name_or_int (iter));
349 }
350 else if (c->catch_all)
351 fprintf_unfiltered (fp, " all");
352 fputc_unfiltered ('\n', fp);
353 }
354
355 /* Implement the "explains_signal" breakpoint_ops method for signal
356 catchpoints. */
357
358 static int
359 signal_catchpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
360 {
361 return 1;
362 }
363
364 /* Create a new signal catchpoint. TEMPFLAG is true if this should be
365 a temporary catchpoint. FILTER is the list of signals to catch; it
366 can be NULL, meaning all signals. CATCH_ALL is a flag indicating
367 whether signals used internally by gdb should be caught; it is only
368 valid if FILTER is NULL. If FILTER is NULL and CATCH_ALL is zero,
369 then internal signals like SIGTRAP are not caught. */
370
371 static void
372 create_signal_catchpoint (int tempflag, VEC (gdb_signal_type) *filter,
373 int catch_all)
374 {
375 struct signal_catchpoint *c;
376 struct gdbarch *gdbarch = get_current_arch ();
377
378 c = XNEW (struct signal_catchpoint);
379 init_catchpoint (&c->base, gdbarch, tempflag, NULL, &signal_catchpoint_ops);
380 c->signals_to_be_caught = filter;
381 c->catch_all = catch_all;
382
383 install_breakpoint (0, &c->base, 1);
384 }
385
386
387 /* Splits the argument using space as delimiter. Returns an xmalloc'd
388 filter list, or NULL if no filtering is required. */
389
390 static VEC (gdb_signal_type) *
391 catch_signal_split_args (char *arg, int *catch_all)
392 {
393 VEC (gdb_signal_type) *result = NULL;
394 struct cleanup *cleanup = make_cleanup (VEC_cleanup (gdb_signal_type),
395 &result);
396 int first = 1;
397
398 while (*arg != '\0')
399 {
400 int num;
401 gdb_signal_type signal_number;
402 char *one_arg, *endptr;
403 struct cleanup *inner_cleanup;
404
405 one_arg = extract_arg (&arg);
406 if (one_arg == NULL)
407 break;
408 inner_cleanup = make_cleanup (xfree, one_arg);
409
410 /* Check for the special flag "all". */
411 if (strcmp (one_arg, "all") == 0)
412 {
413 arg = skip_spaces (arg);
414 if (*arg != '\0' || !first)
415 error (_("'all' cannot be caught with other signals"));
416 *catch_all = 1;
417 gdb_assert (result == NULL);
418 do_cleanups (inner_cleanup);
419 discard_cleanups (cleanup);
420 return NULL;
421 }
422
423 first = 0;
424
425 /* Check if the user provided a signal name or a number. */
426 num = (int) strtol (one_arg, &endptr, 0);
427 if (*endptr == '\0')
428 signal_number = gdb_signal_from_command (num);
429 else
430 {
431 signal_number = gdb_signal_from_name (one_arg);
432 if (signal_number == GDB_SIGNAL_UNKNOWN)
433 error (_("Unknown signal name '%s'."), one_arg);
434 }
435
436 VEC_safe_push (gdb_signal_type, result, signal_number);
437 do_cleanups (inner_cleanup);
438 }
439
440 discard_cleanups (cleanup);
441 return result;
442 }
443
444 /* Implement the "catch signal" command. */
445
446 static void
447 catch_signal_command (char *arg, int from_tty,
448 struct cmd_list_element *command)
449 {
450 int tempflag, catch_all = 0;
451 VEC (gdb_signal_type) *filter;
452
453 tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
454
455 arg = skip_spaces (arg);
456
457 /* The allowed syntax is:
458 catch signal
459 catch signal <name | number> [<name | number> ... <name | number>]
460
461 Let's check if there's a signal name. */
462
463 if (arg != NULL)
464 filter = catch_signal_split_args (arg, &catch_all);
465 else
466 filter = NULL;
467
468 create_signal_catchpoint (tempflag, filter, catch_all);
469 }
470
471 static void
472 initialize_signal_catchpoint_ops (void)
473 {
474 struct breakpoint_ops *ops;
475
476 initialize_breakpoint_ops ();
477
478 ops = &signal_catchpoint_ops;
479 *ops = base_breakpoint_ops;
480 ops->dtor = signal_catchpoint_dtor;
481 ops->insert_location = signal_catchpoint_insert_location;
482 ops->remove_location = signal_catchpoint_remove_location;
483 ops->breakpoint_hit = signal_catchpoint_breakpoint_hit;
484 ops->print_it = signal_catchpoint_print_it;
485 ops->print_one = signal_catchpoint_print_one;
486 ops->print_mention = signal_catchpoint_print_mention;
487 ops->print_recreate = signal_catchpoint_print_recreate;
488 ops->explains_signal = signal_catchpoint_explains_signal;
489 }
490
491 initialize_file_ftype _initialize_break_catch_sig;
492
493 void
494 _initialize_break_catch_sig (void)
495 {
496 initialize_signal_catchpoint_ops ();
497
498 signal_catch_counts = XCNEWVEC (unsigned int, GDB_SIGNAL_LAST);
499
500 add_catch_command ("signal", _("\
501 Catch signals by their names and/or numbers.\n\
502 Usage: catch signal [[NAME|NUMBER] [NAME|NUMBER]...|all]\n\
503 Arguments say which signals to catch. If no arguments\n\
504 are given, every \"normal\" signal will be caught.\n\
505 The argument \"all\" means to also catch signals used by GDB.\n\
506 Arguments, if given, should be one or more signal names\n\
507 (if your system supports that), or signal numbers."),
508 catch_signal_command,
509 signal_completer,
510 CATCH_PERMANENT,
511 CATCH_TEMPORARY);
512 }