Use XCNEW gdbarch_tdep
[external/binutils.git] / gdb / break-catch-syscall.c
1 /* Everything about syscall catchpoints, for GDB.
2
3    Copyright (C) 2009-2017 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 <ctype.h>
22 #include "breakpoint.h"
23 #include "gdbcmd.h"
24 #include "inferior.h"
25 #include "cli/cli-utils.h"
26 #include "annotate.h"
27 #include "mi/mi-common.h"
28 #include "valprint.h"
29 #include "arch-utils.h"
30 #include "observer.h"
31 #include "xml-syscall.h"
32
33 /* An instance of this type is used to represent a syscall catchpoint.
34    It includes a "struct breakpoint" as a kind of base class; users
35    downcast to "struct breakpoint *" when needed.  A breakpoint is
36    really of this type iff its ops pointer points to
37    CATCH_SYSCALL_BREAKPOINT_OPS.  */
38
39 struct syscall_catchpoint
40 {
41   /* The base class.  */
42   struct breakpoint base;
43
44   /* Syscall numbers used for the 'catch syscall' feature.  If no
45      syscall has been specified for filtering, its value is NULL.
46      Otherwise, it holds a list of all syscalls to be caught.  The
47      list elements are allocated with xmalloc.  */
48   VEC(int) *syscalls_to_be_caught;
49 };
50
51 /* Implement the "dtor" breakpoint_ops method for syscall
52    catchpoints.  */
53
54 static void
55 dtor_catch_syscall (struct breakpoint *b)
56 {
57   struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
58
59   VEC_free (int, c->syscalls_to_be_caught);
60
61   base_breakpoint_ops.dtor (b);
62 }
63
64 static const struct inferior_data *catch_syscall_inferior_data = NULL;
65
66 struct catch_syscall_inferior_data
67 {
68   /* We keep a count of the number of times the user has requested a
69      particular syscall to be tracked, and pass this information to the
70      target.  This lets capable targets implement filtering directly.  */
71
72   /* Number of times that "any" syscall is requested.  */
73   int any_syscall_count;
74
75   /* Count of each system call.  */
76   VEC(int) *syscalls_counts;
77
78   /* This counts all syscall catch requests, so we can readily determine
79      if any catching is necessary.  */
80   int total_syscalls_count;
81 };
82
83 static struct catch_syscall_inferior_data*
84 get_catch_syscall_inferior_data (struct inferior *inf)
85 {
86   struct catch_syscall_inferior_data *inf_data;
87
88   inf_data = ((struct catch_syscall_inferior_data *)
89               inferior_data (inf, catch_syscall_inferior_data));
90   if (inf_data == NULL)
91     {
92       inf_data = XCNEW (struct catch_syscall_inferior_data);
93       set_inferior_data (inf, catch_syscall_inferior_data, inf_data);
94     }
95
96   return inf_data;
97 }
98
99 static void
100 catch_syscall_inferior_data_cleanup (struct inferior *inf, void *arg)
101 {
102   xfree (arg);
103 }
104
105
106 /* Implement the "insert" breakpoint_ops method for syscall
107    catchpoints.  */
108
109 static int
110 insert_catch_syscall (struct bp_location *bl)
111 {
112   struct syscall_catchpoint *c = (struct syscall_catchpoint *) bl->owner;
113   struct inferior *inf = current_inferior ();
114   struct catch_syscall_inferior_data *inf_data
115     = get_catch_syscall_inferior_data (inf);
116
117   ++inf_data->total_syscalls_count;
118   if (!c->syscalls_to_be_caught)
119     ++inf_data->any_syscall_count;
120   else
121     {
122       int i, iter;
123
124       for (i = 0;
125            VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
126            i++)
127         {
128           int elem;
129
130           if (iter >= VEC_length (int, inf_data->syscalls_counts))
131             {
132               int old_size = VEC_length (int, inf_data->syscalls_counts);
133               uintptr_t vec_addr_offset
134                 = old_size * ((uintptr_t) sizeof (int));
135               uintptr_t vec_addr;
136               VEC_safe_grow (int, inf_data->syscalls_counts, iter + 1);
137               vec_addr = ((uintptr_t) VEC_address (int,
138                                                   inf_data->syscalls_counts)
139                           + vec_addr_offset);
140               memset ((void *) vec_addr, 0,
141                       (iter + 1 - old_size) * sizeof (int));
142             }
143           elem = VEC_index (int, inf_data->syscalls_counts, iter);
144           VEC_replace (int, inf_data->syscalls_counts, iter, ++elem);
145         }
146     }
147
148   return target_set_syscall_catchpoint (ptid_get_pid (inferior_ptid),
149                                         inf_data->total_syscalls_count != 0,
150                                         inf_data->any_syscall_count,
151                                         VEC_length (int,
152                                                     inf_data->syscalls_counts),
153                                         VEC_address (int,
154                                                      inf_data->syscalls_counts));
155 }
156
157 /* Implement the "remove" breakpoint_ops method for syscall
158    catchpoints.  */
159
160 static int
161 remove_catch_syscall (struct bp_location *bl, enum remove_bp_reason reason)
162 {
163   struct syscall_catchpoint *c = (struct syscall_catchpoint *) bl->owner;
164   struct inferior *inf = current_inferior ();
165   struct catch_syscall_inferior_data *inf_data
166     = get_catch_syscall_inferior_data (inf);
167
168   --inf_data->total_syscalls_count;
169   if (!c->syscalls_to_be_caught)
170     --inf_data->any_syscall_count;
171   else
172     {
173       int i, iter;
174
175       for (i = 0;
176            VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
177            i++)
178         {
179           int elem;
180           if (iter >= VEC_length (int, inf_data->syscalls_counts))
181             /* Shouldn't happen.  */
182             continue;
183           elem = VEC_index (int, inf_data->syscalls_counts, iter);
184           VEC_replace (int, inf_data->syscalls_counts, iter, --elem);
185         }
186     }
187
188   return target_set_syscall_catchpoint (ptid_get_pid (inferior_ptid),
189                                         inf_data->total_syscalls_count != 0,
190                                         inf_data->any_syscall_count,
191                                         VEC_length (int,
192                                                     inf_data->syscalls_counts),
193                                         VEC_address (int,
194                                                      inf_data->syscalls_counts));
195 }
196
197 /* Implement the "breakpoint_hit" breakpoint_ops method for syscall
198    catchpoints.  */
199
200 static int
201 breakpoint_hit_catch_syscall (const struct bp_location *bl,
202                               struct address_space *aspace, CORE_ADDR bp_addr,
203                               const struct target_waitstatus *ws)
204 {
205   /* We must check if we are catching specific syscalls in this
206      breakpoint.  If we are, then we must guarantee that the called
207      syscall is the same syscall we are catching.  */
208   int syscall_number = 0;
209   const struct syscall_catchpoint *c
210     = (const struct syscall_catchpoint *) bl->owner;
211
212   if (ws->kind != TARGET_WAITKIND_SYSCALL_ENTRY
213       && ws->kind != TARGET_WAITKIND_SYSCALL_RETURN)
214     return 0;
215
216   syscall_number = ws->value.syscall_number;
217
218   /* Now, checking if the syscall is the same.  */
219   if (c->syscalls_to_be_caught)
220     {
221       int i, iter;
222
223       for (i = 0;
224            VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
225            i++)
226         if (syscall_number == iter)
227           return 1;
228
229       return 0;
230     }
231
232   return 1;
233 }
234
235 /* Implement the "print_it" breakpoint_ops method for syscall
236    catchpoints.  */
237
238 static enum print_stop_action
239 print_it_catch_syscall (bpstat bs)
240 {
241   struct ui_out *uiout = current_uiout;
242   struct breakpoint *b = bs->breakpoint_at;
243   /* These are needed because we want to know in which state a
244      syscall is.  It can be in the TARGET_WAITKIND_SYSCALL_ENTRY
245      or TARGET_WAITKIND_SYSCALL_RETURN, and depending on it we
246      must print "called syscall" or "returned from syscall".  */
247   ptid_t ptid;
248   struct target_waitstatus last;
249   struct syscall s;
250   struct gdbarch *gdbarch = bs->bp_location_at->gdbarch;
251
252   get_last_target_status (&ptid, &last);
253
254   get_syscall_by_number (gdbarch, last.value.syscall_number, &s);
255
256   annotate_catchpoint (b->number);
257   maybe_print_thread_hit_breakpoint (uiout);
258
259   if (b->disposition == disp_del)
260     uiout->text ("Temporary catchpoint ");
261   else
262     uiout->text ("Catchpoint ");
263   if (uiout->is_mi_like_p ())
264     {
265       uiout->field_string ("reason",
266                            async_reason_lookup (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY
267                                                 ? EXEC_ASYNC_SYSCALL_ENTRY
268                                                 : EXEC_ASYNC_SYSCALL_RETURN));
269       uiout->field_string ("disp", bpdisp_text (b->disposition));
270     }
271   uiout->field_int ("bkptno", b->number);
272
273   if (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY)
274     uiout->text (" (call to syscall ");
275   else
276     uiout->text (" (returned from syscall ");
277
278   if (s.name == NULL || uiout->is_mi_like_p ())
279     uiout->field_int ("syscall-number", last.value.syscall_number);
280   if (s.name != NULL)
281     uiout->field_string ("syscall-name", s.name);
282
283   uiout->text ("), ");
284
285   return PRINT_SRC_AND_LOC;
286 }
287
288 /* Implement the "print_one" breakpoint_ops method for syscall
289    catchpoints.  */
290
291 static void
292 print_one_catch_syscall (struct breakpoint *b,
293                          struct bp_location **last_loc)
294 {
295   struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
296   struct value_print_options opts;
297   struct ui_out *uiout = current_uiout;
298   struct gdbarch *gdbarch = b->loc->gdbarch;
299
300   get_user_print_options (&opts);
301   /* Field 4, the address, is omitted (which makes the columns not
302      line up too nicely with the headers, but the effect is relatively
303      readable).  */
304   if (opts.addressprint)
305     uiout->field_skip ("addr");
306   annotate_field (5);
307
308   if (c->syscalls_to_be_caught
309       && VEC_length (int, c->syscalls_to_be_caught) > 1)
310     uiout->text ("syscalls \"");
311   else
312     uiout->text ("syscall \"");
313
314   if (c->syscalls_to_be_caught)
315     {
316       int i, iter;
317       char *text = xstrprintf ("%s", "");
318
319       for (i = 0;
320            VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
321            i++)
322         {
323           char *x = text;
324           struct syscall s;
325           get_syscall_by_number (gdbarch, iter, &s);
326
327           if (s.name != NULL)
328             text = xstrprintf ("%s%s, ", text, s.name);
329           else
330             text = xstrprintf ("%s%d, ", text, iter);
331
332           /* We have to xfree the last 'text' (now stored at 'x')
333              because xstrprintf dynamically allocates new space for it
334              on every call.  */
335           xfree (x);
336         }
337       /* Remove the last comma.  */
338       text[strlen (text) - 2] = '\0';
339       uiout->field_string ("what", text);
340     }
341   else
342     uiout->field_string ("what", "<any syscall>");
343   uiout->text ("\" ");
344
345   if (uiout->is_mi_like_p ())
346     uiout->field_string ("catch-type", "syscall");
347 }
348
349 /* Implement the "print_mention" breakpoint_ops method for syscall
350    catchpoints.  */
351
352 static void
353 print_mention_catch_syscall (struct breakpoint *b)
354 {
355   struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
356   struct gdbarch *gdbarch = b->loc->gdbarch;
357
358   if (c->syscalls_to_be_caught)
359     {
360       int i, iter;
361
362       if (VEC_length (int, c->syscalls_to_be_caught) > 1)
363         printf_filtered (_("Catchpoint %d (syscalls"), b->number);
364       else
365         printf_filtered (_("Catchpoint %d (syscall"), b->number);
366
367       for (i = 0;
368            VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
369            i++)
370         {
371           struct syscall s;
372           get_syscall_by_number (gdbarch, iter, &s);
373
374           if (s.name)
375             printf_filtered (" '%s' [%d]", s.name, s.number);
376           else
377             printf_filtered (" %d", s.number);
378         }
379       printf_filtered (")");
380     }
381   else
382     printf_filtered (_("Catchpoint %d (any syscall)"),
383                      b->number);
384 }
385
386 /* Implement the "print_recreate" breakpoint_ops method for syscall
387    catchpoints.  */
388
389 static void
390 print_recreate_catch_syscall (struct breakpoint *b, struct ui_file *fp)
391 {
392   struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
393   struct gdbarch *gdbarch = b->loc->gdbarch;
394
395   fprintf_unfiltered (fp, "catch syscall");
396
397   if (c->syscalls_to_be_caught)
398     {
399       int i, iter;
400
401       for (i = 0;
402            VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
403            i++)
404         {
405           struct syscall s;
406
407           get_syscall_by_number (gdbarch, iter, &s);
408           if (s.name)
409             fprintf_unfiltered (fp, " %s", s.name);
410           else
411             fprintf_unfiltered (fp, " %d", s.number);
412         }
413     }
414   print_recreate_thread (b, fp);
415 }
416
417 /* The breakpoint_ops structure to be used in syscall catchpoints.  */
418
419 static struct breakpoint_ops catch_syscall_breakpoint_ops;
420
421 /* Returns non-zero if 'b' is a syscall catchpoint.  */
422
423 static int
424 syscall_catchpoint_p (struct breakpoint *b)
425 {
426   return (b->ops == &catch_syscall_breakpoint_ops);
427 }
428
429 static void
430 create_syscall_event_catchpoint (int tempflag, VEC(int) *filter,
431                                  const struct breakpoint_ops *ops)
432 {
433   struct syscall_catchpoint *c;
434   struct gdbarch *gdbarch = get_current_arch ();
435
436   c = new syscall_catchpoint ();
437   init_catchpoint (&c->base, gdbarch, tempflag, NULL, ops);
438   c->syscalls_to_be_caught = filter;
439
440   install_breakpoint (0, &c->base, 1);
441 }
442
443 /* Splits the argument using space as delimiter.  Returns an xmalloc'd
444    filter list, or NULL if no filtering is required.  */
445 static VEC(int) *
446 catch_syscall_split_args (char *arg)
447 {
448   VEC(int) *result = NULL;
449   struct cleanup *cleanup = make_cleanup (VEC_cleanup (int), &result);
450   struct gdbarch *gdbarch = target_gdbarch ();
451
452   while (*arg != '\0')
453     {
454       int i, syscall_number;
455       char *endptr;
456       char cur_name[128];
457       struct syscall s;
458
459       /* Skip whitespace.  */
460       arg = skip_spaces (arg);
461
462       for (i = 0; i < 127 && arg[i] && !isspace (arg[i]); ++i)
463         cur_name[i] = arg[i];
464       cur_name[i] = '\0';
465       arg += i;
466
467       /* Check if the user provided a syscall name, group, or a number.  */
468       syscall_number = (int) strtol (cur_name, &endptr, 0);
469       if (*endptr == '\0')
470         {
471           get_syscall_by_number (gdbarch, syscall_number, &s);
472           VEC_safe_push (int, result, s.number);
473         }
474       else if (startswith (cur_name, "g:")
475                || startswith (cur_name, "group:"))
476         {
477           /* We have a syscall group.  Let's expand it into a syscall
478              list before inserting.  */
479           struct syscall *syscall_list;
480           const char *group_name;
481
482           /* Skip over "g:" and "group:" prefix strings.  */
483           group_name = strchr (cur_name, ':') + 1;
484
485           syscall_list = get_syscalls_by_group (gdbarch, group_name);
486
487           if (syscall_list == NULL)
488             error (_("Unknown syscall group '%s'."), group_name);
489
490           for (i = 0; syscall_list[i].name != NULL; i++)
491             {
492               /* Insert each syscall that are part of the group.  No
493                  need to check if it is valid.  */
494               VEC_safe_push (int, result, syscall_list[i].number);
495             }
496
497           xfree (syscall_list);
498         }
499       else
500         {
501           /* We have a name.  Let's check if it's valid and convert it
502              to a number.  */
503           get_syscall_by_name (gdbarch, cur_name, &s);
504
505           if (s.number == UNKNOWN_SYSCALL)
506             /* Here we have to issue an error instead of a warning,
507                because GDB cannot do anything useful if there's no
508                syscall number to be caught.  */
509             error (_("Unknown syscall name '%s'."), cur_name);
510
511           /* Ok, it's valid.  */
512           VEC_safe_push (int, result, s.number);
513         }
514     }
515
516   discard_cleanups (cleanup);
517   return result;
518 }
519
520 /* Implement the "catch syscall" command.  */
521
522 static void
523 catch_syscall_command_1 (char *arg, int from_tty, 
524                          struct cmd_list_element *command)
525 {
526   int tempflag;
527   VEC(int) *filter;
528   struct syscall s;
529   struct gdbarch *gdbarch = get_current_arch ();
530
531   /* Checking if the feature if supported.  */
532   if (gdbarch_get_syscall_number_p (gdbarch) == 0)
533     error (_("The feature 'catch syscall' is not supported on \
534 this architecture yet."));
535
536   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
537
538   arg = skip_spaces (arg);
539
540   /* We need to do this first "dummy" translation in order
541      to get the syscall XML file loaded or, most important,
542      to display a warning to the user if there's no XML file
543      for his/her architecture.  */
544   get_syscall_by_number (gdbarch, 0, &s);
545
546   /* The allowed syntax is:
547      catch syscall
548      catch syscall <name | number> [<name | number> ... <name | number>]
549
550      Let's check if there's a syscall name.  */
551
552   if (arg != NULL)
553     filter = catch_syscall_split_args (arg);
554   else
555     filter = NULL;
556
557   create_syscall_event_catchpoint (tempflag, filter,
558                                    &catch_syscall_breakpoint_ops);
559 }
560
561
562 /* Returns 0 if 'bp' is NOT a syscall catchpoint,
563    non-zero otherwise.  */
564 static int
565 is_syscall_catchpoint_enabled (struct breakpoint *bp)
566 {
567   if (syscall_catchpoint_p (bp)
568       && bp->enable_state != bp_disabled
569       && bp->enable_state != bp_call_disabled)
570     return 1;
571   else
572     return 0;
573 }
574
575 int
576 catch_syscall_enabled (void)
577 {
578   struct catch_syscall_inferior_data *inf_data
579     = get_catch_syscall_inferior_data (current_inferior ());
580
581   return inf_data->total_syscalls_count != 0;
582 }
583
584 /* Helper function for catching_syscall_number.  If B is a syscall
585    catchpoint for SYSCALL_NUMBER, return 1 (which will make
586    'breakpoint_find_if' return).  Otherwise, return 0.  */
587
588 static int
589 catching_syscall_number_1 (struct breakpoint *b,
590                            void *data)
591 {
592   int syscall_number = (int) (uintptr_t) data;
593
594   if (is_syscall_catchpoint_enabled (b))
595     {
596       struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
597
598       if (c->syscalls_to_be_caught)
599         {
600           int i, iter;
601           for (i = 0;
602                VEC_iterate (int, c->syscalls_to_be_caught, i, iter);
603                i++)
604             if (syscall_number == iter)
605               return 1;
606         }
607       else
608         return 1;
609     }
610
611   return 0;
612 }
613
614 int
615 catching_syscall_number (int syscall_number)
616 {
617   struct breakpoint *b = breakpoint_find_if (catching_syscall_number_1,
618                                          (void *) (uintptr_t) syscall_number);
619
620   return b != NULL;
621 }
622
623 /* Complete syscall names.  Used by "catch syscall".  */
624 static VEC (char_ptr) *
625 catch_syscall_completer (struct cmd_list_element *cmd,
626                          const char *text, const char *word)
627 {
628   struct gdbarch *gdbarch = get_current_arch ();
629   struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
630   VEC (char_ptr) *group_retlist = NULL;
631   VEC (char_ptr) *syscall_retlist = NULL;
632   VEC (char_ptr) *retlist = NULL;
633   const char **group_list = NULL;
634   const char **syscall_list = NULL;
635   const char *prefix;
636   int i;
637
638   /* Completion considers ':' to be a word separator, so we use this to
639      verify whether the previous word was a group prefix.  If so, we
640      build the completion list using group names only.  */
641   for (prefix = word; prefix != text && prefix[-1] != ' '; prefix--)
642     ;
643
644   if (startswith (prefix, "g:") || startswith (prefix, "group:"))
645     {
646       /* Perform completion inside 'group:' namespace only.  */
647       group_list = get_syscall_group_names (gdbarch);
648       retlist = (group_list == NULL
649                  ? NULL : complete_on_enum (group_list, word, word));
650     }
651   else
652     {
653       /* Complete with both, syscall names and groups.  */
654       syscall_list = get_syscall_names (gdbarch);
655       group_list = get_syscall_group_names (gdbarch);
656
657       /* Append "group:" prefix to syscall groups.  */
658       for (i = 0; group_list[i] != NULL; i++)
659         {
660           char *prefixed_group = xstrprintf ("group:%s", group_list[i]);
661
662           group_list[i] = prefixed_group;
663           make_cleanup (xfree, prefixed_group);
664         }
665
666       syscall_retlist = ((syscall_list == NULL)
667                          ? NULL : complete_on_enum (syscall_list, word, word));
668       group_retlist = ((group_list == NULL)
669                        ? NULL : complete_on_enum (group_list, word, word));
670
671       retlist = VEC_merge (char_ptr, syscall_retlist, group_retlist);
672     }
673
674   VEC_free (char_ptr, syscall_retlist);
675   VEC_free (char_ptr, group_retlist);
676   xfree (syscall_list);
677   xfree (group_list);
678   do_cleanups (cleanups);
679
680   return retlist;
681 }
682
683 static void
684 clear_syscall_counts (struct inferior *inf)
685 {
686   struct catch_syscall_inferior_data *inf_data
687     = get_catch_syscall_inferior_data (inf);
688
689   inf_data->total_syscalls_count = 0;
690   inf_data->any_syscall_count = 0;
691   VEC_free (int, inf_data->syscalls_counts);
692 }
693
694 static void
695 initialize_syscall_catchpoint_ops (void)
696 {
697   struct breakpoint_ops *ops;
698
699   initialize_breakpoint_ops ();
700
701   /* Syscall catchpoints.  */
702   ops = &catch_syscall_breakpoint_ops;
703   *ops = base_breakpoint_ops;
704   ops->dtor = dtor_catch_syscall;
705   ops->insert_location = insert_catch_syscall;
706   ops->remove_location = remove_catch_syscall;
707   ops->breakpoint_hit = breakpoint_hit_catch_syscall;
708   ops->print_it = print_it_catch_syscall;
709   ops->print_one = print_one_catch_syscall;
710   ops->print_mention = print_mention_catch_syscall;
711   ops->print_recreate = print_recreate_catch_syscall;
712 }
713
714 initialize_file_ftype _initialize_break_catch_syscall;
715
716 void
717 _initialize_break_catch_syscall (void)
718 {
719   initialize_syscall_catchpoint_ops ();
720
721   observer_attach_inferior_exit (clear_syscall_counts);
722   catch_syscall_inferior_data
723     = register_inferior_data_with_cleanup (NULL,
724                                            catch_syscall_inferior_data_cleanup);
725
726   add_catch_command ("syscall", _("\
727 Catch system calls by their names, groups and/or numbers.\n\
728 Arguments say which system calls to catch.  If no arguments are given,\n\
729 every system call will be caught.  Arguments, if given, should be one\n\
730 or more system call names (if your system supports that), system call\n\
731 groups or system call numbers."),
732                      catch_syscall_command_1,
733                      catch_syscall_completer,
734                      CATCH_PERMANENT,
735                      CATCH_TEMPORARY);
736 }