GDB (xrefs)
/tmp/gdb-7.10/gdb/break-catch-sig.c
Go to the documentation of this file.
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 
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 
68 
69 /* Count of each signal. */
70 
71 static unsigned int *signal_catch_counts;
72 
73 
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 
90 
91 /* Implement the "dtor" breakpoint_ops method for signal
92  catchpoints. */
93 
94 static void
96 {
97  struct signal_catchpoint *c = (struct signal_catchpoint *) b;
98 
99  VEC_free (gdb_signal_type, c->signals_to_be_caught);
100 
102 }
103 
104 /* Implement the "insert_location" breakpoint_ops method for signal
105  catchpoints. */
106 
107 static int
109 {
110  struct signal_catchpoint *c = (void *) 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
141 {
142  struct signal_catchpoint *c = (void *) 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
179  struct address_space *aspace,
180  CORE_ADDR bp_addr,
181  const struct target_waitstatus *ws)
182 {
183  const struct signal_catchpoint *c = (void *) bl->owner;
184  gdb_signal_type signal_number;
185 
187  return 0;
188 
189  signal_number = ws->value.sig;
190 
191  /* If we are catching specific signals in this breakpoint, then we
192  must guarantee that the called signal is the same signal we are
193  catching. */
194  if (c->signals_to_be_caught)
195  {
196  int i;
197  gdb_signal_type iter;
198 
199  for (i = 0;
200  VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
201  i++)
202  if (signal_number == iter)
203  return 1;
204  /* Not the same. */
205  gdb_assert (!iter);
206  return 0;
207  }
208  else
209  return c->catch_all || !INTERNAL_SIGNAL (signal_number);
210 }
211 
212 /* Implement the "print_it" breakpoint_ops method for signal
213  catchpoints. */
214 
215 static enum print_stop_action
217 {
218  struct breakpoint *b = bs->breakpoint_at;
219  ptid_t ptid;
220  struct target_waitstatus last;
221  const char *signal_name;
222 
223  get_last_target_status (&ptid, &last);
224 
225  signal_name = signal_to_name_or_int (last.value.sig);
226 
228 
229  printf_filtered (_("\nCatchpoint %d (signal %s), "), b->number, signal_name);
230 
231  return PRINT_SRC_AND_LOC;
232 }
233 
234 /* Implement the "print_one" breakpoint_ops method for signal
235  catchpoints. */
236 
237 static void
239  struct bp_location **last_loc)
240 {
241  struct signal_catchpoint *c = (void *) b;
242  struct value_print_options opts;
243  struct ui_out *uiout = current_uiout;
244 
245  get_user_print_options (&opts);
246 
247  /* Field 4, the address, is omitted (which makes the columns
248  not line up too nicely with the headers, but the effect
249  is relatively readable). */
250  if (opts.addressprint)
251  ui_out_field_skip (uiout, "addr");
252  annotate_field (5);
253 
254  if (c->signals_to_be_caught
255  && VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
256  ui_out_text (uiout, "signals \"");
257  else
258  ui_out_text (uiout, "signal \"");
259 
260  if (c->signals_to_be_caught)
261  {
262  int i;
263  gdb_signal_type iter;
264  struct obstack text;
265  struct cleanup *cleanup;
266 
267  obstack_init (&text);
268  cleanup = make_cleanup_obstack_free (&text);
269 
270  for (i = 0;
271  VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
272  i++)
273  {
274  const char *name = signal_to_name_or_int (iter);
275 
276  if (i > 0)
277  obstack_grow (&text, " ", 1);
278  obstack_grow (&text, name, strlen (name));
279  }
280  obstack_grow (&text, "", 1);
281  ui_out_field_string (uiout, "what", obstack_base (&text));
282  do_cleanups (cleanup);
283  }
284  else
285  ui_out_field_string (uiout, "what",
286  c->catch_all ? "<any signal>" : "<standard signals>");
287  ui_out_text (uiout, "\" ");
288 
289  if (ui_out_is_mi_like_p (uiout))
290  ui_out_field_string (uiout, "catch-type", "signal");
291 }
292 
293 /* Implement the "print_mention" breakpoint_ops method for signal
294  catchpoints. */
295 
296 static void
298 {
299  struct signal_catchpoint *c = (void *) b;
300 
301  if (c->signals_to_be_caught)
302  {
303  int i;
304  gdb_signal_type iter;
305 
306  if (VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
307  printf_filtered (_("Catchpoint %d (signals"), b->number);
308  else
309  printf_filtered (_("Catchpoint %d (signal"), b->number);
310 
311  for (i = 0;
312  VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
313  i++)
314  {
315  const char *name = signal_to_name_or_int (iter);
316 
317  printf_filtered (" %s", name);
318  }
319  printf_filtered (")");
320  }
321  else if (c->catch_all)
322  printf_filtered (_("Catchpoint %d (any signal)"), b->number);
323  else
324  printf_filtered (_("Catchpoint %d (standard signals)"), b->number);
325 }
326 
327 /* Implement the "print_recreate" breakpoint_ops method for signal
328  catchpoints. */
329 
330 static void
332 {
333  struct signal_catchpoint *c = (void *) b;
334 
335  fprintf_unfiltered (fp, "catch signal");
336 
337  if (c->signals_to_be_caught)
338  {
339  int i;
340  gdb_signal_type iter;
341 
342  for (i = 0;
343  VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
344  i++)
345  fprintf_unfiltered (fp, " %s", signal_to_name_or_int (iter));
346  }
347  else if (c->catch_all)
348  fprintf_unfiltered (fp, " all");
349  fputc_unfiltered ('\n', fp);
350 }
351 
352 /* Implement the "explains_signal" breakpoint_ops method for signal
353  catchpoints. */
354 
355 static int
356 signal_catchpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
357 {
358  return 1;
359 }
360 
361 /* Create a new signal catchpoint. TEMPFLAG is true if this should be
362  a temporary catchpoint. FILTER is the list of signals to catch; it
363  can be NULL, meaning all signals. CATCH_ALL is a flag indicating
364  whether signals used internally by gdb should be caught; it is only
365  valid if FILTER is NULL. If FILTER is NULL and CATCH_ALL is zero,
366  then internal signals like SIGTRAP are not caught. */
367 
368 static void
369 create_signal_catchpoint (int tempflag, VEC (gdb_signal_type) *filter,
370  int catch_all)
371 {
372  struct signal_catchpoint *c;
373  struct gdbarch *gdbarch = get_current_arch ();
374 
375  c = XNEW (struct signal_catchpoint);
376  init_catchpoint (&c->base, gdbarch, tempflag, NULL, &signal_catchpoint_ops);
377  c->signals_to_be_caught = filter;
378  c->catch_all = catch_all;
379 
380  install_breakpoint (0, &c->base, 1);
381 }
382 
383 
384 /* Splits the argument using space as delimiter. Returns an xmalloc'd
385  filter list, or NULL if no filtering is required. */
386 
387 static VEC (gdb_signal_type) *
388 catch_signal_split_args (char *arg, int *catch_all)
389 {
390  VEC (gdb_signal_type) *result = NULL;
391  struct cleanup *cleanup = make_cleanup (VEC_cleanup (gdb_signal_type),
392  &result);
393  int first = 1;
394 
395  while (*arg != '\0')
396  {
397  int num;
398  gdb_signal_type signal_number;
399  char *one_arg, *endptr;
400  struct cleanup *inner_cleanup;
401 
402  one_arg = extract_arg (&arg);
403  if (one_arg == NULL)
404  break;
405  inner_cleanup = make_cleanup (xfree, one_arg);
406 
407  /* Check for the special flag "all". */
408  if (strcmp (one_arg, "all") == 0)
409  {
410  arg = skip_spaces (arg);
411  if (*arg != '\0' || !first)
412  error (_("'all' cannot be caught with other signals"));
413  *catch_all = 1;
414  gdb_assert (result == NULL);
415  do_cleanups (inner_cleanup);
416  discard_cleanups (cleanup);
417  return NULL;
418  }
419 
420  first = 0;
421 
422  /* Check if the user provided a signal name or a number. */
423  num = (int) strtol (one_arg, &endptr, 0);
424  if (*endptr == '\0')
425  signal_number = gdb_signal_from_command (num);
426  else
427  {
428  signal_number = gdb_signal_from_name (one_arg);
429  if (signal_number == GDB_SIGNAL_UNKNOWN)
430  error (_("Unknown signal name '%s'."), one_arg);
431  }
432 
433  VEC_safe_push (gdb_signal_type, result, signal_number);
434  do_cleanups (inner_cleanup);
435  }
436 
437  discard_cleanups (cleanup);
438  return result;
439 }
440 
441 /* Implement the "catch signal" command. */
442 
443 static void
444 catch_signal_command (char *arg, int from_tty,
445  struct cmd_list_element *command)
446 {
447  int tempflag, catch_all = 0;
448  VEC (gdb_signal_type) *filter;
449 
450  tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
451 
452  arg = skip_spaces (arg);
453 
454  /* The allowed syntax is:
455  catch signal
456  catch signal <name | number> [<name | number> ... <name | number>]
457 
458  Let's check if there's a signal name. */
459 
460  if (arg != NULL)
461  filter = catch_signal_split_args (arg, &catch_all);
462  else
463  filter = NULL;
464 
465  create_signal_catchpoint (tempflag, filter, catch_all);
466 }
467 
468 static void
470 {
471  struct breakpoint_ops *ops;
472 
474 
475  ops = &signal_catchpoint_ops;
476  *ops = base_breakpoint_ops;
486 }
487 
489 
490 void
492 {
494 
495  signal_catch_counts = XCNEWVEC (unsigned int, GDB_SIGNAL_LAST);
496 
497  add_catch_command ("signal", _("\
498 Catch signals by their names and/or numbers.\n\
499 Usage: catch signal [[NAME|NUMBER] [NAME|NUMBER]...|all]\n\
500 Arguments say which signals to catch. If no arguments\n\
501 are given, every \"normal\" signal will be caught.\n\
502 The argument \"all\" means to also catch signals used by GDB.\n\
503 Arguments, if given, should be one or more signal names\n\
504 (if your system supports that), or signal numbers."),
506  signal_completer,
509 }
void get_last_target_status(ptid_t *ptidp, struct target_waitstatus *status)
Definition: infrun.c:3408
void(* print_recreate)(struct breakpoint *, struct ui_file *fp)
Definition: breakpoint.h:575
void * get_cmd_context(struct cmd_list_element *cmd)
Definition: cli-decode.c:147
static unsigned int * signal_catch_counts
static void signal_catchpoint_dtor(struct breakpoint *b)
static int signal_catchpoint_remove_location(struct bp_location *bl)
void signal_catch_update(const unsigned int *info)
Definition: infrun.c:6848
bfd_vma CORE_ADDR
Definition: common-types.h:41
enum gdb_signal gdb_signal_from_command(int num)
Definition: infrun.c:7096
void xfree(void *)
Definition: common-utils.c:97
if(!(yy_init))
Definition: ada-lex.c:1072
#define CATCH_TEMPORARY
Definition: breakpoint.h:1247
enum print_stop_action(* print_it)(struct bpstats *bs)
Definition: breakpoint.h:550
DEF_VEC_I(gdb_signal_type)
void annotate_field(int num)
Definition: annotate.c:188
static void signal_catchpoint_print_one(struct breakpoint *b, struct bp_location **last_loc)
int ui_out_is_mi_like_p(struct ui_out *uiout)
Definition: ui-out.c:655
void(* print_mention)(struct breakpoint *)
Definition: breakpoint.h:572
int(* breakpoint_hit)(const struct bp_location *bl, struct address_space *aspace, CORE_ADDR bp_addr, const struct target_waitstatus *ws)
Definition: breakpoint.h:529
static int signal_catchpoint_breakpoint_hit(const struct bp_location *bl, struct address_space *aspace, CORE_ADDR bp_addr, const struct target_waitstatus *ws)
enum gdb_signal gdb_signal_type
#define VEC_safe_push(T, V, O)
Definition: vec.h:260
char * skip_spaces(char *chp)
Definition: common-utils.c:259
#define _(String)
Definition: gdb_locale.h:40
#define INTERNAL_SIGNAL(x)
void add_catch_command(char *name, char *docstring, cmd_sfunc_ftype *sfunc, completer_ftype *completer, void *user_data_catch, void *user_data_tcatch)
Definition: breakpoint.c:15474
Definition: ui-out.c:99
void ui_out_text(struct ui_out *uiout, const char *string)
Definition: ui-out.c:582
static int signal_catchpoint_explains_signal(struct breakpoint *b, enum gdb_signal sig)
void printf_filtered(const char *format,...)
Definition: utils.c:2388
Definition: ptid.h:35
int(* insert_location)(struct bp_location *)
Definition: breakpoint.h:515
const char *const name
Definition: aarch64-tdep.c:68
#define VEC_iterate(T, V, I, P)
Definition: vec.h:165
void ui_out_field_skip(struct ui_out *uiout, const char *fldname)
Definition: ui-out.c:528
int fputc_unfiltered(int c, struct ui_file *stream)
Definition: utils.c:2169
void initialize_file_ftype(void)
Definition: defs.h:281
void init_catchpoint(struct breakpoint *b, struct gdbarch *gdbarch, int tempflag, char *cond_string, const struct breakpoint_ops *ops)
Definition: breakpoint.c:8439
enum gdb_signal sig
Definition: waitstatus.h:108
void fprintf_unfiltered(struct ui_file *stream, const char *format,...)
Definition: utils.c:2361
#define VEC_length(T, V)
Definition: vec.h:124
struct cleanup * make_cleanup(make_cleanup_ftype *function, void *arg)
Definition: cleanups.c:117
union target_waitstatus::@161 value
#define CATCH_PERMANENT
Definition: breakpoint.h:1246
static const char * signal_to_name_or_int(enum gdb_signal sig)
char * extract_arg(char **arg)
Definition: cli-utils.c:264
struct gdbarch * get_current_arch(void)
Definition: arch-utils.c:781
#define gdb_assert(expr)
Definition: gdb_assert.h:33
static VEC(gdb_signal_type)
const char * gdb_signal_to_name(enum gdb_signal)
Definition: signals.c:78
int(* explains_signal)(struct breakpoint *, enum gdb_signal)
Definition: breakpoint.h:610
struct breakpoint * breakpoint_at
Definition: breakpoint.h:1095
enum gdb_signal gdb_signal_from_name(const char *)
Definition: signals.c:91
print_stop_action
Definition: breakpoint.h:476
struct breakpoint base
const char const char int
Definition: command.h:229
static void signal_catchpoint_print_mention(struct breakpoint *b)
void discard_cleanups(struct cleanup *old_chain)
Definition: cleanups.c:213
initialize_file_ftype _initialize_break_catch_sig
void install_breakpoint(int internal, struct breakpoint *b, int update_gll)
Definition: breakpoint.c:8456
static void signal_catchpoint_print_recreate(struct breakpoint *b, struct ui_file *fp)
enum target_waitkind kind
Definition: waitstatus.h:100
static void catch_signal_command(char *arg, int from_tty, struct cmd_list_element *command)
static enum print_stop_action signal_catchpoint_print_it(bpstat bs)
void get_user_print_options(struct value_print_options *opts)
Definition: valprint.c:129
int(* remove_location)(struct bp_location *)
Definition: breakpoint.h:521
#define VEC_free(T, V)
Definition: vec.h:180
struct breakpoint_ops base_breakpoint_ops
Definition: breakpoint.c:12761
void initialize_breakpoint_ops(void)
Definition: breakpoint.c:15571
#define VEC_cleanup(T)
Definition: vec.h:187
void(* dtor)(struct breakpoint *self)
Definition: breakpoint.h:502
static int signal_catchpoint_insert_location(struct bp_location *bl)
void ui_out_field_string(struct ui_out *uiout, const char *fldname, const char *string)
Definition: ui-out.c:541
void annotate_catchpoint(int num)
Definition: annotate.c:98
void * arg
Definition: cleanups.c:43
struct ui_out * current_uiout
Definition: ui-out.c:233
static void create_signal_catchpoint(int tempflag, VEC(gdb_signal_type)*filter, int catch_all)
struct cleanup * make_cleanup_obstack_free(struct obstack *obstack)
Definition: utils.c:225
static void initialize_signal_catchpoint_ops(void)
struct breakpoint * owner
Definition: breakpoint.h:324
void(* print_one)(struct breakpoint *, struct bp_location **)
Definition: breakpoint.h:554
void error(const char *fmt,...)
Definition: errors.c:38
static struct breakpoint_ops signal_catchpoint_ops
void do_cleanups(struct cleanup *old_chain)
Definition: cleanups.c:175