metag: make an array's type unsigned char[]
[external/binutils.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 }