1 /* Everything about syscall catchpoints, for GDB.
3 Copyright (C) 2009-2017 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
22 #include "breakpoint.h"
25 #include "cli/cli-utils.h"
27 #include "mi/mi-common.h"
29 #include "arch-utils.h"
31 #include "xml-syscall.h"
33 /* An instance of this type is used to represent a syscall catchpoint.
34 A breakpoint is really of this type iff its ops pointer points to
35 CATCH_SYSCALL_BREAKPOINT_OPS. */
37 struct syscall_catchpoint
: public breakpoint
39 /* Syscall numbers used for the 'catch syscall' feature. If no
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
;
45 static const struct inferior_data
*catch_syscall_inferior_data
= NULL
;
47 struct catch_syscall_inferior_data
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. */
53 /* Number of times that "any" syscall is requested. */
54 int any_syscall_count
;
56 /* Count of each system call. */
57 std::vector
<int> syscalls_counts
;
59 /* This counts all syscall catch requests, so we can readily determine
60 if any catching is necessary. */
61 int total_syscalls_count
;
64 static struct catch_syscall_inferior_data
*
65 get_catch_syscall_inferior_data (struct inferior
*inf
)
67 struct catch_syscall_inferior_data
*inf_data
;
69 inf_data
= ((struct catch_syscall_inferior_data
*)
70 inferior_data (inf
, catch_syscall_inferior_data
));
73 inf_data
= new struct catch_syscall_inferior_data ();
74 set_inferior_data (inf
, catch_syscall_inferior_data
, inf_data
);
81 catch_syscall_inferior_data_cleanup (struct inferior
*inf
, void *arg
)
83 struct catch_syscall_inferior_data
*inf_data
84 = (struct catch_syscall_inferior_data
*) arg
;
89 /* Implement the "insert" breakpoint_ops method for syscall
93 insert_catch_syscall (struct bp_location
*bl
)
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
);
100 ++inf_data
->total_syscalls_count
;
101 if (c
->syscalls_to_be_caught
.empty ())
102 ++inf_data
->any_syscall_count
;
105 for (int iter
: c
->syscalls_to_be_caught
)
109 if (iter
>= inf_data
->syscalls_counts
.size ())
110 inf_data
->syscalls_counts
.resize (iter
+ 1);
111 ++inf_data
->syscalls_counts
[iter
];
115 return target_set_syscall_catchpoint (ptid_get_pid (inferior_ptid
),
116 inf_data
->total_syscalls_count
!= 0,
117 inf_data
->any_syscall_count
,
118 inf_data
->syscalls_counts
.size (),
119 inf_data
->syscalls_counts
.data ());
122 /* Implement the "remove" breakpoint_ops method for syscall
126 remove_catch_syscall (struct bp_location
*bl
, enum remove_bp_reason reason
)
128 struct syscall_catchpoint
*c
= (struct syscall_catchpoint
*) bl
->owner
;
129 struct inferior
*inf
= current_inferior ();
130 struct catch_syscall_inferior_data
*inf_data
131 = get_catch_syscall_inferior_data (inf
);
133 --inf_data
->total_syscalls_count
;
134 if (c
->syscalls_to_be_caught
.empty ())
135 --inf_data
->any_syscall_count
;
138 for (int iter
: c
->syscalls_to_be_caught
)
141 if (iter
>= inf_data
->syscalls_counts
.size ())
142 /* Shouldn't happen. */
144 --inf_data
->syscalls_counts
[iter
];
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 inf_data
->syscalls_counts
.size (),
152 inf_data
->syscalls_counts
.data ());
155 /* Implement the "breakpoint_hit" breakpoint_ops method for syscall
159 breakpoint_hit_catch_syscall (const struct bp_location
*bl
,
160 const address_space
*aspace
, CORE_ADDR bp_addr
,
161 const struct target_waitstatus
*ws
)
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;
167 const struct syscall_catchpoint
*c
168 = (const struct syscall_catchpoint
*) bl
->owner
;
170 if (ws
->kind
!= TARGET_WAITKIND_SYSCALL_ENTRY
171 && ws
->kind
!= TARGET_WAITKIND_SYSCALL_RETURN
)
174 syscall_number
= ws
->value
.syscall_number
;
176 /* Now, checking if the syscall is the same. */
177 if (!c
->syscalls_to_be_caught
.empty ())
179 for (int iter
: c
->syscalls_to_be_caught
)
180 if (syscall_number
== iter
)
189 /* Implement the "print_it" breakpoint_ops method for syscall
192 static enum print_stop_action
193 print_it_catch_syscall (bpstat bs
)
195 struct ui_out
*uiout
= current_uiout
;
196 struct breakpoint
*b
= bs
->breakpoint_at
;
197 /* These are needed because we want to know in which state a
198 syscall is. It can be in the TARGET_WAITKIND_SYSCALL_ENTRY
199 or TARGET_WAITKIND_SYSCALL_RETURN, and depending on it we
200 must print "called syscall" or "returned from syscall". */
202 struct target_waitstatus last
;
204 struct gdbarch
*gdbarch
= bs
->bp_location_at
->gdbarch
;
206 get_last_target_status (&ptid
, &last
);
208 get_syscall_by_number (gdbarch
, last
.value
.syscall_number
, &s
);
210 annotate_catchpoint (b
->number
);
211 maybe_print_thread_hit_breakpoint (uiout
);
213 if (b
->disposition
== disp_del
)
214 uiout
->text ("Temporary catchpoint ");
216 uiout
->text ("Catchpoint ");
217 if (uiout
->is_mi_like_p ())
219 uiout
->field_string ("reason",
220 async_reason_lookup (last
.kind
== TARGET_WAITKIND_SYSCALL_ENTRY
221 ? EXEC_ASYNC_SYSCALL_ENTRY
222 : EXEC_ASYNC_SYSCALL_RETURN
));
223 uiout
->field_string ("disp", bpdisp_text (b
->disposition
));
225 uiout
->field_int ("bkptno", b
->number
);
227 if (last
.kind
== TARGET_WAITKIND_SYSCALL_ENTRY
)
228 uiout
->text (" (call to syscall ");
230 uiout
->text (" (returned from syscall ");
232 if (s
.name
== NULL
|| uiout
->is_mi_like_p ())
233 uiout
->field_int ("syscall-number", last
.value
.syscall_number
);
235 uiout
->field_string ("syscall-name", s
.name
);
239 return PRINT_SRC_AND_LOC
;
242 /* Implement the "print_one" breakpoint_ops method for syscall
246 print_one_catch_syscall (struct breakpoint
*b
,
247 struct bp_location
**last_loc
)
249 struct syscall_catchpoint
*c
= (struct syscall_catchpoint
*) b
;
250 struct value_print_options opts
;
251 struct ui_out
*uiout
= current_uiout
;
252 struct gdbarch
*gdbarch
= b
->loc
->gdbarch
;
254 get_user_print_options (&opts
);
255 /* Field 4, the address, is omitted (which makes the columns not
256 line up too nicely with the headers, but the effect is relatively
258 if (opts
.addressprint
)
259 uiout
->field_skip ("addr");
262 if (c
->syscalls_to_be_caught
.size () > 1)
263 uiout
->text ("syscalls \"");
265 uiout
->text ("syscall \"");
267 if (!c
->syscalls_to_be_caught
.empty ())
269 char *text
= xstrprintf ("%s", "");
271 for (int iter
: c
->syscalls_to_be_caught
)
275 get_syscall_by_number (gdbarch
, iter
, &s
);
278 text
= xstrprintf ("%s%s, ", text
, s
.name
);
280 text
= xstrprintf ("%s%d, ", text
, iter
);
282 /* We have to xfree the last 'text' (now stored at 'x')
283 because xstrprintf dynamically allocates new space for it
287 /* Remove the last comma. */
288 text
[strlen (text
) - 2] = '\0';
289 uiout
->field_string ("what", text
);
292 uiout
->field_string ("what", "<any syscall>");
295 if (uiout
->is_mi_like_p ())
296 uiout
->field_string ("catch-type", "syscall");
299 /* Implement the "print_mention" breakpoint_ops method for syscall
303 print_mention_catch_syscall (struct breakpoint
*b
)
305 struct syscall_catchpoint
*c
= (struct syscall_catchpoint
*) b
;
306 struct gdbarch
*gdbarch
= b
->loc
->gdbarch
;
308 if (!c
->syscalls_to_be_caught
.empty ())
310 if (c
->syscalls_to_be_caught
.size () > 1)
311 printf_filtered (_("Catchpoint %d (syscalls"), b
->number
);
313 printf_filtered (_("Catchpoint %d (syscall"), b
->number
);
315 for (int iter
: c
->syscalls_to_be_caught
)
318 get_syscall_by_number (gdbarch
, iter
, &s
);
321 printf_filtered (" '%s' [%d]", s
.name
, s
.number
);
323 printf_filtered (" %d", s
.number
);
325 printf_filtered (")");
328 printf_filtered (_("Catchpoint %d (any syscall)"),
332 /* Implement the "print_recreate" breakpoint_ops method for syscall
336 print_recreate_catch_syscall (struct breakpoint
*b
, struct ui_file
*fp
)
338 struct syscall_catchpoint
*c
= (struct syscall_catchpoint
*) b
;
339 struct gdbarch
*gdbarch
= b
->loc
->gdbarch
;
341 fprintf_unfiltered (fp
, "catch syscall");
343 for (int iter
: c
->syscalls_to_be_caught
)
347 get_syscall_by_number (gdbarch
, iter
, &s
);
349 fprintf_unfiltered (fp
, " %s", s
.name
);
351 fprintf_unfiltered (fp
, " %d", s
.number
);
354 print_recreate_thread (b
, fp
);
357 /* The breakpoint_ops structure to be used in syscall catchpoints. */
359 static struct breakpoint_ops catch_syscall_breakpoint_ops
;
361 /* Returns non-zero if 'b' is a syscall catchpoint. */
364 syscall_catchpoint_p (struct breakpoint
*b
)
366 return (b
->ops
== &catch_syscall_breakpoint_ops
);
370 create_syscall_event_catchpoint (int tempflag
, std::vector
<int> &&filter
,
371 const struct breakpoint_ops
*ops
)
373 struct gdbarch
*gdbarch
= get_current_arch ();
375 std::unique_ptr
<syscall_catchpoint
> c (new syscall_catchpoint ());
376 init_catchpoint (c
.get (), gdbarch
, tempflag
, NULL
, ops
);
377 c
->syscalls_to_be_caught
= std::move (filter
);
379 install_breakpoint (0, std::move (c
), 1);
382 /* Splits the argument using space as delimiter. */
384 static std::vector
<int>
385 catch_syscall_split_args (const char *arg
)
387 std::vector
<int> result
;
388 struct gdbarch
*gdbarch
= target_gdbarch ();
392 int i
, syscall_number
;
397 /* Skip whitespace. */
398 arg
= skip_spaces (arg
);
400 for (i
= 0; i
< 127 && arg
[i
] && !isspace (arg
[i
]); ++i
)
401 cur_name
[i
] = arg
[i
];
405 /* Check if the user provided a syscall name, group, or a number. */
406 syscall_number
= (int) strtol (cur_name
, &endptr
, 0);
409 get_syscall_by_number (gdbarch
, syscall_number
, &s
);
410 result
.push_back (s
.number
);
412 else if (startswith (cur_name
, "g:")
413 || startswith (cur_name
, "group:"))
415 /* We have a syscall group. Let's expand it into a syscall
416 list before inserting. */
417 struct syscall
*syscall_list
;
418 const char *group_name
;
420 /* Skip over "g:" and "group:" prefix strings. */
421 group_name
= strchr (cur_name
, ':') + 1;
423 syscall_list
= get_syscalls_by_group (gdbarch
, group_name
);
425 if (syscall_list
== NULL
)
426 error (_("Unknown syscall group '%s'."), group_name
);
428 for (i
= 0; syscall_list
[i
].name
!= NULL
; i
++)
430 /* Insert each syscall that are part of the group. No
431 need to check if it is valid. */
432 result
.push_back (syscall_list
[i
].number
);
435 xfree (syscall_list
);
439 /* We have a name. Let's check if it's valid and convert it
441 get_syscall_by_name (gdbarch
, cur_name
, &s
);
443 if (s
.number
== UNKNOWN_SYSCALL
)
444 /* Here we have to issue an error instead of a warning,
445 because GDB cannot do anything useful if there's no
446 syscall number to be caught. */
447 error (_("Unknown syscall name '%s'."), cur_name
);
449 /* Ok, it's valid. */
450 result
.push_back (s
.number
);
457 /* Implement the "catch syscall" command. */
460 catch_syscall_command_1 (const char *arg
, int from_tty
,
461 struct cmd_list_element
*command
)
464 std::vector
<int> filter
;
466 struct gdbarch
*gdbarch
= get_current_arch ();
468 /* Checking if the feature if supported. */
469 if (gdbarch_get_syscall_number_p (gdbarch
) == 0)
470 error (_("The feature 'catch syscall' is not supported on \
471 this architecture yet."));
473 tempflag
= get_cmd_context (command
) == CATCH_TEMPORARY
;
475 arg
= skip_spaces (arg
);
477 /* We need to do this first "dummy" translation in order
478 to get the syscall XML file loaded or, most important,
479 to display a warning to the user if there's no XML file
480 for his/her architecture. */
481 get_syscall_by_number (gdbarch
, 0, &s
);
483 /* The allowed syntax is:
485 catch syscall <name | number> [<name | number> ... <name | number>]
487 Let's check if there's a syscall name. */
490 filter
= catch_syscall_split_args (arg
);
492 create_syscall_event_catchpoint (tempflag
, std::move (filter
),
493 &catch_syscall_breakpoint_ops
);
497 /* Returns 0 if 'bp' is NOT a syscall catchpoint,
498 non-zero otherwise. */
500 is_syscall_catchpoint_enabled (struct breakpoint
*bp
)
502 if (syscall_catchpoint_p (bp
)
503 && bp
->enable_state
!= bp_disabled
504 && bp
->enable_state
!= bp_call_disabled
)
511 catch_syscall_enabled (void)
513 struct catch_syscall_inferior_data
*inf_data
514 = get_catch_syscall_inferior_data (current_inferior ());
516 return inf_data
->total_syscalls_count
!= 0;
519 /* Helper function for catching_syscall_number. If B is a syscall
520 catchpoint for SYSCALL_NUMBER, return 1 (which will make
521 'breakpoint_find_if' return). Otherwise, return 0. */
524 catching_syscall_number_1 (struct breakpoint
*b
,
527 int syscall_number
= (int) (uintptr_t) data
;
529 if (is_syscall_catchpoint_enabled (b
))
531 struct syscall_catchpoint
*c
= (struct syscall_catchpoint
*) b
;
533 if (!c
->syscalls_to_be_caught
.empty ())
535 for (int iter
: c
->syscalls_to_be_caught
)
536 if (syscall_number
== iter
)
547 catching_syscall_number (int syscall_number
)
549 struct breakpoint
*b
= breakpoint_find_if (catching_syscall_number_1
,
550 (void *) (uintptr_t) syscall_number
);
555 /* Complete syscall names. Used by "catch syscall". */
558 catch_syscall_completer (struct cmd_list_element
*cmd
,
559 completion_tracker
&tracker
,
560 const char *text
, const char *word
)
562 struct gdbarch
*gdbarch
= get_current_arch ();
563 gdb::unique_xmalloc_ptr
<const char *> group_list
;
567 /* Completion considers ':' to be a word separator, so we use this to
568 verify whether the previous word was a group prefix. If so, we
569 build the completion list using group names only. */
570 for (prefix
= word
; prefix
!= text
&& prefix
[-1] != ' '; prefix
--)
573 if (startswith (prefix
, "g:") || startswith (prefix
, "group:"))
575 /* Perform completion inside 'group:' namespace only. */
576 group_list
.reset (get_syscall_group_names (gdbarch
));
577 if (group_list
!= NULL
)
578 complete_on_enum (tracker
, group_list
.get (), word
, word
);
582 /* Complete with both, syscall names and groups. */
583 gdb::unique_xmalloc_ptr
<const char *> syscall_list
584 (get_syscall_names (gdbarch
));
585 group_list
.reset (get_syscall_group_names (gdbarch
));
587 const char **group_ptr
= group_list
.get ();
589 /* Hold on to strings while we're using them. */
590 std::vector
<std::string
> holders
;
592 /* Append "group:" prefix to syscall groups. */
593 for (i
= 0; group_ptr
[i
] != NULL
; i
++)
595 std::string prefixed_group
= string_printf ("group:%s",
598 group_ptr
[i
] = prefixed_group
.c_str ();
599 holders
.push_back (std::move (prefixed_group
));
602 if (syscall_list
!= NULL
)
603 complete_on_enum (tracker
, syscall_list
.get (), word
, word
);
604 if (group_list
!= NULL
)
605 complete_on_enum (tracker
, group_ptr
, word
, word
);
610 clear_syscall_counts (struct inferior
*inf
)
612 struct catch_syscall_inferior_data
*inf_data
613 = get_catch_syscall_inferior_data (inf
);
615 inf_data
->total_syscalls_count
= 0;
616 inf_data
->any_syscall_count
= 0;
617 inf_data
->syscalls_counts
.clear ();
621 initialize_syscall_catchpoint_ops (void)
623 struct breakpoint_ops
*ops
;
625 initialize_breakpoint_ops ();
627 /* Syscall catchpoints. */
628 ops
= &catch_syscall_breakpoint_ops
;
629 *ops
= base_breakpoint_ops
;
630 ops
->insert_location
= insert_catch_syscall
;
631 ops
->remove_location
= remove_catch_syscall
;
632 ops
->breakpoint_hit
= breakpoint_hit_catch_syscall
;
633 ops
->print_it
= print_it_catch_syscall
;
634 ops
->print_one
= print_one_catch_syscall
;
635 ops
->print_mention
= print_mention_catch_syscall
;
636 ops
->print_recreate
= print_recreate_catch_syscall
;
640 _initialize_break_catch_syscall (void)
642 initialize_syscall_catchpoint_ops ();
644 observer_attach_inferior_exit (clear_syscall_counts
);
645 catch_syscall_inferior_data
646 = register_inferior_data_with_cleanup (NULL
,
647 catch_syscall_inferior_data_cleanup
);
649 add_catch_command ("syscall", _("\
650 Catch system calls by their names, groups and/or numbers.\n\
651 Arguments say which system calls to catch. If no arguments are given,\n\
652 every system call will be caught. Arguments, if given, should be one\n\
653 or more system call names (if your system supports that), system call\n\
654 groups or system call numbers."),
655 catch_syscall_command_1
,
656 catch_syscall_completer
,