Add AArch64 Pointer Authentication to the NEWS file
[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 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           if (iter >= inf_data->syscalls_counts.size ())
108             inf_data->syscalls_counts.resize (iter + 1);
109           ++inf_data->syscalls_counts[iter];
110         }
111     }
112
113   return target_set_syscall_catchpoint (inferior_ptid.pid (),
114                                         inf_data->total_syscalls_count != 0,
115                                         inf_data->any_syscall_count,
116                                         inf_data->syscalls_counts);
117 }
118
119 /* Implement the "remove" breakpoint_ops method for syscall
120    catchpoints.  */
121
122 static int
123 remove_catch_syscall (struct bp_location *bl, enum remove_bp_reason reason)
124 {
125   struct syscall_catchpoint *c = (struct syscall_catchpoint *) bl->owner;
126   struct inferior *inf = current_inferior ();
127   struct catch_syscall_inferior_data *inf_data
128     = get_catch_syscall_inferior_data (inf);
129
130   --inf_data->total_syscalls_count;
131   if (c->syscalls_to_be_caught.empty ())
132     --inf_data->any_syscall_count;
133   else
134     {
135       for (int iter : c->syscalls_to_be_caught)
136         {
137           if (iter >= inf_data->syscalls_counts.size ())
138             /* Shouldn't happen.  */
139             continue;
140           --inf_data->syscalls_counts[iter];
141         }
142     }
143
144   return target_set_syscall_catchpoint (inferior_ptid.pid (),
145                                         inf_data->total_syscalls_count != 0,
146                                         inf_data->any_syscall_count,
147                                         inf_data->syscalls_counts);
148 }
149
150 /* Implement the "breakpoint_hit" breakpoint_ops method for syscall
151    catchpoints.  */
152
153 static int
154 breakpoint_hit_catch_syscall (const struct bp_location *bl,
155                               const address_space *aspace, CORE_ADDR bp_addr,
156                               const struct target_waitstatus *ws)
157 {
158   /* We must check if we are catching specific syscalls in this
159      breakpoint.  If we are, then we must guarantee that the called
160      syscall is the same syscall we are catching.  */
161   int syscall_number = 0;
162   const struct syscall_catchpoint *c
163     = (const struct syscall_catchpoint *) bl->owner;
164
165   if (ws->kind != TARGET_WAITKIND_SYSCALL_ENTRY
166       && ws->kind != TARGET_WAITKIND_SYSCALL_RETURN)
167     return 0;
168
169   syscall_number = ws->value.syscall_number;
170
171   /* Now, checking if the syscall is the same.  */
172   if (!c->syscalls_to_be_caught.empty ())
173     {
174       for (int iter : c->syscalls_to_be_caught)
175         if (syscall_number == iter)
176           return 1;
177
178       return 0;
179     }
180
181   return 1;
182 }
183
184 /* Implement the "print_it" breakpoint_ops method for syscall
185    catchpoints.  */
186
187 static enum print_stop_action
188 print_it_catch_syscall (bpstat bs)
189 {
190   struct ui_out *uiout = current_uiout;
191   struct breakpoint *b = bs->breakpoint_at;
192   /* These are needed because we want to know in which state a
193      syscall is.  It can be in the TARGET_WAITKIND_SYSCALL_ENTRY
194      or TARGET_WAITKIND_SYSCALL_RETURN, and depending on it we
195      must print "called syscall" or "returned from syscall".  */
196   ptid_t ptid;
197   struct target_waitstatus last;
198   struct syscall s;
199   struct gdbarch *gdbarch = bs->bp_location_at->gdbarch;
200
201   get_last_target_status (&ptid, &last);
202
203   get_syscall_by_number (gdbarch, last.value.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_int ("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_int ("syscall-number", last.value.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" breakpoint_ops method for syscall
238    catchpoints.  */
239
240 static void
241 print_one_catch_syscall (struct breakpoint *b,
242                          struct bp_location **last_loc)
243 {
244   struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
245   struct value_print_options opts;
246   struct ui_out *uiout = current_uiout;
247   struct gdbarch *gdbarch = b->loc->gdbarch;
248
249   get_user_print_options (&opts);
250   /* Field 4, the address, is omitted (which makes the columns not
251      line up too nicely with the headers, but the effect is relatively
252      readable).  */
253   if (opts.addressprint)
254     uiout->field_skip ("addr");
255   annotate_field (5);
256
257   if (c->syscalls_to_be_caught.size () > 1)
258     uiout->text ("syscalls \"");
259   else
260     uiout->text ("syscall \"");
261
262   if (!c->syscalls_to_be_caught.empty ())
263     {
264       char *text = xstrprintf ("%s", "");
265
266       for (int iter : c->syscalls_to_be_caught)
267         {
268           char *previous_text = text;
269           struct syscall s;
270           get_syscall_by_number (gdbarch, iter, &s);
271
272           if (s.name != NULL)
273             text = xstrprintf ("%s%s, ", text, s.name);
274           else
275             text = xstrprintf ("%s%d, ", text, iter);
276
277           /* We have to xfree previous_text because xstrprintf dynamically
278              allocates new space for text on every call.  */
279           xfree (previous_text);
280         }
281       /* Remove the last comma.  */
282       text[strlen (text) - 2] = '\0';
283       uiout->field_string ("what", text);
284       /* xfree last text.  */
285       xfree (text);
286     }
287   else
288     uiout->field_string ("what", "<any syscall>");
289   uiout->text ("\" ");
290
291   if (uiout->is_mi_like_p ())
292     uiout->field_string ("catch-type", "syscall");
293 }
294
295 /* Implement the "print_mention" breakpoint_ops method for syscall
296    catchpoints.  */
297
298 static void
299 print_mention_catch_syscall (struct breakpoint *b)
300 {
301   struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
302   struct gdbarch *gdbarch = b->loc->gdbarch;
303
304   if (!c->syscalls_to_be_caught.empty ())
305     {
306       if (c->syscalls_to_be_caught.size () > 1)
307         printf_filtered (_("Catchpoint %d (syscalls"), b->number);
308       else
309         printf_filtered (_("Catchpoint %d (syscall"), b->number);
310
311       for (int iter : c->syscalls_to_be_caught)
312         {
313           struct syscall s;
314           get_syscall_by_number (gdbarch, iter, &s);
315
316           if (s.name != NULL)
317             printf_filtered (" '%s' [%d]", s.name, s.number);
318           else
319             printf_filtered (" %d", s.number);
320         }
321       printf_filtered (")");
322     }
323   else
324     printf_filtered (_("Catchpoint %d (any syscall)"),
325                      b->number);
326 }
327
328 /* Implement the "print_recreate" breakpoint_ops method for syscall
329    catchpoints.  */
330
331 static void
332 print_recreate_catch_syscall (struct breakpoint *b, struct ui_file *fp)
333 {
334   struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
335   struct gdbarch *gdbarch = b->loc->gdbarch;
336
337   fprintf_unfiltered (fp, "catch syscall");
338
339   for (int iter : c->syscalls_to_be_caught)
340     {
341       struct syscall s;
342
343       get_syscall_by_number (gdbarch, iter, &s);
344       if (s.name != NULL)
345         fprintf_unfiltered (fp, " %s", s.name);
346       else
347         fprintf_unfiltered (fp, " %d", s.number);
348     }
349
350   print_recreate_thread (b, fp);
351 }
352
353 /* The breakpoint_ops structure to be used in syscall catchpoints.  */
354
355 static struct breakpoint_ops catch_syscall_breakpoint_ops;
356
357 /* Returns non-zero if 'b' is a syscall catchpoint.  */
358
359 static int
360 syscall_catchpoint_p (struct breakpoint *b)
361 {
362   return (b->ops == &catch_syscall_breakpoint_ops);
363 }
364
365 static void
366 create_syscall_event_catchpoint (int tempflag, std::vector<int> &&filter,
367                                  const struct breakpoint_ops *ops)
368 {
369   struct gdbarch *gdbarch = get_current_arch ();
370
371   std::unique_ptr<syscall_catchpoint> c (new syscall_catchpoint ());
372   init_catchpoint (c.get (), gdbarch, tempflag, NULL, ops);
373   c->syscalls_to_be_caught = std::move (filter);
374
375   install_breakpoint (0, std::move (c), 1);
376 }
377
378 /* Splits the argument using space as delimiter.  */
379
380 static std::vector<int>
381 catch_syscall_split_args (const char *arg)
382 {
383   std::vector<int> result;
384   struct gdbarch *gdbarch = target_gdbarch ();
385
386   while (*arg != '\0')
387     {
388       int i, syscall_number;
389       char *endptr;
390       char cur_name[128];
391       struct syscall s;
392
393       /* Skip whitespace.  */
394       arg = skip_spaces (arg);
395
396       for (i = 0; i < 127 && arg[i] && !isspace (arg[i]); ++i)
397         cur_name[i] = arg[i];
398       cur_name[i] = '\0';
399       arg += i;
400
401       /* Check if the user provided a syscall name, group, or a number.  */
402       syscall_number = (int) strtol (cur_name, &endptr, 0);
403       if (*endptr == '\0')
404         {
405           get_syscall_by_number (gdbarch, syscall_number, &s);
406           result.push_back (s.number);
407         }
408       else if (startswith (cur_name, "g:")
409                || startswith (cur_name, "group:"))
410         {
411           /* We have a syscall group.  Let's expand it into a syscall
412              list before inserting.  */
413           const char *group_name;
414
415           /* Skip over "g:" and "group:" prefix strings.  */
416           group_name = strchr (cur_name, ':') + 1;
417
418           if (!get_syscalls_by_group (gdbarch, group_name, &result))
419             error (_("Unknown syscall group '%s'."), group_name);
420         }
421       else
422         {
423           /* We have a name.  Let's check if it's valid and fetch a
424              list of matching numbers.  */
425           if (!get_syscalls_by_name (gdbarch, cur_name, &result))
426             /* Here we have to issue an error instead of a warning,
427                because GDB cannot do anything useful if there's no
428                syscall number to be caught.  */
429             error (_("Unknown syscall name '%s'."), cur_name);
430         }
431     }
432
433   return result;
434 }
435
436 /* Implement the "catch syscall" command.  */
437
438 static void
439 catch_syscall_command_1 (const char *arg, int from_tty, 
440                          struct cmd_list_element *command)
441 {
442   int tempflag;
443   std::vector<int> filter;
444   struct syscall s;
445   struct gdbarch *gdbarch = get_current_arch ();
446
447   /* Checking if the feature if supported.  */
448   if (gdbarch_get_syscall_number_p (gdbarch) == 0)
449     error (_("The feature 'catch syscall' is not supported on \
450 this architecture yet."));
451
452   tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
453
454   arg = skip_spaces (arg);
455
456   /* We need to do this first "dummy" translation in order
457      to get the syscall XML file loaded or, most important,
458      to display a warning to the user if there's no XML file
459      for his/her architecture.  */
460   get_syscall_by_number (gdbarch, 0, &s);
461
462   /* The allowed syntax is:
463      catch syscall
464      catch syscall <name | number> [<name | number> ... <name | number>]
465
466      Let's check if there's a syscall name.  */
467
468   if (arg != NULL)
469     filter = catch_syscall_split_args (arg);
470
471   create_syscall_event_catchpoint (tempflag, std::move (filter),
472                                    &catch_syscall_breakpoint_ops);
473 }
474
475
476 /* Returns 0 if 'bp' is NOT a syscall catchpoint,
477    non-zero otherwise.  */
478 static int
479 is_syscall_catchpoint_enabled (struct breakpoint *bp)
480 {
481   if (syscall_catchpoint_p (bp)
482       && bp->enable_state != bp_disabled
483       && bp->enable_state != bp_call_disabled)
484     return 1;
485   else
486     return 0;
487 }
488
489 int
490 catch_syscall_enabled (void)
491 {
492   struct catch_syscall_inferior_data *inf_data
493     = get_catch_syscall_inferior_data (current_inferior ());
494
495   return inf_data->total_syscalls_count != 0;
496 }
497
498 /* Helper function for catching_syscall_number.  If B is a syscall
499    catchpoint for SYSCALL_NUMBER, return 1 (which will make
500    'breakpoint_find_if' return).  Otherwise, return 0.  */
501
502 static int
503 catching_syscall_number_1 (struct breakpoint *b,
504                            void *data)
505 {
506   int syscall_number = (int) (uintptr_t) data;
507
508   if (is_syscall_catchpoint_enabled (b))
509     {
510       struct syscall_catchpoint *c = (struct syscall_catchpoint *) b;
511
512       if (!c->syscalls_to_be_caught.empty ())
513         {
514           for (int iter : c->syscalls_to_be_caught)
515             if (syscall_number == iter)
516               return 1;
517         }
518       else
519         return 1;
520     }
521
522   return 0;
523 }
524
525 int
526 catching_syscall_number (int syscall_number)
527 {
528   struct breakpoint *b = breakpoint_find_if (catching_syscall_number_1,
529                                          (void *) (uintptr_t) syscall_number);
530
531   return b != NULL;
532 }
533
534 /* Complete syscall names.  Used by "catch syscall".  */
535
536 static void
537 catch_syscall_completer (struct cmd_list_element *cmd,
538                          completion_tracker &tracker,
539                          const char *text, const char *word)
540 {
541   struct gdbarch *gdbarch = get_current_arch ();
542   gdb::unique_xmalloc_ptr<const char *> group_list;
543   const char *prefix;
544
545   /* Completion considers ':' to be a word separator, so we use this to
546      verify whether the previous word was a group prefix.  If so, we
547      build the completion list using group names only.  */
548   for (prefix = word; prefix != text && prefix[-1] != ' '; prefix--)
549     ;
550
551   if (startswith (prefix, "g:") || startswith (prefix, "group:"))
552     {
553       /* Perform completion inside 'group:' namespace only.  */
554       group_list.reset (get_syscall_group_names (gdbarch));
555       if (group_list != NULL)
556         complete_on_enum (tracker, group_list.get (), word, word);
557     }
558   else
559     {
560       /* Complete with both, syscall names and groups.  */
561       gdb::unique_xmalloc_ptr<const char *> syscall_list
562         (get_syscall_names (gdbarch));
563       group_list.reset (get_syscall_group_names (gdbarch));
564
565       const char **group_ptr = group_list.get ();
566
567       /* Hold on to strings while we're using them.  */
568       std::vector<std::string> holders;
569
570       /* Append "group:" prefix to syscall groups.  */
571       for (int i = 0; group_ptr[i] != NULL; i++)
572         holders.push_back (string_printf ("group:%s", group_ptr[i]));
573
574       for (int i = 0; group_ptr[i] != NULL; i++)
575         group_ptr[i] = holders[i].c_str ();
576
577       if (syscall_list != NULL)
578         complete_on_enum (tracker, syscall_list.get (), word, word);
579       if (group_list != NULL)
580         complete_on_enum (tracker, group_ptr, word, word);
581     }
582 }
583
584 static void
585 clear_syscall_counts (struct inferior *inf)
586 {
587   struct catch_syscall_inferior_data *inf_data
588     = get_catch_syscall_inferior_data (inf);
589
590   inf_data->total_syscalls_count = 0;
591   inf_data->any_syscall_count = 0;
592   inf_data->syscalls_counts.clear ();
593 }
594
595 static void
596 initialize_syscall_catchpoint_ops (void)
597 {
598   struct breakpoint_ops *ops;
599
600   initialize_breakpoint_ops ();
601
602   /* Syscall catchpoints.  */
603   ops = &catch_syscall_breakpoint_ops;
604   *ops = base_breakpoint_ops;
605   ops->insert_location = insert_catch_syscall;
606   ops->remove_location = remove_catch_syscall;
607   ops->breakpoint_hit = breakpoint_hit_catch_syscall;
608   ops->print_it = print_it_catch_syscall;
609   ops->print_one = print_one_catch_syscall;
610   ops->print_mention = print_mention_catch_syscall;
611   ops->print_recreate = print_recreate_catch_syscall;
612 }
613
614 void
615 _initialize_break_catch_syscall (void)
616 {
617   initialize_syscall_catchpoint_ops ();
618
619   gdb::observers::inferior_exit.attach (clear_syscall_counts);
620   catch_syscall_inferior_data
621     = register_inferior_data_with_cleanup (NULL,
622                                            catch_syscall_inferior_data_cleanup);
623
624   add_catch_command ("syscall", _("\
625 Catch system calls by their names, groups and/or numbers.\n\
626 Arguments say which system calls to catch.  If no arguments are given,\n\
627 every system call will be caught.  Arguments, if given, should be one\n\
628 or more system call names (if your system supports that), system call\n\
629 groups or system call numbers."),
630                      catch_syscall_command_1,
631                      catch_syscall_completer,
632                      CATCH_PERMANENT,
633                      CATCH_TEMPORARY);
634 }