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