Add some more casts (1/2)
[external/binutils.git] / gdb / break-catch-sig.c
1 /* Everything about signal catchpoints, for GDB.
2
3    Copyright (C) 2011-2015 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
224   get_last_target_status (&ptid, &last);
225
226   signal_name = signal_to_name_or_int (last.value.sig);
227
228   annotate_catchpoint (b->number);
229
230   printf_filtered (_("\nCatchpoint %d (signal %s), "), b->number, signal_name);
231
232   return PRINT_SRC_AND_LOC;
233 }
234
235 /* Implement the "print_one" breakpoint_ops method for signal
236    catchpoints.  */
237
238 static void
239 signal_catchpoint_print_one (struct breakpoint *b,
240                              struct bp_location **last_loc)
241 {
242   struct signal_catchpoint *c = (struct signal_catchpoint *) b;
243   struct value_print_options opts;
244   struct ui_out *uiout = current_uiout;
245
246   get_user_print_options (&opts);
247
248   /* Field 4, the address, is omitted (which makes the columns
249      not line up too nicely with the headers, but the effect
250      is relatively readable).  */
251   if (opts.addressprint)
252     ui_out_field_skip (uiout, "addr");
253   annotate_field (5);
254
255   if (c->signals_to_be_caught
256       && VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
257     ui_out_text (uiout, "signals \"");
258   else
259     ui_out_text (uiout, "signal \"");
260
261   if (c->signals_to_be_caught)
262     {
263       int i;
264       gdb_signal_type iter;
265       struct obstack text;
266       struct cleanup *cleanup;
267
268       obstack_init (&text);
269       cleanup = make_cleanup_obstack_free (&text);
270
271       for (i = 0;
272            VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
273            i++)
274         {
275           const char *name = signal_to_name_or_int (iter);
276
277           if (i > 0)
278             obstack_grow (&text, " ", 1);
279           obstack_grow (&text, name, strlen (name));
280         }
281       obstack_grow (&text, "", 1);
282       ui_out_field_string (uiout, "what", obstack_base (&text));
283       do_cleanups (cleanup);
284     }
285   else
286     ui_out_field_string (uiout, "what",
287                          c->catch_all ? "<any signal>" : "<standard signals>");
288   ui_out_text (uiout, "\" ");
289
290   if (ui_out_is_mi_like_p (uiout))
291     ui_out_field_string (uiout, "catch-type", "signal");
292 }
293
294 /* Implement the "print_mention" breakpoint_ops method for signal
295    catchpoints.  */
296
297 static void
298 signal_catchpoint_print_mention (struct breakpoint *b)
299 {
300   struct signal_catchpoint *c = (struct signal_catchpoint *) b;
301
302   if (c->signals_to_be_caught)
303     {
304       int i;
305       gdb_signal_type iter;
306
307       if (VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
308         printf_filtered (_("Catchpoint %d (signals"), b->number);
309       else
310         printf_filtered (_("Catchpoint %d (signal"), b->number);
311
312       for (i = 0;
313            VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
314            i++)
315         {
316           const char *name = signal_to_name_or_int (iter);
317
318           printf_filtered (" %s", name);
319         }
320       printf_filtered (")");
321     }
322   else if (c->catch_all)
323     printf_filtered (_("Catchpoint %d (any signal)"), b->number);
324   else
325     printf_filtered (_("Catchpoint %d (standard signals)"), b->number);
326 }
327
328 /* Implement the "print_recreate" breakpoint_ops method for signal
329    catchpoints.  */
330
331 static void
332 signal_catchpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
333 {
334   struct signal_catchpoint *c = (struct signal_catchpoint *) b;
335
336   fprintf_unfiltered (fp, "catch signal");
337
338   if (c->signals_to_be_caught)
339     {
340       int i;
341       gdb_signal_type iter;
342
343       for (i = 0;
344            VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
345            i++)
346         fprintf_unfiltered (fp, " %s", signal_to_name_or_int (iter));
347     }
348   else if (c->catch_all)
349     fprintf_unfiltered (fp, " all");
350   fputc_unfiltered ('\n', fp);
351 }
352
353 /* Implement the "explains_signal" breakpoint_ops method for signal
354    catchpoints.  */
355
356 static int
357 signal_catchpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
358 {
359   return 1;
360 }
361
362 /* Create a new signal catchpoint.  TEMPFLAG is true if this should be
363    a temporary catchpoint.  FILTER is the list of signals to catch; it
364    can be NULL, meaning all signals.  CATCH_ALL is a flag indicating
365    whether signals used internally by gdb should be caught; it is only
366    valid if FILTER is NULL.  If FILTER is NULL and CATCH_ALL is zero,
367    then internal signals like SIGTRAP are not caught.  */
368
369 static void
370 create_signal_catchpoint (int tempflag, VEC (gdb_signal_type) *filter,
371                           int catch_all)
372 {
373   struct signal_catchpoint *c;
374   struct gdbarch *gdbarch = get_current_arch ();
375
376   c = XNEW (struct signal_catchpoint);
377   init_catchpoint (&c->base, gdbarch, tempflag, NULL, &signal_catchpoint_ops);
378   c->signals_to_be_caught = filter;
379   c->catch_all = catch_all;
380
381   install_breakpoint (0, &c->base, 1);
382 }
383
384
385 /* Splits the argument using space as delimiter.  Returns an xmalloc'd
386    filter list, or NULL if no filtering is required.  */
387
388 static VEC (gdb_signal_type) *
389 catch_signal_split_args (char *arg, int *catch_all)
390 {
391   VEC (gdb_signal_type) *result = NULL;
392   struct cleanup *cleanup = make_cleanup (VEC_cleanup (gdb_signal_type),
393                                           &result);
394   int first = 1;
395
396   while (*arg != '\0')
397     {
398       int num;
399       gdb_signal_type signal_number;
400       char *one_arg, *endptr;
401       struct cleanup *inner_cleanup;
402
403       one_arg = extract_arg (&arg);
404       if (one_arg == NULL)
405         break;
406       inner_cleanup = make_cleanup (xfree, one_arg);
407
408       /* Check for the special flag "all".  */
409       if (strcmp (one_arg, "all") == 0)
410         {
411           arg = skip_spaces (arg);
412           if (*arg != '\0' || !first)
413             error (_("'all' cannot be caught with other signals"));
414           *catch_all = 1;
415           gdb_assert (result == NULL);
416           do_cleanups (inner_cleanup);
417           discard_cleanups (cleanup);
418           return NULL;
419         }
420
421       first = 0;
422
423       /* Check if the user provided a signal name or a number.  */
424       num = (int) strtol (one_arg, &endptr, 0);
425       if (*endptr == '\0')
426         signal_number = gdb_signal_from_command (num);
427       else
428         {
429           signal_number = gdb_signal_from_name (one_arg);
430           if (signal_number == GDB_SIGNAL_UNKNOWN)
431             error (_("Unknown signal name '%s'."), one_arg);
432         }
433
434       VEC_safe_push (gdb_signal_type, result, signal_number);
435       do_cleanups (inner_cleanup);
436     }
437
438   discard_cleanups (cleanup);
439   return result;
440 }
441
442 /* Implement the "catch signal" command.  */
443
444 static void
445 catch_signal_command (char *arg, int from_tty,
446                       struct cmd_list_element *command)
447 {
448   int tempflag, catch_all = 0;
449   VEC (gdb_signal_type) *filter;
450
451   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
452
453   arg = skip_spaces (arg);
454
455   /* The allowed syntax is:
456      catch signal
457      catch signal <name | number> [<name | number> ... <name | number>]
458
459      Let's check if there's a signal name.  */
460
461   if (arg != NULL)
462     filter = catch_signal_split_args (arg, &catch_all);
463   else
464     filter = NULL;
465
466   create_signal_catchpoint (tempflag, filter, catch_all);
467 }
468
469 static void
470 initialize_signal_catchpoint_ops (void)
471 {
472   struct breakpoint_ops *ops;
473
474   initialize_breakpoint_ops ();
475
476   ops = &signal_catchpoint_ops;
477   *ops = base_breakpoint_ops;
478   ops->dtor = signal_catchpoint_dtor;
479   ops->insert_location = signal_catchpoint_insert_location;
480   ops->remove_location = signal_catchpoint_remove_location;
481   ops->breakpoint_hit = signal_catchpoint_breakpoint_hit;
482   ops->print_it = signal_catchpoint_print_it;
483   ops->print_one = signal_catchpoint_print_one;
484   ops->print_mention = signal_catchpoint_print_mention;
485   ops->print_recreate = signal_catchpoint_print_recreate;
486   ops->explains_signal = signal_catchpoint_explains_signal;
487 }
488
489 initialize_file_ftype _initialize_break_catch_sig;
490
491 void
492 _initialize_break_catch_sig (void)
493 {
494   initialize_signal_catchpoint_ops ();
495
496   signal_catch_counts = XCNEWVEC (unsigned int, GDB_SIGNAL_LAST);
497
498   add_catch_command ("signal", _("\
499 Catch signals by their names and/or numbers.\n\
500 Usage: catch signal [[NAME|NUMBER] [NAME|NUMBER]...|all]\n\
501 Arguments say which signals to catch.  If no arguments\n\
502 are given, every \"normal\" signal will be caught.\n\
503 The argument \"all\" means to also catch signals used by GDB.\n\
504 Arguments, if given, should be one or more signal names\n\
505 (if your system supports that), or signal numbers."),
506                      catch_signal_command,
507                      signal_completer,
508                      CATCH_PERMANENT,
509                      CATCH_TEMPORARY);
510 }