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