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