Rotate gdb/ChangeLog (start of New Year procedure)
[binutils-gdb.git] / gdb / break-catch-syscall.c
blobdde80b54a2fb98e946381250591368b3d99ce54b
1 /* Everything about syscall catchpoints, for GDB.
3 Copyright (C) 2009-2019 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/>. */
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 "observable.h"
31 #include "xml-syscall.h"
32 #include "cli/cli-style.h"
34 /* An instance of this type is used to represent a syscall catchpoint.
35 A breakpoint is really of this type iff its ops pointer points to
36 CATCH_SYSCALL_BREAKPOINT_OPS. */
38 struct syscall_catchpoint : public breakpoint
40 /* Syscall numbers used for the 'catch syscall' feature. If no
41 syscall has been specified for filtering, it is empty.
42 Otherwise, it holds a list of all syscalls to be caught. */
43 std::vector<int> syscalls_to_be_caught;
46 struct catch_syscall_inferior_data
48 /* We keep a count of the number of times the user has requested a
49 particular syscall to be tracked, and pass this information to the
50 target. This lets capable targets implement filtering directly. */
52 /* Number of times that "any" syscall is requested. */
53 int any_syscall_count;
55 /* Count of each system call. */
56 std::vector<int> syscalls_counts;
58 /* This counts all syscall catch requests, so we can readily determine
59 if any catching is necessary. */
60 int total_syscalls_count;
63 static const struct inferior_key<struct catch_syscall_inferior_data>
64 catch_syscall_inferior_data;
66 static struct catch_syscall_inferior_data *
67 get_catch_syscall_inferior_data (struct inferior *inf)
69 struct catch_syscall_inferior_data *inf_data;
71 inf_data = catch_syscall_inferior_data.get (inf);
72 if (inf_data == NULL)
73 inf_data = catch_syscall_inferior_data.emplace (inf);
75 return inf_data;
78 /* Implement the "insert" breakpoint_ops method for syscall
79 catchpoints. */
81 static int
82 insert_catch_syscall (struct bp_location *bl)
84 struct syscall_catchpoint *c = (struct syscall_catchpoint *) bl->owner;
85 struct inferior *inf = current_inferior ();
86 struct catch_syscall_inferior_data *inf_data
87 = get_catch_syscall_inferior_data (inf);
89 ++inf_data->total_syscalls_count;
90 if (c->syscalls_to_be_caught.empty ())
91 ++inf_data->any_syscall_count;
92 else
94 for (int iter : c->syscalls_to_be_caught)
96 if (iter >= inf_data->syscalls_counts.size ())
97 inf_data->syscalls_counts.resize (iter + 1);
98 ++inf_data->syscalls_counts[iter];
102 return target_set_syscall_catchpoint (inferior_ptid.pid (),
103 inf_data->total_syscalls_count != 0,
104 inf_data->any_syscall_count,
105 inf_data->syscalls_counts);
108 /* Implement the "remove" breakpoint_ops method for syscall
109 catchpoints. */
111 static int
112 remove_catch_syscall (struct bp_location *bl, enum remove_bp_reason reason)
114 struct syscall_catchpoint *c = (struct syscall_catchpoint *) bl->owner;
115 struct inferior *inf = current_inferior ();
116 struct catch_syscall_inferior_data *inf_data
117 = get_catch_syscall_inferior_data (inf);
119 --inf_data->total_syscalls_count;
120 if (c->syscalls_to_be_caught.empty ())
121 --inf_data->any_syscall_count;
122 else
124 for (int iter : c->syscalls_to_be_caught)
126 if (iter >= inf_data->syscalls_counts.size ())
127 /* Shouldn't happen. */
128 continue;
129 --inf_data->syscalls_counts[iter];
133 return target_set_syscall_catchpoint (inferior_ptid.pid (),
134 inf_data->total_syscalls_count != 0,
135 inf_data->any_syscall_count,
136 inf_data->syscalls_counts);
139 /* Implement the "breakpoint_hit" breakpoint_ops method for syscall
140 catchpoints. */
142 static int
143 breakpoint_hit_catch_syscall (const struct bp_location *bl,
144 const address_space *aspace, CORE_ADDR bp_addr,
145 const struct target_waitstatus *ws)
147 /* We must check if we are catching specific syscalls in this
148 breakpoint. If we are, then we must guarantee that the called
149 syscall is the same syscall we are catching. */
150 int syscall_number = 0;
151 const struct syscall_catchpoint *c
152 = (const struct syscall_catchpoint *) bl->owner;
154 if (ws->kind != TARGET_WAITKIND_SYSCALL_ENTRY
155 && ws->kind != TARGET_WAITKIND_SYSCALL_RETURN)
156 return 0;
158 syscall_number = ws->value.syscall_number;
160 /* Now, checking if the syscall is the same. */
161 if (!c->syscalls_to_be_caught.empty ())
163 for (int iter : c->syscalls_to_be_caught)
164 if (syscall_number == iter)
165 return 1;
167 return 0;
170 return 1;
173 /* Implement the "print_it" breakpoint_ops method for syscall
174 catchpoints. */
176 static enum print_stop_action
177 print_it_catch_syscall (bpstat bs)
179 struct ui_out *uiout = current_uiout;
180 struct breakpoint *b = bs->breakpoint_at;
181 /* These are needed because we want to know in which state a
182 syscall is. It can be in the TARGET_WAITKIND_SYSCALL_ENTRY
183 or TARGET_WAITKIND_SYSCALL_RETURN, and depending on it we
184 must print "called syscall" or "returned from syscall". */
185 ptid_t ptid;
186 struct target_waitstatus last;
187 struct syscall s;
188 struct gdbarch *gdbarch = bs->bp_location_at->gdbarch;
190 get_last_target_status (&ptid, &last);
192 get_syscall_by_number (gdbarch, last.value.syscall_number, &s);
194 annotate_catchpoint (b->number);
195 maybe_print_thread_hit_breakpoint (uiout);
197 if (b->disposition == disp_del)
198 uiout->text ("Temporary catchpoint ");
199 else
200 uiout->text ("Catchpoint ");
201 if (uiout->is_mi_like_p ())
203 uiout->field_string ("reason",
204 async_reason_lookup (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY
205 ? EXEC_ASYNC_SYSCALL_ENTRY
206 : EXEC_ASYNC_SYSCALL_RETURN));
207 uiout->field_string ("disp", bpdisp_text (b->disposition));
209 uiout->field_signed ("bkptno", b->number);
211 if (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY)
212 uiout->text (" (call to syscall ");
213 else
214 uiout->text (" (returned from syscall ");
216 if (s.name == NULL || uiout->is_mi_like_p ())
217 uiout->field_signed ("syscall-number", last.value.syscall_number);
218 if (s.name != NULL)
219 uiout->field_string ("syscall-name", s.name);
221 uiout->text ("), ");
223 return PRINT_SRC_AND_LOC;
226 /* Implement the "print_one" breakpoint_ops method for syscall
227 catchpoints. */
229 static void
230 print_one_catch_syscall (struct breakpoint *b,
231 struct bp_location **last_loc)
233 struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
234 struct value_print_options opts;
235 struct ui_out *uiout = current_uiout;
236 struct gdbarch *gdbarch = b->loc->gdbarch;
238 get_user_print_options (&opts);
239 /* Field 4, the address, is omitted (which makes the columns not
240 line up too nicely with the headers, but the effect is relatively
241 readable). */
242 if (opts.addressprint)
243 uiout->field_skip ("addr");
244 annotate_field (5);
246 if (c->syscalls_to_be_caught.size () > 1)
247 uiout->text ("syscalls \"");
248 else
249 uiout->text ("syscall \"");
251 if (!c->syscalls_to_be_caught.empty ())
253 char *text = xstrprintf ("%s", "");
255 for (int iter : c->syscalls_to_be_caught)
257 char *previous_text = text;
258 struct syscall s;
259 get_syscall_by_number (gdbarch, iter, &s);
261 if (s.name != NULL)
262 text = xstrprintf ("%s%s, ", text, s.name);
263 else
264 text = xstrprintf ("%s%d, ", text, iter);
266 /* We have to xfree previous_text because xstrprintf dynamically
267 allocates new space for text on every call. */
268 xfree (previous_text);
270 /* Remove the last comma. */
271 text[strlen (text) - 2] = '\0';
272 uiout->field_string ("what", text);
273 /* xfree last text. */
274 xfree (text);
276 else
277 uiout->field_string ("what", "<any syscall>", metadata_style.style ());
278 uiout->text ("\" ");
280 if (uiout->is_mi_like_p ())
281 uiout->field_string ("catch-type", "syscall");
284 /* Implement the "print_mention" breakpoint_ops method for syscall
285 catchpoints. */
287 static void
288 print_mention_catch_syscall (struct breakpoint *b)
290 struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
291 struct gdbarch *gdbarch = b->loc->gdbarch;
293 if (!c->syscalls_to_be_caught.empty ())
295 if (c->syscalls_to_be_caught.size () > 1)
296 printf_filtered (_("Catchpoint %d (syscalls"), b->number);
297 else
298 printf_filtered (_("Catchpoint %d (syscall"), b->number);
300 for (int iter : c->syscalls_to_be_caught)
302 struct syscall s;
303 get_syscall_by_number (gdbarch, iter, &s);
305 if (s.name != NULL)
306 printf_filtered (" '%s' [%d]", s.name, s.number);
307 else
308 printf_filtered (" %d", s.number);
310 printf_filtered (")");
312 else
313 printf_filtered (_("Catchpoint %d (any syscall)"),
314 b->number);
317 /* Implement the "print_recreate" breakpoint_ops method for syscall
318 catchpoints. */
320 static void
321 print_recreate_catch_syscall (struct breakpoint *b, struct ui_file *fp)
323 struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
324 struct gdbarch *gdbarch = b->loc->gdbarch;
326 fprintf_unfiltered (fp, "catch syscall");
328 for (int iter : c->syscalls_to_be_caught)
330 struct syscall s;
332 get_syscall_by_number (gdbarch, iter, &s);
333 if (s.name != NULL)
334 fprintf_unfiltered (fp, " %s", s.name);
335 else
336 fprintf_unfiltered (fp, " %d", s.number);
339 print_recreate_thread (b, fp);
342 /* The breakpoint_ops structure to be used in syscall catchpoints. */
344 static struct breakpoint_ops catch_syscall_breakpoint_ops;
346 /* Returns non-zero if 'b' is a syscall catchpoint. */
348 static int
349 syscall_catchpoint_p (struct breakpoint *b)
351 return (b->ops == &catch_syscall_breakpoint_ops);
354 static void
355 create_syscall_event_catchpoint (int tempflag, std::vector<int> &&filter,
356 const struct breakpoint_ops *ops)
358 struct gdbarch *gdbarch = get_current_arch ();
360 std::unique_ptr<syscall_catchpoint> c (new syscall_catchpoint ());
361 init_catchpoint (c.get (), gdbarch, tempflag, NULL, ops);
362 c->syscalls_to_be_caught = std::move (filter);
364 install_breakpoint (0, std::move (c), 1);
367 /* Splits the argument using space as delimiter. */
369 static std::vector<int>
370 catch_syscall_split_args (const char *arg)
372 std::vector<int> result;
373 struct gdbarch *gdbarch = target_gdbarch ();
375 while (*arg != '\0')
377 int i, syscall_number;
378 char *endptr;
379 char cur_name[128];
380 struct syscall s;
382 /* Skip whitespace. */
383 arg = skip_spaces (arg);
385 for (i = 0; i < 127 && arg[i] && !isspace (arg[i]); ++i)
386 cur_name[i] = arg[i];
387 cur_name[i] = '\0';
388 arg += i;
390 /* Check if the user provided a syscall name, group, or a number. */
391 syscall_number = (int) strtol (cur_name, &endptr, 0);
392 if (*endptr == '\0')
394 get_syscall_by_number (gdbarch, syscall_number, &s);
395 result.push_back (s.number);
397 else if (startswith (cur_name, "g:")
398 || startswith (cur_name, "group:"))
400 /* We have a syscall group. Let's expand it into a syscall
401 list before inserting. */
402 const char *group_name;
404 /* Skip over "g:" and "group:" prefix strings. */
405 group_name = strchr (cur_name, ':') + 1;
407 if (!get_syscalls_by_group (gdbarch, group_name, &result))
408 error (_("Unknown syscall group '%s'."), group_name);
410 else
412 /* We have a name. Let's check if it's valid and fetch a
413 list of matching numbers. */
414 if (!get_syscalls_by_name (gdbarch, cur_name, &result))
415 /* Here we have to issue an error instead of a warning,
416 because GDB cannot do anything useful if there's no
417 syscall number to be caught. */
418 error (_("Unknown syscall name '%s'."), cur_name);
422 return result;
425 /* Implement the "catch syscall" command. */
427 static void
428 catch_syscall_command_1 (const char *arg, int from_tty,
429 struct cmd_list_element *command)
431 int tempflag;
432 std::vector<int> filter;
433 struct syscall s;
434 struct gdbarch *gdbarch = get_current_arch ();
436 /* Checking if the feature if supported. */
437 if (gdbarch_get_syscall_number_p (gdbarch) == 0)
438 error (_("The feature 'catch syscall' is not supported on \
439 this architecture yet."));
441 tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
443 arg = skip_spaces (arg);
445 /* We need to do this first "dummy" translation in order
446 to get the syscall XML file loaded or, most important,
447 to display a warning to the user if there's no XML file
448 for his/her architecture. */
449 get_syscall_by_number (gdbarch, 0, &s);
451 /* The allowed syntax is:
452 catch syscall
453 catch syscall <name | number> [<name | number> ... <name | number>]
455 Let's check if there's a syscall name. */
457 if (arg != NULL)
458 filter = catch_syscall_split_args (arg);
460 create_syscall_event_catchpoint (tempflag, std::move (filter),
461 &catch_syscall_breakpoint_ops);
465 /* Returns 0 if 'bp' is NOT a syscall catchpoint,
466 non-zero otherwise. */
467 static int
468 is_syscall_catchpoint_enabled (struct breakpoint *bp)
470 if (syscall_catchpoint_p (bp)
471 && bp->enable_state != bp_disabled
472 && bp->enable_state != bp_call_disabled)
473 return 1;
474 else
475 return 0;
479 catch_syscall_enabled (void)
481 struct catch_syscall_inferior_data *inf_data
482 = get_catch_syscall_inferior_data (current_inferior ());
484 return inf_data->total_syscalls_count != 0;
487 /* Helper function for catching_syscall_number. If B is a syscall
488 catchpoint for SYSCALL_NUMBER, return 1 (which will make
489 'breakpoint_find_if' return). Otherwise, return 0. */
491 static int
492 catching_syscall_number_1 (struct breakpoint *b,
493 void *data)
495 int syscall_number = (int) (uintptr_t) data;
497 if (is_syscall_catchpoint_enabled (b))
499 struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
501 if (!c->syscalls_to_be_caught.empty ())
503 for (int iter : c->syscalls_to_be_caught)
504 if (syscall_number == iter)
505 return 1;
507 else
508 return 1;
511 return 0;
515 catching_syscall_number (int syscall_number)
517 struct breakpoint *b = breakpoint_find_if (catching_syscall_number_1,
518 (void *) (uintptr_t) syscall_number);
520 return b != NULL;
523 /* Complete syscall names. Used by "catch syscall". */
525 static void
526 catch_syscall_completer (struct cmd_list_element *cmd,
527 completion_tracker &tracker,
528 const char *text, const char *word)
530 struct gdbarch *gdbarch = get_current_arch ();
531 gdb::unique_xmalloc_ptr<const char *> group_list;
532 const char *prefix;
534 /* Completion considers ':' to be a word separator, so we use this to
535 verify whether the previous word was a group prefix. If so, we
536 build the completion list using group names only. */
537 for (prefix = word; prefix != text && prefix[-1] != ' '; prefix--)
540 if (startswith (prefix, "g:") || startswith (prefix, "group:"))
542 /* Perform completion inside 'group:' namespace only. */
543 group_list.reset (get_syscall_group_names (gdbarch));
544 if (group_list != NULL)
545 complete_on_enum (tracker, group_list.get (), word, word);
547 else
549 /* Complete with both, syscall names and groups. */
550 gdb::unique_xmalloc_ptr<const char *> syscall_list
551 (get_syscall_names (gdbarch));
552 group_list.reset (get_syscall_group_names (gdbarch));
554 const char **group_ptr = group_list.get ();
556 /* Hold on to strings while we're using them. */
557 std::vector<std::string> holders;
559 /* Append "group:" prefix to syscall groups. */
560 for (int i = 0; group_ptr[i] != NULL; i++)
561 holders.push_back (string_printf ("group:%s", group_ptr[i]));
563 for (int i = 0; group_ptr[i] != NULL; i++)
564 group_ptr[i] = holders[i].c_str ();
566 if (syscall_list != NULL)
567 complete_on_enum (tracker, syscall_list.get (), word, word);
568 if (group_list != NULL)
569 complete_on_enum (tracker, group_ptr, word, word);
573 static void
574 clear_syscall_counts (struct inferior *inf)
576 struct catch_syscall_inferior_data *inf_data
577 = get_catch_syscall_inferior_data (inf);
579 inf_data->total_syscalls_count = 0;
580 inf_data->any_syscall_count = 0;
581 inf_data->syscalls_counts.clear ();
584 static void
585 initialize_syscall_catchpoint_ops (void)
587 struct breakpoint_ops *ops;
589 initialize_breakpoint_ops ();
591 /* Syscall catchpoints. */
592 ops = &catch_syscall_breakpoint_ops;
593 *ops = base_breakpoint_ops;
594 ops->insert_location = insert_catch_syscall;
595 ops->remove_location = remove_catch_syscall;
596 ops->breakpoint_hit = breakpoint_hit_catch_syscall;
597 ops->print_it = print_it_catch_syscall;
598 ops->print_one = print_one_catch_syscall;
599 ops->print_mention = print_mention_catch_syscall;
600 ops->print_recreate = print_recreate_catch_syscall;
603 void
604 _initialize_break_catch_syscall (void)
606 initialize_syscall_catchpoint_ops ();
608 gdb::observers::inferior_exit.attach (clear_syscall_counts);
610 add_catch_command ("syscall", _("\
611 Catch system calls by their names, groups and/or numbers.\n\
612 Arguments say which system calls to catch. If no arguments are given,\n\
613 every system call will be caught. Arguments, if given, should be one\n\
614 or more system call names (if your system supports that), system call\n\
615 groups or system call numbers."),
616 catch_syscall_command_1,
617 catch_syscall_completer,
618 CATCH_PERMANENT,
619 CATCH_TEMPORARY);