Automatic date update in version.in
[external/binutils.git] / gdb / break-catch-syscall.c
1 /* Everything about syscall catchpoints, for GDB.
2
3    Copyright (C) 2009-2017 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 "observer.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 static const struct inferior_data *catch_syscall_inferior_data = NULL;
46
47 struct catch_syscall_inferior_data
48 {
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.  */
52
53   /* Number of times that "any" syscall is requested.  */
54   int any_syscall_count;
55
56   /* Count of each system call.  */
57   std::vector<int> syscalls_counts;
58
59   /* This counts all syscall catch requests, so we can readily determine
60      if any catching is necessary.  */
61   int total_syscalls_count;
62 };
63
64 static struct catch_syscall_inferior_data *
65 get_catch_syscall_inferior_data (struct inferior *inf)
66 {
67   struct catch_syscall_inferior_data *inf_data;
68
69   inf_data = ((struct catch_syscall_inferior_data *)
70               inferior_data (inf, catch_syscall_inferior_data));
71   if (inf_data == NULL)
72     {
73       inf_data = new struct catch_syscall_inferior_data ();
74       set_inferior_data (inf, catch_syscall_inferior_data, inf_data);
75     }
76
77   return inf_data;
78 }
79
80 static void
81 catch_syscall_inferior_data_cleanup (struct inferior *inf, void *arg)
82 {
83   struct catch_syscall_inferior_data *inf_data
84     = (struct catch_syscall_inferior_data *) arg;
85   delete inf_data;
86 }
87
88
89 /* Implement the "insert" breakpoint_ops method for syscall
90    catchpoints.  */
91
92 static int
93 insert_catch_syscall (struct bp_location *bl)
94 {
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);
99
100   ++inf_data->total_syscalls_count;
101   if (c->syscalls_to_be_caught.empty ())
102     ++inf_data->any_syscall_count;
103   else
104     {
105       for (int iter : c->syscalls_to_be_caught)
106         {
107           int elem;
108
109           if (iter >= inf_data->syscalls_counts.size ())
110             inf_data->syscalls_counts.resize (iter + 1);
111           ++inf_data->syscalls_counts[iter];
112         }
113     }
114
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 ());
120 }
121
122 /* Implement the "remove" breakpoint_ops method for syscall
123    catchpoints.  */
124
125 static int
126 remove_catch_syscall (struct bp_location *bl, enum remove_bp_reason reason)
127 {
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);
132
133   --inf_data->total_syscalls_count;
134   if (c->syscalls_to_be_caught.empty ())
135     --inf_data->any_syscall_count;
136   else
137     {
138       for (int iter : c->syscalls_to_be_caught)
139         {
140           int elem;
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 (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 ());
153 }
154
155 /* Implement the "breakpoint_hit" breakpoint_ops method for syscall
156    catchpoints.  */
157
158 static int
159 breakpoint_hit_catch_syscall (const struct bp_location *bl,
160                               struct address_space *aspace, CORE_ADDR bp_addr,
161                               const struct target_waitstatus *ws)
162 {
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;
169
170   if (ws->kind != TARGET_WAITKIND_SYSCALL_ENTRY
171       && ws->kind != TARGET_WAITKIND_SYSCALL_RETURN)
172     return 0;
173
174   syscall_number = ws->value.syscall_number;
175
176   /* Now, checking if the syscall is the same.  */
177   if (!c->syscalls_to_be_caught.empty ())
178     {
179       for (int iter : c->syscalls_to_be_caught)
180         if (syscall_number == iter)
181           return 1;
182
183       return 0;
184     }
185
186   return 1;
187 }
188
189 /* Implement the "print_it" breakpoint_ops method for syscall
190    catchpoints.  */
191
192 static enum print_stop_action
193 print_it_catch_syscall (bpstat bs)
194 {
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".  */
201   ptid_t ptid;
202   struct target_waitstatus last;
203   struct syscall s;
204   struct gdbarch *gdbarch = bs->bp_location_at->gdbarch;
205
206   get_last_target_status (&ptid, &last);
207
208   get_syscall_by_number (gdbarch, last.value.syscall_number, &s);
209
210   annotate_catchpoint (b->number);
211   maybe_print_thread_hit_breakpoint (uiout);
212
213   if (b->disposition == disp_del)
214     uiout->text ("Temporary catchpoint ");
215   else
216     uiout->text ("Catchpoint ");
217   if (uiout->is_mi_like_p ())
218     {
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));
224     }
225   uiout->field_int ("bkptno", b->number);
226
227   if (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY)
228     uiout->text (" (call to syscall ");
229   else
230     uiout->text (" (returned from syscall ");
231
232   if (s.name == NULL || uiout->is_mi_like_p ())
233     uiout->field_int ("syscall-number", last.value.syscall_number);
234   if (s.name != NULL)
235     uiout->field_string ("syscall-name", s.name);
236
237   uiout->text ("), ");
238
239   return PRINT_SRC_AND_LOC;
240 }
241
242 /* Implement the "print_one" breakpoint_ops method for syscall
243    catchpoints.  */
244
245 static void
246 print_one_catch_syscall (struct breakpoint *b,
247                          struct bp_location **last_loc)
248 {
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;
253
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
257      readable).  */
258   if (opts.addressprint)
259     uiout->field_skip ("addr");
260   annotate_field (5);
261
262   if (c->syscalls_to_be_caught.size () > 1)
263     uiout->text ("syscalls \"");
264   else
265     uiout->text ("syscall \"");
266
267   if (!c->syscalls_to_be_caught.empty ())
268     {
269       char *text = xstrprintf ("%s", "");
270
271       for (int iter : c->syscalls_to_be_caught)
272         {
273           char *x = text;
274           struct syscall s;
275           get_syscall_by_number (gdbarch, iter, &s);
276
277           if (s.name != NULL)
278             text = xstrprintf ("%s%s, ", text, s.name);
279           else
280             text = xstrprintf ("%s%d, ", text, iter);
281
282           /* We have to xfree the last 'text' (now stored at 'x')
283              because xstrprintf dynamically allocates new space for it
284              on every call.  */
285           xfree (x);
286         }
287       /* Remove the last comma.  */
288       text[strlen (text) - 2] = '\0';
289       uiout->field_string ("what", text);
290     }
291   else
292     uiout->field_string ("what", "<any syscall>");
293   uiout->text ("\" ");
294
295   if (uiout->is_mi_like_p ())
296     uiout->field_string ("catch-type", "syscall");
297 }
298
299 /* Implement the "print_mention" breakpoint_ops method for syscall
300    catchpoints.  */
301
302 static void
303 print_mention_catch_syscall (struct breakpoint *b)
304 {
305   struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
306   struct gdbarch *gdbarch = b->loc->gdbarch;
307
308   if (!c->syscalls_to_be_caught.empty ())
309     {
310       if (c->syscalls_to_be_caught.size () > 1)
311         printf_filtered (_("Catchpoint %d (syscalls"), b->number);
312       else
313         printf_filtered (_("Catchpoint %d (syscall"), b->number);
314
315       for (int iter : c->syscalls_to_be_caught)
316         {
317           struct syscall s;
318           get_syscall_by_number (gdbarch, iter, &s);
319
320           if (s.name != NULL)
321             printf_filtered (" '%s' [%d]", s.name, s.number);
322           else
323             printf_filtered (" %d", s.number);
324         }
325       printf_filtered (")");
326     }
327   else
328     printf_filtered (_("Catchpoint %d (any syscall)"),
329                      b->number);
330 }
331
332 /* Implement the "print_recreate" breakpoint_ops method for syscall
333    catchpoints.  */
334
335 static void
336 print_recreate_catch_syscall (struct breakpoint *b, struct ui_file *fp)
337 {
338   struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
339   struct gdbarch *gdbarch = b->loc->gdbarch;
340
341   fprintf_unfiltered (fp, "catch syscall");
342
343   for (int iter : c->syscalls_to_be_caught)
344     {
345       struct syscall s;
346
347       get_syscall_by_number (gdbarch, iter, &s);
348       if (s.name != NULL)
349         fprintf_unfiltered (fp, " %s", s.name);
350       else
351         fprintf_unfiltered (fp, " %d", s.number);
352     }
353
354   print_recreate_thread (b, fp);
355 }
356
357 /* The breakpoint_ops structure to be used in syscall catchpoints.  */
358
359 static struct breakpoint_ops catch_syscall_breakpoint_ops;
360
361 /* Returns non-zero if 'b' is a syscall catchpoint.  */
362
363 static int
364 syscall_catchpoint_p (struct breakpoint *b)
365 {
366   return (b->ops == &catch_syscall_breakpoint_ops);
367 }
368
369 static void
370 create_syscall_event_catchpoint (int tempflag, std::vector<int> &&filter,
371                                  const struct breakpoint_ops *ops)
372 {
373   struct gdbarch *gdbarch = get_current_arch ();
374
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);
378
379   install_breakpoint (0, std::move (c), 1);
380 }
381
382 /* Splits the argument using space as delimiter.  */
383
384 static std::vector<int>
385 catch_syscall_split_args (char *arg)
386 {
387   std::vector<int> result;
388   struct gdbarch *gdbarch = target_gdbarch ();
389
390   while (*arg != '\0')
391     {
392       int i, syscall_number;
393       char *endptr;
394       char cur_name[128];
395       struct syscall s;
396
397       /* Skip whitespace.  */
398       arg = skip_spaces (arg);
399
400       for (i = 0; i < 127 && arg[i] && !isspace (arg[i]); ++i)
401         cur_name[i] = arg[i];
402       cur_name[i] = '\0';
403       arg += i;
404
405       /* Check if the user provided a syscall name, group, or a number.  */
406       syscall_number = (int) strtol (cur_name, &endptr, 0);
407       if (*endptr == '\0')
408         {
409           get_syscall_by_number (gdbarch, syscall_number, &s);
410           result.push_back (s.number);
411         }
412       else if (startswith (cur_name, "g:")
413                || startswith (cur_name, "group:"))
414         {
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;
419
420           /* Skip over "g:" and "group:" prefix strings.  */
421           group_name = strchr (cur_name, ':') + 1;
422
423           syscall_list = get_syscalls_by_group (gdbarch, group_name);
424
425           if (syscall_list == NULL)
426             error (_("Unknown syscall group '%s'."), group_name);
427
428           for (i = 0; syscall_list[i].name != NULL; i++)
429             {
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);
433             }
434
435           xfree (syscall_list);
436         }
437       else
438         {
439           /* We have a name.  Let's check if it's valid and convert it
440              to a number.  */
441           get_syscall_by_name (gdbarch, cur_name, &s);
442
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);
448
449           /* Ok, it's valid.  */
450           result.push_back (s.number);
451         }
452     }
453
454   return result;
455 }
456
457 /* Implement the "catch syscall" command.  */
458
459 static void
460 catch_syscall_command_1 (char *arg, int from_tty, 
461                          struct cmd_list_element *command)
462 {
463   int tempflag;
464   std::vector<int> filter;
465   struct syscall s;
466   struct gdbarch *gdbarch = get_current_arch ();
467
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."));
472
473   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
474
475   arg = skip_spaces (arg);
476
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);
482
483   /* The allowed syntax is:
484      catch syscall
485      catch syscall <name | number> [<name | number> ... <name | number>]
486
487      Let's check if there's a syscall name.  */
488
489   if (arg != NULL)
490     filter = catch_syscall_split_args (arg);
491
492   create_syscall_event_catchpoint (tempflag, std::move (filter),
493                                    &catch_syscall_breakpoint_ops);
494 }
495
496
497 /* Returns 0 if 'bp' is NOT a syscall catchpoint,
498    non-zero otherwise.  */
499 static int
500 is_syscall_catchpoint_enabled (struct breakpoint *bp)
501 {
502   if (syscall_catchpoint_p (bp)
503       && bp->enable_state != bp_disabled
504       && bp->enable_state != bp_call_disabled)
505     return 1;
506   else
507     return 0;
508 }
509
510 int
511 catch_syscall_enabled (void)
512 {
513   struct catch_syscall_inferior_data *inf_data
514     = get_catch_syscall_inferior_data (current_inferior ());
515
516   return inf_data->total_syscalls_count != 0;
517 }
518
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.  */
522
523 static int
524 catching_syscall_number_1 (struct breakpoint *b,
525                            void *data)
526 {
527   int syscall_number = (int) (uintptr_t) data;
528
529   if (is_syscall_catchpoint_enabled (b))
530     {
531       struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
532
533       if (!c->syscalls_to_be_caught.empty ())
534         {
535           for (int iter : c->syscalls_to_be_caught)
536             if (syscall_number == iter)
537               return 1;
538         }
539       else
540         return 1;
541     }
542
543   return 0;
544 }
545
546 int
547 catching_syscall_number (int syscall_number)
548 {
549   struct breakpoint *b = breakpoint_find_if (catching_syscall_number_1,
550                                          (void *) (uintptr_t) syscall_number);
551
552   return b != NULL;
553 }
554
555 /* Complete syscall names.  Used by "catch syscall".  */
556
557 static void
558 catch_syscall_completer (struct cmd_list_element *cmd,
559                          completion_tracker &tracker,
560                          const char *text, const char *word)
561 {
562   struct gdbarch *gdbarch = get_current_arch ();
563   gdb::unique_xmalloc_ptr<const char *> group_list;
564   const char *prefix;
565   int i;
566
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--)
571     ;
572
573   if (startswith (prefix, "g:") || startswith (prefix, "group:"))
574     {
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);
579     }
580   else
581     {
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));
586
587       const char **group_ptr = group_list.get ();
588
589       /* Hold on to strings while we're using them.  */
590       std::vector<std::string> holders;
591
592       /* Append "group:" prefix to syscall groups.  */
593       for (i = 0; group_ptr[i] != NULL; i++)
594         {
595           std::string prefixed_group = string_printf ("group:%s",
596                                                       group_ptr[i]);
597
598           group_ptr[i] = prefixed_group.c_str ();
599           holders.push_back (std::move (prefixed_group));
600         }
601
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);
606     }
607 }
608
609 static void
610 clear_syscall_counts (struct inferior *inf)
611 {
612   struct catch_syscall_inferior_data *inf_data
613     = get_catch_syscall_inferior_data (inf);
614
615   inf_data->total_syscalls_count = 0;
616   inf_data->any_syscall_count = 0;
617   inf_data->syscalls_counts.clear ();
618 }
619
620 static void
621 initialize_syscall_catchpoint_ops (void)
622 {
623   struct breakpoint_ops *ops;
624
625   initialize_breakpoint_ops ();
626
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;
637 }
638
639 void
640 _initialize_break_catch_syscall (void)
641 {
642   initialize_syscall_catchpoint_ops ();
643
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);
648
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,
657                      CATCH_PERMANENT,
658                      CATCH_TEMPORARY);
659 }