]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/break-catch-syscall.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / break-catch-syscall.c
CommitLineData
10304ef3
SDJ
1/* Everything about syscall catchpoints, for GDB.
2
1d506c26 3 Copyright (C) 2009-2024 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"
4de283e4
TT
25#include "cli/cli-utils.h"
26#include "annotate.h"
10304ef3 27#include "mi/mi-common.h"
d55e5aa6 28#include "valprint.h"
4de283e4
TT
29#include "arch-utils.h"
30#include "observable.h"
10304ef3 31#include "xml-syscall.h"
7f6aba03 32#include "cli/cli-style.h"
0f8e2034 33#include "cli/cli-decode.h"
10304ef3 34
3aca48d3
TT
35/* An instance of this type is used to represent a syscall
36 catchpoint. */
10304ef3 37
c5eab52d 38struct syscall_catchpoint : public catchpoint
10304ef3 39{
c5eab52d
TT
40 syscall_catchpoint (struct gdbarch *gdbarch, bool tempflag,
41 std::vector<int> &&calls)
42 : catchpoint (gdbarch, tempflag, nullptr),
73063f51 43 syscalls_to_be_caught (std::move (calls))
6c91c7de
TT
44 {
45 }
46
3aca48d3
TT
47 int insert_location (struct bp_location *) override;
48 int remove_location (struct bp_location *,
49 enum remove_bp_reason reason) override;
50 int breakpoint_hit (const struct bp_location *bl,
51 const address_space *aspace,
52 CORE_ADDR bp_addr,
53 const target_waitstatus &ws) override;
7bd86313 54 enum print_stop_action print_it (const bpstat *bs) const override;
5e632eca 55 bool print_one (const bp_location **) const override;
b713485d 56 void print_mention () const override;
4d1ae558 57 void print_recreate (struct ui_file *fp) const override;
3aca48d3 58
10304ef3 59 /* Syscall numbers used for the 'catch syscall' feature. If no
e12c9b7a
TT
60 syscall has been specified for filtering, it is empty.
61 Otherwise, it holds a list of all syscalls to be caught. */
62 std::vector<int> syscalls_to_be_caught;
10304ef3
SDJ
63};
64
10304ef3
SDJ
65struct catch_syscall_inferior_data
66{
67 /* We keep a count of the number of times the user has requested a
68 particular syscall to be tracked, and pass this information to the
69 target. This lets capable targets implement filtering directly. */
70
71 /* Number of times that "any" syscall is requested. */
72 int any_syscall_count;
73
74 /* Count of each system call. */
b6f48cb0 75 std::vector<int> syscalls_counts;
10304ef3
SDJ
76
77 /* This counts all syscall catch requests, so we can readily determine
78 if any catching is necessary. */
79 int total_syscalls_count;
80};
81
08b8a139 82static const registry<inferior>::key<catch_syscall_inferior_data>
6ae614f6
TT
83 catch_syscall_inferior_data;
84
b6f48cb0 85static struct catch_syscall_inferior_data *
10304ef3
SDJ
86get_catch_syscall_inferior_data (struct inferior *inf)
87{
88 struct catch_syscall_inferior_data *inf_data;
89
6ae614f6 90 inf_data = catch_syscall_inferior_data.get (inf);
10304ef3 91 if (inf_data == NULL)
6ae614f6 92 inf_data = catch_syscall_inferior_data.emplace (inf);
10304ef3
SDJ
93
94 return inf_data;
95}
96
3aca48d3 97/* Implement the "insert" method for syscall catchpoints. */
10304ef3 98
3aca48d3
TT
99int
100syscall_catchpoint::insert_location (struct bp_location *bl)
10304ef3 101{
10304ef3
SDJ
102 struct inferior *inf = current_inferior ();
103 struct catch_syscall_inferior_data *inf_data
104 = get_catch_syscall_inferior_data (inf);
105
106 ++inf_data->total_syscalls_count;
3aca48d3 107 if (syscalls_to_be_caught.empty ())
10304ef3
SDJ
108 ++inf_data->any_syscall_count;
109 else
110 {
3aca48d3 111 for (int iter : syscalls_to_be_caught)
10304ef3 112 {
b6f48cb0
TT
113 if (iter >= inf_data->syscalls_counts.size ())
114 inf_data->syscalls_counts.resize (iter + 1);
115 ++inf_data->syscalls_counts[iter];
10304ef3
SDJ
116 }
117 }
118
e99b03dc 119 return target_set_syscall_catchpoint (inferior_ptid.pid (),
10304ef3
SDJ
120 inf_data->total_syscalls_count != 0,
121 inf_data->any_syscall_count,
649a140c 122 inf_data->syscalls_counts);
10304ef3
SDJ
123}
124
3aca48d3 125/* Implement the "remove" method for syscall catchpoints. */
10304ef3 126
3aca48d3
TT
127int
128syscall_catchpoint::remove_location (struct bp_location *bl,
129 enum remove_bp_reason reason)
10304ef3 130{
10304ef3
SDJ
131 struct inferior *inf = current_inferior ();
132 struct catch_syscall_inferior_data *inf_data
133 = get_catch_syscall_inferior_data (inf);
134
135 --inf_data->total_syscalls_count;
3aca48d3 136 if (syscalls_to_be_caught.empty ())
10304ef3
SDJ
137 --inf_data->any_syscall_count;
138 else
139 {
3aca48d3 140 for (int iter : syscalls_to_be_caught)
10304ef3 141 {
b6f48cb0 142 if (iter >= inf_data->syscalls_counts.size ())
10304ef3
SDJ
143 /* Shouldn't happen. */
144 continue;
dda83cd7
SM
145 --inf_data->syscalls_counts[iter];
146 }
10304ef3
SDJ
147 }
148
e99b03dc 149 return target_set_syscall_catchpoint (inferior_ptid.pid (),
10304ef3
SDJ
150 inf_data->total_syscalls_count != 0,
151 inf_data->any_syscall_count,
649a140c 152 inf_data->syscalls_counts);
10304ef3
SDJ
153}
154
3aca48d3 155/* Implement the "breakpoint_hit" method for syscall catchpoints. */
10304ef3 156
3aca48d3
TT
157int
158syscall_catchpoint::breakpoint_hit (const struct bp_location *bl,
159 const address_space *aspace,
160 CORE_ADDR bp_addr,
161 const target_waitstatus &ws)
10304ef3
SDJ
162{
163 /* We must check if we are catching specific syscalls in this
164 breakpoint. If we are, then we must guarantee that the called
165 syscall is the same syscall we are catching. */
166 int syscall_number = 0;
10304ef3 167
c272a98c
SM
168 if (ws.kind () != TARGET_WAITKIND_SYSCALL_ENTRY
169 && ws.kind () != TARGET_WAITKIND_SYSCALL_RETURN)
10304ef3
SDJ
170 return 0;
171
c272a98c 172 syscall_number = ws.syscall_number ();
10304ef3
SDJ
173
174 /* Now, checking if the syscall is the same. */
3aca48d3 175 if (!syscalls_to_be_caught.empty ())
10304ef3 176 {
3aca48d3 177 for (int iter : syscalls_to_be_caught)
10304ef3
SDJ
178 if (syscall_number == iter)
179 return 1;
180
181 return 0;
182 }
183
184 return 1;
185}
186
3aca48d3 187/* Implement the "print_it" method for syscall catchpoints. */
10304ef3 188
3aca48d3 189enum print_stop_action
7bd86313 190syscall_catchpoint::print_it (const bpstat *bs) const
10304ef3
SDJ
191{
192 struct ui_out *uiout = current_uiout;
10304ef3
SDJ
193 /* These are needed because we want to know in which state a
194 syscall is. It can be in the TARGET_WAITKIND_SYSCALL_ENTRY
195 or TARGET_WAITKIND_SYSCALL_RETURN, and depending on it we
196 must print "called syscall" or "returned from syscall". */
10304ef3
SDJ
197 struct target_waitstatus last;
198 struct syscall s;
10304ef3 199
5b6d1e4f 200 get_last_target_status (nullptr, nullptr, &last);
10304ef3 201
183be222 202 get_syscall_by_number (gdbarch, last.syscall_number (), &s);
10304ef3 203
dbaa3bf6 204 annotate_catchpoint (this->number);
f303dbd6 205 maybe_print_thread_hit_breakpoint (uiout);
10304ef3 206
dbaa3bf6 207 if (this->disposition == disp_del)
112e8700 208 uiout->text ("Temporary catchpoint ");
10304ef3 209 else
112e8700
SM
210 uiout->text ("Catchpoint ");
211 if (uiout->is_mi_like_p ())
10304ef3 212 {
112e8700 213 uiout->field_string ("reason",
183be222 214 async_reason_lookup (last.kind () == TARGET_WAITKIND_SYSCALL_ENTRY
10304ef3
SDJ
215 ? EXEC_ASYNC_SYSCALL_ENTRY
216 : EXEC_ASYNC_SYSCALL_RETURN));
dbaa3bf6 217 uiout->field_string ("disp", bpdisp_text (this->disposition));
10304ef3 218 }
78805ff8 219 print_num_locno (bs, uiout);
10304ef3 220
183be222 221 if (last.kind () == TARGET_WAITKIND_SYSCALL_ENTRY)
112e8700 222 uiout->text (" (call to syscall ");
10304ef3 223 else
112e8700 224 uiout->text (" (returned from syscall ");
10304ef3 225
112e8700 226 if (s.name == NULL || uiout->is_mi_like_p ())
183be222 227 uiout->field_signed ("syscall-number", last.syscall_number ());
10304ef3 228 if (s.name != NULL)
112e8700 229 uiout->field_string ("syscall-name", s.name);
10304ef3 230
112e8700 231 uiout->text ("), ");
10304ef3
SDJ
232
233 return PRINT_SRC_AND_LOC;
234}
235
3aca48d3 236/* Implement the "print_one" method for syscall catchpoints. */
10304ef3 237
3aca48d3 238bool
5e632eca 239syscall_catchpoint::print_one (const bp_location **last_loc) const
10304ef3 240{
10304ef3
SDJ
241 struct value_print_options opts;
242 struct ui_out *uiout = current_uiout;
10304ef3
SDJ
243
244 get_user_print_options (&opts);
245 /* Field 4, the address, is omitted (which makes the columns not
246 line up too nicely with the headers, but the effect is relatively
247 readable). */
248 if (opts.addressprint)
112e8700 249 uiout->field_skip ("addr");
10304ef3
SDJ
250 annotate_field (5);
251
3aca48d3 252 if (syscalls_to_be_caught.size () > 1)
112e8700 253 uiout->text ("syscalls \"");
10304ef3 254 else
112e8700 255 uiout->text ("syscall \"");
10304ef3 256
3aca48d3 257 if (!syscalls_to_be_caught.empty ())
10304ef3 258 {
570bc793 259 std::string text;
10304ef3 260
570bc793 261 bool first = true;
3aca48d3 262 for (int iter : syscalls_to_be_caught)
dda83cd7 263 {
dda83cd7
SM
264 struct syscall s;
265 get_syscall_by_number (gdbarch, iter, &s);
10304ef3 266
570bc793
TT
267 if (!first)
268 text += ", ";
269 first = false;
270
dda83cd7 271 if (s.name != NULL)
570bc793 272 text += s.name;
dda83cd7 273 else
570bc793 274 text += std::to_string (iter);
dda83cd7 275 }
570bc793 276 uiout->field_string ("what", text.c_str ());
10304ef3
SDJ
277 }
278 else
7f6aba03 279 uiout->field_string ("what", "<any syscall>", metadata_style.style ());
112e8700 280 uiout->text ("\" ");
10304ef3 281
112e8700
SM
282 if (uiout->is_mi_like_p ())
283 uiout->field_string ("catch-type", "syscall");
c01e038b
TT
284
285 return true;
10304ef3
SDJ
286}
287
3aca48d3 288/* Implement the "print_mention" method for syscall catchpoints. */
10304ef3 289
3aca48d3 290void
b713485d 291syscall_catchpoint::print_mention () const
10304ef3 292{
3aca48d3 293 if (!syscalls_to_be_caught.empty ())
10304ef3 294 {
3aca48d3
TT
295 if (syscalls_to_be_caught.size () > 1)
296 gdb_printf (_("Catchpoint %d (syscalls"), number);
10304ef3 297 else
3aca48d3 298 gdb_printf (_("Catchpoint %d (syscall"), number);
10304ef3 299
3aca48d3 300 for (int iter : syscalls_to_be_caught)
dda83cd7
SM
301 {
302 struct syscall s;
303 get_syscall_by_number (gdbarch, iter, &s);
304
305 if (s.name != NULL)
6cb06a8c 306 gdb_printf (" '%s' [%d]", s.name, s.number);
dda83cd7 307 else
6cb06a8c 308 gdb_printf (" %d", s.number);
dda83cd7 309 }
6cb06a8c 310 gdb_printf (")");
10304ef3
SDJ
311 }
312 else
3aca48d3 313 gdb_printf (_("Catchpoint %d (any syscall)"), number);
10304ef3
SDJ
314}
315
3aca48d3 316/* Implement the "print_recreate" method for syscall catchpoints. */
10304ef3 317
3aca48d3 318void
4d1ae558 319syscall_catchpoint::print_recreate (struct ui_file *fp) const
10304ef3 320{
6cb06a8c 321 gdb_printf (fp, "catch syscall");
10304ef3 322
3aca48d3 323 for (int iter : syscalls_to_be_caught)
10304ef3 324 {
e12c9b7a 325 struct syscall s;
10304ef3 326
e12c9b7a
TT
327 get_syscall_by_number (gdbarch, iter, &s);
328 if (s.name != NULL)
6cb06a8c 329 gdb_printf (fp, " %s", s.name);
e12c9b7a 330 else
6cb06a8c 331 gdb_printf (fp, " %d", s.number);
10304ef3 332 }
e12c9b7a 333
04d0163c 334 print_recreate_thread (fp);
10304ef3
SDJ
335}
336
10304ef3
SDJ
337/* Returns non-zero if 'b' is a syscall catchpoint. */
338
339static int
340syscall_catchpoint_p (struct breakpoint *b)
341{
3aca48d3 342 return dynamic_cast<syscall_catchpoint *> (b) != nullptr;
10304ef3
SDJ
343}
344
345static void
3aca48d3 346create_syscall_event_catchpoint (int tempflag, std::vector<int> &&filter)
10304ef3 347{
10304ef3
SDJ
348 struct gdbarch *gdbarch = get_current_arch ();
349
6c91c7de 350 std::unique_ptr<syscall_catchpoint> c
c5eab52d 351 (new syscall_catchpoint (gdbarch, tempflag, std::move (filter)));
10304ef3 352
b270e6f9 353 install_breakpoint (0, std::move (c), 1);
10304ef3
SDJ
354}
355
e12c9b7a
TT
356/* Splits the argument using space as delimiter. */
357
358static std::vector<int>
eb4c3f4a 359catch_syscall_split_args (const char *arg)
10304ef3 360{
e12c9b7a 361 std::vector<int> result;
99d9c3b9 362 gdbarch *gdbarch = current_inferior ()->arch ();
10304ef3
SDJ
363
364 while (*arg != '\0')
365 {
366 int i, syscall_number;
367 char *endptr;
368 char cur_name[128];
369 struct syscall s;
370
371 /* Skip whitespace. */
372 arg = skip_spaces (arg);
373
374 for (i = 0; i < 127 && arg[i] && !isspace (arg[i]); ++i)
375 cur_name[i] = arg[i];
376 cur_name[i] = '\0';
377 arg += i;
378
e3487908 379 /* Check if the user provided a syscall name, group, or a number. */
10304ef3
SDJ
380 syscall_number = (int) strtol (cur_name, &endptr, 0);
381 if (*endptr == '\0')
e3487908 382 {
0e857c82
TV
383 if (syscall_number < 0)
384 error (_("Unknown syscall number '%d'."), syscall_number);
e3487908 385 get_syscall_by_number (gdbarch, syscall_number, &s);
e12c9b7a 386 result.push_back (s.number);
e3487908
GKB
387 }
388 else if (startswith (cur_name, "g:")
389 || startswith (cur_name, "group:"))
390 {
391 /* We have a syscall group. Let's expand it into a syscall
392 list before inserting. */
e3487908
GKB
393 const char *group_name;
394
395 /* Skip over "g:" and "group:" prefix strings. */
396 group_name = strchr (cur_name, ':') + 1;
397
4794efbf 398 if (!get_syscalls_by_group (gdbarch, group_name, &result))
e3487908 399 error (_("Unknown syscall group '%s'."), group_name);
e3487908 400 }
10304ef3
SDJ
401 else
402 {
e9076973
JB
403 /* We have a name. Let's check if it's valid and fetch a
404 list of matching numbers. */
405 if (!get_syscalls_by_name (gdbarch, cur_name, &result))
10304ef3
SDJ
406 /* Here we have to issue an error instead of a warning,
407 because GDB cannot do anything useful if there's no
408 syscall number to be caught. */
409 error (_("Unknown syscall name '%s'."), cur_name);
e3487908 410 }
10304ef3
SDJ
411 }
412
10304ef3
SDJ
413 return result;
414}
415
416/* Implement the "catch syscall" command. */
417
418static void
eb4c3f4a 419catch_syscall_command_1 (const char *arg, int from_tty,
10304ef3
SDJ
420 struct cmd_list_element *command)
421{
422 int tempflag;
e12c9b7a 423 std::vector<int> filter;
10304ef3
SDJ
424 struct syscall s;
425 struct gdbarch *gdbarch = get_current_arch ();
426
427 /* Checking if the feature if supported. */
428 if (gdbarch_get_syscall_number_p (gdbarch) == 0)
429 error (_("The feature 'catch syscall' is not supported on \
430this architecture yet."));
431
0f8e2034 432 tempflag = command->context () == CATCH_TEMPORARY;
10304ef3
SDJ
433
434 arg = skip_spaces (arg);
435
436 /* We need to do this first "dummy" translation in order
437 to get the syscall XML file loaded or, most important,
438 to display a warning to the user if there's no XML file
439 for his/her architecture. */
440 get_syscall_by_number (gdbarch, 0, &s);
441
442 /* The allowed syntax is:
443 catch syscall
444 catch syscall <name | number> [<name | number> ... <name | number>]
445
446 Let's check if there's a syscall name. */
447
448 if (arg != NULL)
449 filter = catch_syscall_split_args (arg);
10304ef3 450
3aca48d3 451 create_syscall_event_catchpoint (tempflag, std::move (filter));
10304ef3
SDJ
452}
453
454
455/* Returns 0 if 'bp' is NOT a syscall catchpoint,
456 non-zero otherwise. */
457static int
458is_syscall_catchpoint_enabled (struct breakpoint *bp)
459{
460 if (syscall_catchpoint_p (bp)
461 && bp->enable_state != bp_disabled
462 && bp->enable_state != bp_call_disabled)
463 return 1;
464 else
465 return 0;
466}
467
f087eb27
SM
468/* See breakpoint.h. */
469
470bool
471catch_syscall_enabled ()
10304ef3
SDJ
472{
473 struct catch_syscall_inferior_data *inf_data
474 = get_catch_syscall_inferior_data (current_inferior ());
475
476 return inf_data->total_syscalls_count != 0;
477}
478
9fe3819e
SM
479/* Helper function for catching_syscall_number. return true if B is a syscall
480 catchpoint for SYSCALL_NUMBER, else false. */
10304ef3 481
9fe3819e
SM
482static bool
483catching_syscall_number_1 (struct breakpoint *b, int syscall_number)
10304ef3 484{
10304ef3
SDJ
485 if (is_syscall_catchpoint_enabled (b))
486 {
8e032233
TT
487 syscall_catchpoint *c
488 = gdb::checked_static_cast<syscall_catchpoint *> (b);
10304ef3 489
e12c9b7a 490 if (!c->syscalls_to_be_caught.empty ())
10304ef3 491 {
e12c9b7a 492 for (int iter : c->syscalls_to_be_caught)
10304ef3 493 if (syscall_number == iter)
9fe3819e 494 return true;
10304ef3
SDJ
495 }
496 else
9fe3819e 497 return true;
10304ef3
SDJ
498 }
499
9fe3819e 500 return false;
10304ef3
SDJ
501}
502
9fe3819e 503bool
10304ef3
SDJ
504catching_syscall_number (int syscall_number)
505{
a1decfc1
SM
506 for (breakpoint &b : all_breakpoints ())
507 if (catching_syscall_number_1 (&b, syscall_number))
9fe3819e 508 return true;
10304ef3 509
9fe3819e 510 return false;
10304ef3
SDJ
511}
512
513/* Complete syscall names. Used by "catch syscall". */
eb3ff9a5
PA
514
515static void
10304ef3 516catch_syscall_completer (struct cmd_list_element *cmd,
eb3ff9a5 517 completion_tracker &tracker,
dda83cd7 518 const char *text, const char *word)
10304ef3 519{
e3487908 520 struct gdbarch *gdbarch = get_current_arch ();
3d415c26 521 gdb::unique_xmalloc_ptr<const char *> group_list;
e3487908 522 const char *prefix;
e3487908
GKB
523
524 /* Completion considers ':' to be a word separator, so we use this to
525 verify whether the previous word was a group prefix. If so, we
526 build the completion list using group names only. */
527 for (prefix = word; prefix != text && prefix[-1] != ' '; prefix--)
528 ;
529
530 if (startswith (prefix, "g:") || startswith (prefix, "group:"))
531 {
532 /* Perform completion inside 'group:' namespace only. */
3d415c26 533 group_list.reset (get_syscall_group_names (gdbarch));
eb3ff9a5 534 if (group_list != NULL)
3d415c26 535 complete_on_enum (tracker, group_list.get (), word, word);
e3487908
GKB
536 }
537 else
538 {
539 /* Complete with both, syscall names and groups. */
3d415c26
TT
540 gdb::unique_xmalloc_ptr<const char *> syscall_list
541 (get_syscall_names (gdbarch));
542 group_list.reset (get_syscall_group_names (gdbarch));
543
544 const char **group_ptr = group_list.get ();
545
546 /* Hold on to strings while we're using them. */
547 std::vector<std::string> holders;
e3487908
GKB
548
549 /* Append "group:" prefix to syscall groups. */
9a93831c
SM
550 for (int i = 0; group_ptr[i] != NULL; i++)
551 holders.push_back (string_printf ("group:%s", group_ptr[i]));
e3487908 552
9a93831c
SM
553 for (int i = 0; group_ptr[i] != NULL; i++)
554 group_ptr[i] = holders[i].c_str ();
e3487908 555
eb3ff9a5 556 if (syscall_list != NULL)
3d415c26 557 complete_on_enum (tracker, syscall_list.get (), word, word);
eb3ff9a5 558 if (group_list != NULL)
3d415c26 559 complete_on_enum (tracker, group_ptr, word, word);
e3487908 560 }
10304ef3
SDJ
561}
562
563static void
564clear_syscall_counts (struct inferior *inf)
565{
566 struct catch_syscall_inferior_data *inf_data
567 = get_catch_syscall_inferior_data (inf);
568
569 inf_data->total_syscalls_count = 0;
570 inf_data->any_syscall_count = 0;
b6f48cb0 571 inf_data->syscalls_counts.clear ();
10304ef3
SDJ
572}
573
6c265988 574void _initialize_break_catch_syscall ();
10304ef3 575void
6c265988 576_initialize_break_catch_syscall ()
10304ef3 577{
c90e7d63
SM
578 gdb::observers::inferior_exit.attach (clear_syscall_counts,
579 "break-catch-syscall");
10304ef3
SDJ
580
581 add_catch_command ("syscall", _("\
e3487908
GKB
582Catch system calls by their names, groups and/or numbers.\n\
583Arguments say which system calls to catch. If no arguments are given,\n\
584every system call will be caught. Arguments, if given, should be one\n\
585or more system call names (if your system supports that), system call\n\
586groups or system call numbers."),
10304ef3
SDJ
587 catch_syscall_command_1,
588 catch_syscall_completer,
589 CATCH_PERMANENT,
590 CATCH_TEMPORARY);
591}