write_pieced_value: Notify memory_changed observers
[deliverable/binutils-gdb.git] / gdb / break-catch-sig.c
CommitLineData
ab04a2af
TT
1/* Everything about signal catchpoints, for GDB.
2
61baf725 3 Copyright (C) 2011-2017 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"
21#include "arch-utils.h"
22#include <ctype.h>
23#include "breakpoint.h"
24#include "gdbcmd.h"
25#include "inferior.h"
45741a9c 26#include "infrun.h"
ab04a2af
TT
27#include "annotate.h"
28#include "valprint.h"
29#include "cli/cli-utils.h"
30#include "completer.h"
5809899d
TT
31
32#include <string>
ab04a2af
TT
33
34#define INTERNAL_SIGNAL(x) ((x) == GDB_SIGNAL_TRAP || (x) == GDB_SIGNAL_INT)
35
36typedef enum gdb_signal gdb_signal_type;
37
38DEF_VEC_I (gdb_signal_type);
39
40/* An instance of this type is used to represent a signal catchpoint.
c1fc2657 41 A breakpoint is really of this type iff its ops pointer points to
ab04a2af
TT
42 SIGNAL_CATCHPOINT_OPS. */
43
c1fc2657 44struct signal_catchpoint : public breakpoint
ab04a2af 45{
c1fc2657 46 ~signal_catchpoint () override;
ab04a2af
TT
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
64static struct breakpoint_ops signal_catchpoint_ops;
65
66/* Count of each signal. */
67
68static 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
75static const char *
76signal_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
c1fc2657 88/* signal_catchpoint destructor. */
ab04a2af 89
c1fc2657 90signal_catchpoint::~signal_catchpoint ()
ab04a2af 91{
c1fc2657 92 VEC_free (gdb_signal_type, this->signals_to_be_caught);
ab04a2af
TT
93}
94
95/* Implement the "insert_location" breakpoint_ops method for signal
96 catchpoints. */
97
98static int
99signal_catchpoint_insert_location (struct bp_location *bl)
100{
9a3c8263 101 struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
ab04a2af
TT
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
130static int
73971819
PA
131signal_catchpoint_remove_location (struct bp_location *bl,
132 enum remove_bp_reason reason)
ab04a2af 133{
9a3c8263 134 struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
ab04a2af
TT
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
169static int
170signal_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{
9a3c8263
SM
175 const struct signal_catchpoint *c
176 = (const struct signal_catchpoint *) bl->owner;
ab04a2af
TT
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)
96f7d3f1 196 return 1;
ab04a2af 197 /* Not the same. */
96f7d3f1
PW
198 gdb_assert (!iter);
199 return 0;
ab04a2af 200 }
96f7d3f1
PW
201 else
202 return c->catch_all || !INTERNAL_SIGNAL (signal_number);
ab04a2af
TT
203}
204
205/* Implement the "print_it" breakpoint_ops method for signal
206 catchpoints. */
207
208static enum print_stop_action
209signal_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;
f303dbd6 215 struct ui_out *uiout = current_uiout;
ab04a2af
TT
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);
f303dbd6 222 maybe_print_thread_hit_breakpoint (uiout);
ab04a2af 223
f303dbd6 224 printf_filtered (_("Catchpoint %d (signal %s), "), b->number, signal_name);
ab04a2af
TT
225
226 return PRINT_SRC_AND_LOC;
227}
228
229/* Implement the "print_one" breakpoint_ops method for signal
230 catchpoints. */
231
232static void
233signal_catchpoint_print_one (struct breakpoint *b,
234 struct bp_location **last_loc)
235{
9a3c8263 236 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
ab04a2af
TT
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)
112e8700 246 uiout->field_skip ("addr");
ab04a2af
TT
247 annotate_field (5);
248
249 if (c->signals_to_be_caught
250 && VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
112e8700 251 uiout->text ("signals \"");
ab04a2af 252 else
112e8700 253 uiout->text ("signal \"");
ab04a2af
TT
254
255 if (c->signals_to_be_caught)
256 {
257 int i;
258 gdb_signal_type iter;
5809899d 259 std::string text;
ab04a2af
TT
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)
5809899d
TT
268 text += " ";
269 text += name;
ab04a2af 270 }
112e8700 271 uiout->field_string ("what", text.c_str ());
ab04a2af
TT
272 }
273 else
112e8700 274 uiout->field_string ("what",
ab04a2af 275 c->catch_all ? "<any signal>" : "<standard signals>");
112e8700 276 uiout->text ("\" ");
ab04a2af 277
112e8700
SM
278 if (uiout->is_mi_like_p ())
279 uiout->field_string ("catch-type", "signal");
ab04a2af
TT
280}
281
282/* Implement the "print_mention" breakpoint_ops method for signal
283 catchpoints. */
284
285static void
286signal_catchpoint_print_mention (struct breakpoint *b)
287{
9a3c8263 288 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
ab04a2af
TT
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
319static void
320signal_catchpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
321{
9a3c8263 322 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
ab04a2af
TT
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");
c780cc2f 338 fputc_unfiltered ('\n', fp);
ab04a2af
TT
339}
340
341/* Implement the "explains_signal" breakpoint_ops method for signal
342 catchpoints. */
343
47591c29 344static int
427cd150 345signal_catchpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
ab04a2af 346{
47591c29 347 return 1;
ab04a2af
TT
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
357static void
358create_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
4d01a485 364 c = new signal_catchpoint ();
c1fc2657 365 init_catchpoint (c, gdbarch, tempflag, NULL, &signal_catchpoint_ops);
ab04a2af
TT
366 c->signals_to_be_caught = filter;
367 c->catch_all = catch_all;
368
c1fc2657 369 install_breakpoint (0, c, 1);
ab04a2af
TT
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
376static VEC (gdb_signal_type) *
377catch_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
432static void
433catch_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;
ab04a2af
TT
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
457static void
458initialize_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;
ab04a2af
TT
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
476initialize_file_ftype _initialize_break_catch_sig;
477
478void
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", _("\
486Catch signals by their names and/or numbers.\n\
487Usage: catch signal [[NAME|NUMBER] [NAME|NUMBER]...|all]\n\
488Arguments say which signals to catch. If no arguments\n\
489are given, every \"normal\" signal will be caught.\n\
490The argument \"all\" means to also catch signals used by GDB.\n\
491Arguments, 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.41813 seconds and 4 git commands to generate.