[PATCH 7/57][Arm][GAS] Add support for MVE instructions: vstr/vldr
[binutils-gdb.git] / gdb / break-catch-syscall.c
blobcd4870f7f5125e26f537a8dec64ddbbe61144c78
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"
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 struct catch_syscall_inferior_data
47 /* We keep a count of the number of times the user has requested a
48 particular syscall to be tracked, and pass this information to the
49 target. This lets capable targets implement filtering directly. */
51 /* Number of times that "any" syscall is requested. */
52 int any_syscall_count;
54 /* Count of each system call. */
55 std::vector<int> syscalls_counts;
57 /* This counts all syscall catch requests, so we can readily determine
58 if any catching is necessary. */
59 int total_syscalls_count;
62 static const struct inferior_key<struct catch_syscall_inferior_data>
63 catch_syscall_inferior_data;
65 static struct catch_syscall_inferior_data *
66 get_catch_syscall_inferior_data (struct inferior *inf)
68 struct catch_syscall_inferior_data *inf_data;
70 inf_data = catch_syscall_inferior_data.get (inf);
71 if (inf_data == NULL)
72 inf_data = catch_syscall_inferior_data.emplace (inf);
74 return inf_data;
77 /* Implement the "insert" breakpoint_ops method for syscall
78 catchpoints. */
80 static int
81 insert_catch_syscall (struct bp_location *bl)
83 struct syscall_catchpoint *c = (struct syscall_catchpoint *) bl->owner;
84 struct inferior *inf = current_inferior ();
85 struct catch_syscall_inferior_data *inf_data
86 = get_catch_syscall_inferior_data (inf);
88 ++inf_data->total_syscalls_count;
89 if (c->syscalls_to_be_caught.empty ())
90 ++inf_data->any_syscall_count;
91 else
93 for (int iter : c->syscalls_to_be_caught)
95 if (iter >= inf_data->syscalls_counts.size ())
96 inf_data->syscalls_counts.resize (iter + 1);
97 ++inf_data->syscalls_counts[iter];
101 return target_set_syscall_catchpoint (inferior_ptid.pid (),
102 inf_data->total_syscalls_count != 0,
103 inf_data->any_syscall_count,
104 inf_data->syscalls_counts);
107 /* Implement the "remove" breakpoint_ops method for syscall
108 catchpoints. */
110 static int
111 remove_catch_syscall (struct bp_location *bl, enum remove_bp_reason reason)
113 struct syscall_catchpoint *c = (struct syscall_catchpoint *) bl->owner;
114 struct inferior *inf = current_inferior ();
115 struct catch_syscall_inferior_data *inf_data
116 = get_catch_syscall_inferior_data (inf);
118 --inf_data->total_syscalls_count;
119 if (c->syscalls_to_be_caught.empty ())
120 --inf_data->any_syscall_count;
121 else
123 for (int iter : c->syscalls_to_be_caught)
125 if (iter >= inf_data->syscalls_counts.size ())
126 /* Shouldn't happen. */
127 continue;
128 --inf_data->syscalls_counts[iter];
132 return target_set_syscall_catchpoint (inferior_ptid.pid (),
133 inf_data->total_syscalls_count != 0,
134 inf_data->any_syscall_count,
135 inf_data->syscalls_counts);
138 /* Implement the "breakpoint_hit" breakpoint_ops method for syscall
139 catchpoints. */
141 static int
142 breakpoint_hit_catch_syscall (const struct bp_location *bl,
143 const address_space *aspace, CORE_ADDR bp_addr,
144 const struct target_waitstatus *ws)
146 /* We must check if we are catching specific syscalls in this
147 breakpoint. If we are, then we must guarantee that the called
148 syscall is the same syscall we are catching. */
149 int syscall_number = 0;
150 const struct syscall_catchpoint *c
151 = (const struct syscall_catchpoint *) bl->owner;
153 if (ws->kind != TARGET_WAITKIND_SYSCALL_ENTRY
154 && ws->kind != TARGET_WAITKIND_SYSCALL_RETURN)
155 return 0;
157 syscall_number = ws->value.syscall_number;
159 /* Now, checking if the syscall is the same. */
160 if (!c->syscalls_to_be_caught.empty ())
162 for (int iter : c->syscalls_to_be_caught)
163 if (syscall_number == iter)
164 return 1;
166 return 0;
169 return 1;
172 /* Implement the "print_it" breakpoint_ops method for syscall
173 catchpoints. */
175 static enum print_stop_action
176 print_it_catch_syscall (bpstat bs)
178 struct ui_out *uiout = current_uiout;
179 struct breakpoint *b = bs->breakpoint_at;
180 /* These are needed because we want to know in which state a
181 syscall is. It can be in the TARGET_WAITKIND_SYSCALL_ENTRY
182 or TARGET_WAITKIND_SYSCALL_RETURN, and depending on it we
183 must print "called syscall" or "returned from syscall". */
184 ptid_t ptid;
185 struct target_waitstatus last;
186 struct syscall s;
187 struct gdbarch *gdbarch = bs->bp_location_at->gdbarch;
189 get_last_target_status (&ptid, &last);
191 get_syscall_by_number (gdbarch, last.value.syscall_number, &s);
193 annotate_catchpoint (b->number);
194 maybe_print_thread_hit_breakpoint (uiout);
196 if (b->disposition == disp_del)
197 uiout->text ("Temporary catchpoint ");
198 else
199 uiout->text ("Catchpoint ");
200 if (uiout->is_mi_like_p ())
202 uiout->field_string ("reason",
203 async_reason_lookup (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY
204 ? EXEC_ASYNC_SYSCALL_ENTRY
205 : EXEC_ASYNC_SYSCALL_RETURN));
206 uiout->field_string ("disp", bpdisp_text (b->disposition));
208 uiout->field_int ("bkptno", b->number);
210 if (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY)
211 uiout->text (" (call to syscall ");
212 else
213 uiout->text (" (returned from syscall ");
215 if (s.name == NULL || uiout->is_mi_like_p ())
216 uiout->field_int ("syscall-number", last.value.syscall_number);
217 if (s.name != NULL)
218 uiout->field_string ("syscall-name", s.name);
220 uiout->text ("), ");
222 return PRINT_SRC_AND_LOC;
225 /* Implement the "print_one" breakpoint_ops method for syscall
226 catchpoints. */
228 static void
229 print_one_catch_syscall (struct breakpoint *b,
230 struct bp_location **last_loc)
232 struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
233 struct value_print_options opts;
234 struct ui_out *uiout = current_uiout;
235 struct gdbarch *gdbarch = b->loc->gdbarch;
237 get_user_print_options (&opts);
238 /* Field 4, the address, is omitted (which makes the columns not
239 line up too nicely with the headers, but the effect is relatively
240 readable). */
241 if (opts.addressprint)
242 uiout->field_skip ("addr");
243 annotate_field (5);
245 if (c->syscalls_to_be_caught.size () > 1)
246 uiout->text ("syscalls \"");
247 else
248 uiout->text ("syscall \"");
250 if (!c->syscalls_to_be_caught.empty ())
252 char *text = xstrprintf ("%s", "");
254 for (int iter : c->syscalls_to_be_caught)
256 char *previous_text = text;
257 struct syscall s;
258 get_syscall_by_number (gdbarch, iter, &s);
260 if (s.name != NULL)
261 text = xstrprintf ("%s%s, ", text, s.name);
262 else
263 text = xstrprintf ("%s%d, ", text, iter);
265 /* We have to xfree previous_text because xstrprintf dynamically
266 allocates new space for text on every call. */
267 xfree (previous_text);
269 /* Remove the last comma. */
270 text[strlen (text) - 2] = '\0';
271 uiout->field_string ("what", text);
272 /* xfree last text. */
273 xfree (text);
275 else
276 uiout->field_string ("what", "<any syscall>");
277 uiout->text ("\" ");
279 if (uiout->is_mi_like_p ())
280 uiout->field_string ("catch-type", "syscall");
283 /* Implement the "print_mention" breakpoint_ops method for syscall
284 catchpoints. */
286 static void
287 print_mention_catch_syscall (struct breakpoint *b)
289 struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
290 struct gdbarch *gdbarch = b->loc->gdbarch;
292 if (!c->syscalls_to_be_caught.empty ())
294 if (c->syscalls_to_be_caught.size () > 1)
295 printf_filtered (_("Catchpoint %d (syscalls"), b->number);
296 else
297 printf_filtered (_("Catchpoint %d (syscall"), b->number);
299 for (int iter : c->syscalls_to_be_caught)
301 struct syscall s;
302 get_syscall_by_number (gdbarch, iter, &s);
304 if (s.name != NULL)
305 printf_filtered (" '%s' [%d]", s.name, s.number);
306 else
307 printf_filtered (" %d", s.number);
309 printf_filtered (")");
311 else
312 printf_filtered (_("Catchpoint %d (any syscall)"),
313 b->number);
316 /* Implement the "print_recreate" breakpoint_ops method for syscall
317 catchpoints. */
319 static void
320 print_recreate_catch_syscall (struct breakpoint *b, struct ui_file *fp)
322 struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
323 struct gdbarch *gdbarch = b->loc->gdbarch;
325 fprintf_unfiltered (fp, "catch syscall");
327 for (int iter : c->syscalls_to_be_caught)
329 struct syscall s;
331 get_syscall_by_number (gdbarch, iter, &s);
332 if (s.name != NULL)
333 fprintf_unfiltered (fp, " %s", s.name);
334 else
335 fprintf_unfiltered (fp, " %d", s.number);
338 print_recreate_thread (b, fp);
341 /* The breakpoint_ops structure to be used in syscall catchpoints. */
343 static struct breakpoint_ops catch_syscall_breakpoint_ops;
345 /* Returns non-zero if 'b' is a syscall catchpoint. */
347 static int
348 syscall_catchpoint_p (struct breakpoint *b)
350 return (b->ops == &catch_syscall_breakpoint_ops);
353 static void
354 create_syscall_event_catchpoint (int tempflag, std::vector<int> &&filter,
355 const struct breakpoint_ops *ops)
357 struct gdbarch *gdbarch = get_current_arch ();
359 std::unique_ptr<syscall_catchpoint> c (new syscall_catchpoint ());
360 init_catchpoint (c.get (), gdbarch, tempflag, NULL, ops);
361 c->syscalls_to_be_caught = std::move (filter);
363 install_breakpoint (0, std::move (c), 1);
366 /* Splits the argument using space as delimiter. */
368 static std::vector<int>
369 catch_syscall_split_args (const char *arg)
371 std::vector<int> result;
372 struct gdbarch *gdbarch = target_gdbarch ();
374 while (*arg != '\0')
376 int i, syscall_number;
377 char *endptr;
378 char cur_name[128];
379 struct syscall s;
381 /* Skip whitespace. */
382 arg = skip_spaces (arg);
384 for (i = 0; i < 127 && arg[i] && !isspace (arg[i]); ++i)
385 cur_name[i] = arg[i];
386 cur_name[i] = '\0';
387 arg += i;
389 /* Check if the user provided a syscall name, group, or a number. */
390 syscall_number = (int) strtol (cur_name, &endptr, 0);
391 if (*endptr == '\0')
393 get_syscall_by_number (gdbarch, syscall_number, &s);
394 result.push_back (s.number);
396 else if (startswith (cur_name, "g:")
397 || startswith (cur_name, "group:"))
399 /* We have a syscall group. Let's expand it into a syscall
400 list before inserting. */
401 const char *group_name;
403 /* Skip over "g:" and "group:" prefix strings. */
404 group_name = strchr (cur_name, ':') + 1;
406 if (!get_syscalls_by_group (gdbarch, group_name, &result))
407 error (_("Unknown syscall group '%s'."), group_name);
409 else
411 /* We have a name. Let's check if it's valid and fetch a
412 list of matching numbers. */
413 if (!get_syscalls_by_name (gdbarch, cur_name, &result))
414 /* Here we have to issue an error instead of a warning,
415 because GDB cannot do anything useful if there's no
416 syscall number to be caught. */
417 error (_("Unknown syscall name '%s'."), cur_name);
421 return result;
424 /* Implement the "catch syscall" command. */
426 static void
427 catch_syscall_command_1 (const char *arg, int from_tty,
428 struct cmd_list_element *command)
430 int tempflag;
431 std::vector<int> filter;
432 struct syscall s;
433 struct gdbarch *gdbarch = get_current_arch ();
435 /* Checking if the feature if supported. */
436 if (gdbarch_get_syscall_number_p (gdbarch) == 0)
437 error (_("The feature 'catch syscall' is not supported on \
438 this architecture yet."));
440 tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
442 arg = skip_spaces (arg);
444 /* We need to do this first "dummy" translation in order
445 to get the syscall XML file loaded or, most important,
446 to display a warning to the user if there's no XML file
447 for his/her architecture. */
448 get_syscall_by_number (gdbarch, 0, &s);
450 /* The allowed syntax is:
451 catch syscall
452 catch syscall <name | number> [<name | number> ... <name | number>]
454 Let's check if there's a syscall name. */
456 if (arg != NULL)
457 filter = catch_syscall_split_args (arg);
459 create_syscall_event_catchpoint (tempflag, std::move (filter),
460 &catch_syscall_breakpoint_ops);
464 /* Returns 0 if 'bp' is NOT a syscall catchpoint,
465 non-zero otherwise. */
466 static int
467 is_syscall_catchpoint_enabled (struct breakpoint *bp)
469 if (syscall_catchpoint_p (bp)
470 && bp->enable_state != bp_disabled
471 && bp->enable_state != bp_call_disabled)
472 return 1;
473 else
474 return 0;
478 catch_syscall_enabled (void)
480 struct catch_syscall_inferior_data *inf_data
481 = get_catch_syscall_inferior_data (current_inferior ());
483 return inf_data->total_syscalls_count != 0;
486 /* Helper function for catching_syscall_number. If B is a syscall
487 catchpoint for SYSCALL_NUMBER, return 1 (which will make
488 'breakpoint_find_if' return). Otherwise, return 0. */
490 static int
491 catching_syscall_number_1 (struct breakpoint *b,
492 void *data)
494 int syscall_number = (int) (uintptr_t) data;
496 if (is_syscall_catchpoint_enabled (b))
498 struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
500 if (!c->syscalls_to_be_caught.empty ())
502 for (int iter : c->syscalls_to_be_caught)
503 if (syscall_number == iter)
504 return 1;
506 else
507 return 1;
510 return 0;
514 catching_syscall_number (int syscall_number)
516 struct breakpoint *b = breakpoint_find_if (catching_syscall_number_1,
517 (void *) (uintptr_t) syscall_number);
519 return b != NULL;
522 /* Complete syscall names. Used by "catch syscall". */
524 static void
525 catch_syscall_completer (struct cmd_list_element *cmd,
526 completion_tracker &tracker,
527 const char *text, const char *word)
529 struct gdbarch *gdbarch = get_current_arch ();
530 gdb::unique_xmalloc_ptr<const char *> group_list;
531 const char *prefix;
533 /* Completion considers ':' to be a word separator, so we use this to
534 verify whether the previous word was a group prefix. If so, we
535 build the completion list using group names only. */
536 for (prefix = word; prefix != text && prefix[-1] != ' '; prefix--)
539 if (startswith (prefix, "g:") || startswith (prefix, "group:"))
541 /* Perform completion inside 'group:' namespace only. */
542 group_list.reset (get_syscall_group_names (gdbarch));
543 if (group_list != NULL)
544 complete_on_enum (tracker, group_list.get (), word, word);
546 else
548 /* Complete with both, syscall names and groups. */
549 gdb::unique_xmalloc_ptr<const char *> syscall_list
550 (get_syscall_names (gdbarch));
551 group_list.reset (get_syscall_group_names (gdbarch));
553 const char **group_ptr = group_list.get ();
555 /* Hold on to strings while we're using them. */
556 std::vector<std::string> holders;
558 /* Append "group:" prefix to syscall groups. */
559 for (int i = 0; group_ptr[i] != NULL; i++)
560 holders.push_back (string_printf ("group:%s", group_ptr[i]));
562 for (int i = 0; group_ptr[i] != NULL; i++)
563 group_ptr[i] = holders[i].c_str ();
565 if (syscall_list != NULL)
566 complete_on_enum (tracker, syscall_list.get (), word, word);
567 if (group_list != NULL)
568 complete_on_enum (tracker, group_ptr, word, word);
572 static void
573 clear_syscall_counts (struct inferior *inf)
575 struct catch_syscall_inferior_data *inf_data
576 = get_catch_syscall_inferior_data (inf);
578 inf_data->total_syscalls_count = 0;
579 inf_data->any_syscall_count = 0;
580 inf_data->syscalls_counts.clear ();
583 static void
584 initialize_syscall_catchpoint_ops (void)
586 struct breakpoint_ops *ops;
588 initialize_breakpoint_ops ();
590 /* Syscall catchpoints. */
591 ops = &catch_syscall_breakpoint_ops;
592 *ops = base_breakpoint_ops;
593 ops->insert_location = insert_catch_syscall;
594 ops->remove_location = remove_catch_syscall;
595 ops->breakpoint_hit = breakpoint_hit_catch_syscall;
596 ops->print_it = print_it_catch_syscall;
597 ops->print_one = print_one_catch_syscall;
598 ops->print_mention = print_mention_catch_syscall;
599 ops->print_recreate = print_recreate_catch_syscall;
602 void
603 _initialize_break_catch_syscall (void)
605 initialize_syscall_catchpoint_ops ();
607 gdb::observers::inferior_exit.attach (clear_syscall_counts);
609 add_catch_command ("syscall", _("\
610 Catch system calls by their names, groups and/or numbers.\n\
611 Arguments say which system calls to catch. If no arguments are given,\n\
612 every system call will be caught. Arguments, if given, should be one\n\
613 or more system call names (if your system supports that), system call\n\
614 groups or system call numbers."),
615 catch_syscall_command_1,
616 catch_syscall_completer,
617 CATCH_PERMANENT,
618 CATCH_TEMPORARY);