Release 2.33.1
[external/binutils.git] / gdb / break-catch-syscall.c
1 /* Everything about syscall catchpoints, for GDB.
2
3    Copyright (C) 2009-2019 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
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.  */
36
37 struct syscall_catchpoint : public breakpoint
38 {
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;
43 };
44
45 struct catch_syscall_inferior_data
46 {
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.  */
50
51   /* Number of times that "any" syscall is requested.  */
52   int any_syscall_count;
53
54   /* Count of each system call.  */
55   std::vector<int> syscalls_counts;
56
57   /* This counts all syscall catch requests, so we can readily determine
58      if any catching is necessary.  */
59   int total_syscalls_count;
60 };
61
62 static const struct inferior_key<struct catch_syscall_inferior_data>
63   catch_syscall_inferior_data;
64
65 static struct catch_syscall_inferior_data *
66 get_catch_syscall_inferior_data (struct inferior *inf)
67 {
68   struct catch_syscall_inferior_data *inf_data;
69
70   inf_data = catch_syscall_inferior_data.get (inf);
71   if (inf_data == NULL)
72     inf_data = catch_syscall_inferior_data.emplace (inf);
73
74   return inf_data;
75 }
76
77 /* Implement the "insert" breakpoint_ops method for syscall
78    catchpoints.  */
79
80 static int
81 insert_catch_syscall (struct bp_location *bl)
82 {
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);
87
88   ++inf_data->total_syscalls_count;
89   if (c->syscalls_to_be_caught.empty ())
90     ++inf_data->any_syscall_count;
91   else
92     {
93       for (int iter : c->syscalls_to_be_caught)
94         {
95           if (iter >= inf_data->syscalls_counts.size ())
96             inf_data->syscalls_counts.resize (iter + 1);
97           ++inf_data->syscalls_counts[iter];
98         }
99     }
100
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);
105 }
106
107 /* Implement the "remove" breakpoint_ops method for syscall
108    catchpoints.  */
109
110 static int
111 remove_catch_syscall (struct bp_location *bl, enum remove_bp_reason reason)
112 {
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);
117
118   --inf_data->total_syscalls_count;
119   if (c->syscalls_to_be_caught.empty ())
120     --inf_data->any_syscall_count;
121   else
122     {
123       for (int iter : c->syscalls_to_be_caught)
124         {
125           if (iter >= inf_data->syscalls_counts.size ())
126             /* Shouldn't happen.  */
127             continue;
128           --inf_data->syscalls_counts[iter];
129         }
130     }
131
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);
136 }
137
138 /* Implement the "breakpoint_hit" breakpoint_ops method for syscall
139    catchpoints.  */
140
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)
145 {
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;
152
153   if (ws->kind != TARGET_WAITKIND_SYSCALL_ENTRY
154       && ws->kind != TARGET_WAITKIND_SYSCALL_RETURN)
155     return 0;
156
157   syscall_number = ws->value.syscall_number;
158
159   /* Now, checking if the syscall is the same.  */
160   if (!c->syscalls_to_be_caught.empty ())
161     {
162       for (int iter : c->syscalls_to_be_caught)
163         if (syscall_number == iter)
164           return 1;
165
166       return 0;
167     }
168
169   return 1;
170 }
171
172 /* Implement the "print_it" breakpoint_ops method for syscall
173    catchpoints.  */
174
175 static enum print_stop_action
176 print_it_catch_syscall (bpstat bs)
177 {
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;
188
189   get_last_target_status (&ptid, &last);
190
191   get_syscall_by_number (gdbarch, last.value.syscall_number, &s);
192
193   annotate_catchpoint (b->number);
194   maybe_print_thread_hit_breakpoint (uiout);
195
196   if (b->disposition == disp_del)
197     uiout->text ("Temporary catchpoint ");
198   else
199     uiout->text ("Catchpoint ");
200   if (uiout->is_mi_like_p ())
201     {
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));
207     }
208   uiout->field_signed ("bkptno", b->number);
209
210   if (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY)
211     uiout->text (" (call to syscall ");
212   else
213     uiout->text (" (returned from syscall ");
214
215   if (s.name == NULL || uiout->is_mi_like_p ())
216     uiout->field_signed ("syscall-number", last.value.syscall_number);
217   if (s.name != NULL)
218     uiout->field_string ("syscall-name", s.name);
219
220   uiout->text ("), ");
221
222   return PRINT_SRC_AND_LOC;
223 }
224
225 /* Implement the "print_one" breakpoint_ops method for syscall
226    catchpoints.  */
227
228 static void
229 print_one_catch_syscall (struct breakpoint *b,
230                          struct bp_location **last_loc)
231 {
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;
236
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);
244
245   if (c->syscalls_to_be_caught.size () > 1)
246     uiout->text ("syscalls \"");
247   else
248     uiout->text ("syscall \"");
249
250   if (!c->syscalls_to_be_caught.empty ())
251     {
252       char *text = xstrprintf ("%s", "");
253
254       for (int iter : c->syscalls_to_be_caught)
255         {
256           char *previous_text = text;
257           struct syscall s;
258           get_syscall_by_number (gdbarch, iter, &s);
259
260           if (s.name != NULL)
261             text = xstrprintf ("%s%s, ", text, s.name);
262           else
263             text = xstrprintf ("%s%d, ", text, iter);
264
265           /* We have to xfree previous_text because xstrprintf dynamically
266              allocates new space for text on every call.  */
267           xfree (previous_text);
268         }
269       /* Remove the last comma.  */
270       text[strlen (text) - 2] = '\0';
271       uiout->field_string ("what", text);
272       /* xfree last text.  */
273       xfree (text);
274     }
275   else
276     uiout->field_string ("what", "<any syscall>");
277   uiout->text ("\" ");
278
279   if (uiout->is_mi_like_p ())
280     uiout->field_string ("catch-type", "syscall");
281 }
282
283 /* Implement the "print_mention" breakpoint_ops method for syscall
284    catchpoints.  */
285
286 static void
287 print_mention_catch_syscall (struct breakpoint *b)
288 {
289   struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
290   struct gdbarch *gdbarch = b->loc->gdbarch;
291
292   if (!c->syscalls_to_be_caught.empty ())
293     {
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);
298
299       for (int iter : c->syscalls_to_be_caught)
300         {
301           struct syscall s;
302           get_syscall_by_number (gdbarch, iter, &s);
303
304           if (s.name != NULL)
305             printf_filtered (" '%s' [%d]", s.name, s.number);
306           else
307             printf_filtered (" %d", s.number);
308         }
309       printf_filtered (")");
310     }
311   else
312     printf_filtered (_("Catchpoint %d (any syscall)"),
313                      b->number);
314 }
315
316 /* Implement the "print_recreate" breakpoint_ops method for syscall
317    catchpoints.  */
318
319 static void
320 print_recreate_catch_syscall (struct breakpoint *b, struct ui_file *fp)
321 {
322   struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
323   struct gdbarch *gdbarch = b->loc->gdbarch;
324
325   fprintf_unfiltered (fp, "catch syscall");
326
327   for (int iter : c->syscalls_to_be_caught)
328     {
329       struct syscall s;
330
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);
336     }
337
338   print_recreate_thread (b, fp);
339 }
340
341 /* The breakpoint_ops structure to be used in syscall catchpoints.  */
342
343 static struct breakpoint_ops catch_syscall_breakpoint_ops;
344
345 /* Returns non-zero if 'b' is a syscall catchpoint.  */
346
347 static int
348 syscall_catchpoint_p (struct breakpoint *b)
349 {
350   return (b->ops == &catch_syscall_breakpoint_ops);
351 }
352
353 static void
354 create_syscall_event_catchpoint (int tempflag, std::vector<int> &&filter,
355                                  const struct breakpoint_ops *ops)
356 {
357   struct gdbarch *gdbarch = get_current_arch ();
358
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);
362
363   install_breakpoint (0, std::move (c), 1);
364 }
365
366 /* Splits the argument using space as delimiter.  */
367
368 static std::vector<int>
369 catch_syscall_split_args (const char *arg)
370 {
371   std::vector<int> result;
372   struct gdbarch *gdbarch = target_gdbarch ();
373
374   while (*arg != '\0')
375     {
376       int i, syscall_number;
377       char *endptr;
378       char cur_name[128];
379       struct syscall s;
380
381       /* Skip whitespace.  */
382       arg = skip_spaces (arg);
383
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;
388
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')
392         {
393           get_syscall_by_number (gdbarch, syscall_number, &s);
394           result.push_back (s.number);
395         }
396       else if (startswith (cur_name, "g:")
397                || startswith (cur_name, "group:"))
398         {
399           /* We have a syscall group.  Let's expand it into a syscall
400              list before inserting.  */
401           const char *group_name;
402
403           /* Skip over "g:" and "group:" prefix strings.  */
404           group_name = strchr (cur_name, ':') + 1;
405
406           if (!get_syscalls_by_group (gdbarch, group_name, &result))
407             error (_("Unknown syscall group '%s'."), group_name);
408         }
409       else
410         {
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);
418         }
419     }
420
421   return result;
422 }
423
424 /* Implement the "catch syscall" command.  */
425
426 static void
427 catch_syscall_command_1 (const char *arg, int from_tty, 
428                          struct cmd_list_element *command)
429 {
430   int tempflag;
431   std::vector<int> filter;
432   struct syscall s;
433   struct gdbarch *gdbarch = get_current_arch ();
434
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."));
439
440   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
441
442   arg = skip_spaces (arg);
443
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);
449
450   /* The allowed syntax is:
451      catch syscall
452      catch syscall <name | number> [<name | number> ... <name | number>]
453
454      Let's check if there's a syscall name.  */
455
456   if (arg != NULL)
457     filter = catch_syscall_split_args (arg);
458
459   create_syscall_event_catchpoint (tempflag, std::move (filter),
460                                    &catch_syscall_breakpoint_ops);
461 }
462
463
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)
468 {
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;
475 }
476
477 int
478 catch_syscall_enabled (void)
479 {
480   struct catch_syscall_inferior_data *inf_data
481     = get_catch_syscall_inferior_data (current_inferior ());
482
483   return inf_data->total_syscalls_count != 0;
484 }
485
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.  */
489
490 static int
491 catching_syscall_number_1 (struct breakpoint *b,
492                            void *data)
493 {
494   int syscall_number = (int) (uintptr_t) data;
495
496   if (is_syscall_catchpoint_enabled (b))
497     {
498       struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
499
500       if (!c->syscalls_to_be_caught.empty ())
501         {
502           for (int iter : c->syscalls_to_be_caught)
503             if (syscall_number == iter)
504               return 1;
505         }
506       else
507         return 1;
508     }
509
510   return 0;
511 }
512
513 int
514 catching_syscall_number (int syscall_number)
515 {
516   struct breakpoint *b = breakpoint_find_if (catching_syscall_number_1,
517                                          (void *) (uintptr_t) syscall_number);
518
519   return b != NULL;
520 }
521
522 /* Complete syscall names.  Used by "catch syscall".  */
523
524 static void
525 catch_syscall_completer (struct cmd_list_element *cmd,
526                          completion_tracker &tracker,
527                          const char *text, const char *word)
528 {
529   struct gdbarch *gdbarch = get_current_arch ();
530   gdb::unique_xmalloc_ptr<const char *> group_list;
531   const char *prefix;
532
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--)
537     ;
538
539   if (startswith (prefix, "g:") || startswith (prefix, "group:"))
540     {
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);
545     }
546   else
547     {
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));
552
553       const char **group_ptr = group_list.get ();
554
555       /* Hold on to strings while we're using them.  */
556       std::vector<std::string> holders;
557
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]));
561
562       for (int i = 0; group_ptr[i] != NULL; i++)
563         group_ptr[i] = holders[i].c_str ();
564
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);
569     }
570 }
571
572 static void
573 clear_syscall_counts (struct inferior *inf)
574 {
575   struct catch_syscall_inferior_data *inf_data
576     = get_catch_syscall_inferior_data (inf);
577
578   inf_data->total_syscalls_count = 0;
579   inf_data->any_syscall_count = 0;
580   inf_data->syscalls_counts.clear ();
581 }
582
583 static void
584 initialize_syscall_catchpoint_ops (void)
585 {
586   struct breakpoint_ops *ops;
587
588   initialize_breakpoint_ops ();
589
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;
600 }
601
602 void
603 _initialize_break_catch_syscall (void)
604 {
605   initialize_syscall_catchpoint_ops ();
606
607   gdb::observers::inferior_exit.attach (clear_syscall_counts);
608
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);
619 }