Extend "skip" command to support -file, -gfile, -function, -rfunction.
[external/binutils.git] / gdb / skip.c
1 /* Skipping uninteresting files and functions while stepping.
2
3    Copyright (C) 2011-2016 Free Software Foundation, Inc.
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 #include "defs.h"
19 #include "skip.h"
20 #include "value.h"
21 #include "valprint.h"
22 #include "ui-out.h"
23 #include "symtab.h"
24 #include "gdbcmd.h"
25 #include "command.h"
26 #include "completer.h"
27 #include "stack.h"
28 #include "cli/cli-utils.h"
29 #include "arch-utils.h"
30 #include "linespec.h"
31 #include "objfiles.h"
32 #include "breakpoint.h" /* for get_sal_arch () */
33 #include "source.h"
34 #include "filenames.h"
35 #include "fnmatch.h"
36 #include "gdb_regex.h"
37
38 struct skiplist_entry
39 {
40   int number;
41
42   /* Non-zero if FILE is a glob-style pattern.
43      Otherewise it is the plain file name (possibly with directories).  */
44   int file_is_glob;
45
46   /* The name of the file or NULL.
47      The skiplist entry owns this pointer.  */
48   char *file;
49
50   /* Non-zero if FUNCTION is a regexp.
51      Otherwise it is a plain function name (possibly with arguments,
52      for C++).  */
53   int function_is_regexp;
54
55   /* The name of the function or NULL.
56      The skiplist entry owns this pointer.  */
57   char *function;
58
59   /* If this is a function regexp, the compiled form.  */
60   regex_t compiled_function_regexp;
61
62   /* Non-zero if the function regexp has been compiled.  */
63   int compiled_function_regexp_is_valid;
64
65   int enabled;
66
67   struct skiplist_entry *next;
68 };
69
70 static void add_skiplist_entry (struct skiplist_entry *e);
71
72 static struct skiplist_entry *skiplist_entry_chain;
73 static int skiplist_entry_count;
74
75 #define ALL_SKIPLIST_ENTRIES(E) \
76   for (E = skiplist_entry_chain; E; E = E->next)
77
78 #define ALL_SKIPLIST_ENTRIES_SAFE(E,TMP) \
79   for (E = skiplist_entry_chain;         \
80        E ? (TMP = E->next, 1) : 0;       \
81        E = TMP)
82
83 /* Create a skip object.  */
84
85 static struct skiplist_entry *
86 make_skip_entry (int file_is_glob, const char *file,
87                  int function_is_regexp, const char *function)
88 {
89   struct skiplist_entry *e = XCNEW (struct skiplist_entry);
90
91   gdb_assert (file != NULL || function != NULL);
92   if (file_is_glob)
93     gdb_assert (file != NULL);
94   if (function_is_regexp)
95     gdb_assert (function != NULL);
96
97   if (file != NULL)
98     e->file = xstrdup (file);
99   if (function != NULL)
100     e->function = xstrdup (function);
101   e->file_is_glob = file_is_glob;
102   e->function_is_regexp = function_is_regexp;
103   e->enabled = 1;
104
105   return e;
106 }
107
108 /* Free a skiplist entry.  */
109
110 static void
111 free_skiplist_entry (struct skiplist_entry *e)
112 {
113   xfree (e->file);
114   xfree (e->function);
115   if (e->function_is_regexp && e->compiled_function_regexp_is_valid)
116     regfree (&e->compiled_function_regexp);
117   xfree (e);
118 }
119
120 /* Wrapper to free_skiplist_entry for use as a cleanup.  */
121
122 static void
123 free_skiplist_entry_cleanup (void *e)
124 {
125   free_skiplist_entry ((struct skiplist_entry *) e);
126 }
127
128 /* Create a cleanup to free skiplist entry E.  */
129
130 static struct cleanup *
131 make_free_skiplist_entry_cleanup (struct skiplist_entry *e)
132 {
133   return make_cleanup (free_skiplist_entry_cleanup, e);
134 }
135
136 static void
137 skip_file_command (char *arg, int from_tty)
138 {
139   struct symtab *symtab;
140   const char *filename = NULL;
141
142   /* If no argument was given, try to default to the last
143      displayed codepoint.  */
144   if (arg == NULL)
145     {
146       symtab = get_last_displayed_symtab ();
147       if (symtab == NULL)
148         error (_("No default file now."));
149
150       /* It is not a typo, symtab_to_filename_for_display woule be needlessly
151          ambiguous.  */
152       filename = symtab_to_fullname (symtab);
153     }
154   else
155     filename = arg;
156
157   add_skiplist_entry (make_skip_entry (0, filename, 0, NULL));
158
159   printf_filtered (_("File %s will be skipped when stepping.\n"), filename);
160 }
161
162 /* Create a skiplist entry for the given function NAME and add it to the
163    list.  */
164
165 static void
166 skip_function (const char *name)
167 {
168   add_skiplist_entry (make_skip_entry (0, NULL, 0, name));
169
170   printf_filtered (_("Function %s will be skipped when stepping.\n"), name);
171 }
172
173 static void
174 skip_function_command (char *arg, int from_tty)
175 {
176   /* Default to the current function if no argument is given.  */
177   if (arg == NULL)
178     {
179       const char *name = NULL;
180       CORE_ADDR pc;
181
182       if (!last_displayed_sal_is_valid ())
183         error (_("No default function now."));
184
185       pc = get_last_displayed_addr ();
186       if (!find_pc_partial_function (pc, &name, NULL, NULL))
187         {
188           error (_("No function found containing current program point %s."),
189                   paddress (get_current_arch (), pc));
190         }
191       skip_function (name);
192       return;
193     }
194
195   skip_function (arg);
196 }
197
198 /* Compile the regexp in E.
199    An error is thrown if there's an error.
200    MESSAGE is used as a prefix of the error message.  */
201
202 static void
203 compile_skip_regexp (struct skiplist_entry *e, const char *message)
204 {
205   int code;
206   int flags = REG_NOSUB;
207
208 #ifdef REG_EXTENDED
209   flags |= REG_EXTENDED;
210 #endif
211
212   gdb_assert (e->function_is_regexp && e->function != NULL);
213
214   code = regcomp (&e->compiled_function_regexp, e->function, flags);
215   if (code != 0)
216     {
217       char *err = get_regcomp_error (code, &e->compiled_function_regexp);
218
219       make_cleanup (xfree, err);
220       error (_("%s: %s"), message, err);
221     }
222   e->compiled_function_regexp_is_valid = 1;
223 }
224
225 /* Process "skip ..." that does not match "skip file" or "skip function".  */
226
227 static void
228 skip_command (char *arg, int from_tty)
229 {
230   const char *file = NULL;
231   const char *gfile = NULL;
232   const char *function = NULL;
233   const char *rfunction = NULL;
234   char **argv;
235   struct cleanup *cleanups;
236   struct skiplist_entry *e;
237   int i;
238
239   if (arg == NULL)
240     {
241       skip_function_command (arg, from_tty);
242       return;
243     }
244
245   argv = buildargv (arg);
246   cleanups = make_cleanup_freeargv (argv);
247
248   for (i = 0; argv[i] != NULL; ++i)
249     {
250       const char *p = argv[i];
251       const char *value = argv[i + 1];
252
253       if (strcmp (p, "-fi") == 0
254           || strcmp (p, "-file") == 0)
255         {
256           if (value == NULL)
257             error (_("Missing value for %s option."), p);
258           file = value;
259           ++i;
260         }
261       else if (strcmp (p, "-gfi") == 0
262                || strcmp (p, "-gfile") == 0)
263         {
264           if (value == NULL)
265             error (_("Missing value for %s option."), p);
266           gfile = value;
267           ++i;
268         }
269       else if (strcmp (p, "-fu") == 0
270                || strcmp (p, "-function") == 0)
271         {
272           if (value == NULL)
273             error (_("Missing value for %s option."), p);
274           function = value;
275           ++i;
276         }
277       else if (strcmp (p, "-rfu") == 0
278                || strcmp (p, "-rfunction") == 0)
279         {
280           if (value == NULL)
281             error (_("Missing value for %s option."), p);
282           rfunction = value;
283           ++i;
284         }
285       else if (*p == '-')
286         error (_("Invalid skip option: %s"), p);
287       else if (i == 0)
288         {
289           /* Assume the user entered "skip FUNCTION-NAME".
290              FUNCTION-NAME may be `foo (int)', and therefore we pass the
291              complete original arg to skip_function command as if the user
292              typed "skip function arg".  */
293           do_cleanups (cleanups);
294           skip_function_command (arg, from_tty);
295           return;
296         }
297       else
298         error (_("Invalid argument: %s"), p);
299     }
300
301   if (file != NULL && gfile != NULL)
302     error (_("Cannot specify both -file and -gfile."));
303
304   if (function != NULL && rfunction != NULL)
305     error (_("Cannot specify both -function and -rfunction."));
306
307   /* This shouldn't happen as "skip" by itself gets punted to
308      skip_function_command.  */
309   gdb_assert (file != NULL || gfile != NULL
310               || function != NULL || rfunction != NULL);
311
312   e = make_skip_entry (gfile != NULL, file ? file : gfile,
313                        rfunction != NULL, function ? function : rfunction);
314   if (rfunction != NULL)
315     {
316       struct cleanup *rf_cleanups = make_free_skiplist_entry_cleanup (e);
317
318       compile_skip_regexp (e, _("regexp"));
319       discard_cleanups (rf_cleanups);
320     }
321   add_skiplist_entry (e);
322
323   /* I18N concerns drive some of the choices here (we can't piece together
324      the output too much).  OTOH we want to keep this simple.  Therefore the
325      only polish we add to the output is to append "(s)" to "File" or
326      "Function" if they're a glob/regexp.  */
327   {
328     const char *file_to_print = file != NULL ? file : gfile;
329     const char *function_to_print = function != NULL ? function : rfunction;
330     const char *file_text = gfile != NULL ? _("File(s)") : _("File");
331     const char *lower_file_text = gfile != NULL ? _("file(s)") : _("file");
332     const char *function_text
333       = rfunction != NULL ? _("Function(s)") : _("Function");
334
335     if (function_to_print == NULL)
336       {
337         printf_filtered (_("%s %s will be skipped when stepping.\n"),
338                          file_text, file_to_print);
339       }
340     else if (file_to_print == NULL)
341       {
342         printf_filtered (_("%s %s will be skipped when stepping.\n"),
343                          function_text, function_to_print);
344       }
345     else
346       {
347         printf_filtered (_("%s %s in %s %s will be skipped"
348                            " when stepping.\n"),
349                          function_text, function_to_print,
350                          lower_file_text, file_to_print);
351       }
352   }
353
354   do_cleanups (cleanups);
355 }
356
357 static void
358 skip_info (char *arg, int from_tty)
359 {
360   struct skiplist_entry *e;
361   int num_printable_entries = 0;
362   struct value_print_options opts;
363   struct cleanup *tbl_chain;
364
365   get_user_print_options (&opts);
366
367   /* Count the number of rows in the table and see if we need space for a
368      64-bit address anywhere.  */
369   ALL_SKIPLIST_ENTRIES (e)
370     if (arg == NULL || number_is_in_list (arg, e->number))
371       num_printable_entries++;
372
373   if (num_printable_entries == 0)
374     {
375       if (arg == NULL)
376         ui_out_message (current_uiout, 0, _("\
377 Not skipping any files or functions.\n"));
378       else
379         ui_out_message (current_uiout, 0,
380                         _("No skiplist entries found with number %s.\n"), arg);
381
382       return;
383     }
384
385   tbl_chain = make_cleanup_ui_out_table_begin_end (current_uiout, 6,
386                                                    num_printable_entries,
387                                                    "SkiplistTable");
388
389   ui_out_table_header (current_uiout, 5, ui_left, "number", "Num");   /* 1 */
390   ui_out_table_header (current_uiout, 3, ui_left, "enabled", "Enb");  /* 2 */
391   ui_out_table_header (current_uiout, 4, ui_right, "regexp", "Glob"); /* 3 */
392   ui_out_table_header (current_uiout, 20, ui_left, "file", "File");   /* 4 */
393   ui_out_table_header (current_uiout, 2, ui_right, "regexp", "RE");   /* 5 */
394   ui_out_table_header (current_uiout, 40, ui_noalign,
395                        "function", "Function"); /* 6 */
396   ui_out_table_body (current_uiout);
397
398   ALL_SKIPLIST_ENTRIES (e)
399     {
400       struct cleanup *entry_chain;
401
402       QUIT;
403       if (arg != NULL && !number_is_in_list (arg, e->number))
404         continue;
405
406       entry_chain = make_cleanup_ui_out_tuple_begin_end (current_uiout,
407                                                          "blklst-entry");
408       ui_out_field_int (current_uiout, "number", e->number); /* 1 */
409
410       if (e->enabled)
411         ui_out_field_string (current_uiout, "enabled", "y"); /* 2 */
412       else
413         ui_out_field_string (current_uiout, "enabled", "n"); /* 2 */
414
415       if (e->file_is_glob)
416         ui_out_field_string (current_uiout, "regexp", "y"); /* 3 */
417       else
418         ui_out_field_string (current_uiout, "regexp", "n"); /* 3 */
419
420       ui_out_field_string (current_uiout, "file",
421                            e->file ? e->file : "<none>"); /* 4 */
422       if (e->function_is_regexp)
423         ui_out_field_string (current_uiout, "regexp", "y"); /* 5 */
424       else
425         ui_out_field_string (current_uiout, "regexp", "n"); /* 5 */
426
427       ui_out_field_string (current_uiout, "function", 
428                            e->function ? e->function : "<none>"); /* 6 */
429
430       ui_out_text (current_uiout, "\n");
431       do_cleanups (entry_chain);
432     }
433
434   do_cleanups (tbl_chain);
435 }
436
437 static void
438 skip_enable_command (char *arg, int from_tty)
439 {
440   struct skiplist_entry *e;
441   int found = 0;
442
443   ALL_SKIPLIST_ENTRIES (e)
444     if (arg == NULL || number_is_in_list (arg, e->number))
445       {
446         e->enabled = 1;
447         found = 1;
448       }
449
450   if (!found)
451     error (_("No skiplist entries found with number %s."), arg);
452 }
453
454 static void
455 skip_disable_command (char *arg, int from_tty)
456 {
457   struct skiplist_entry *e;
458   int found = 0;
459
460   ALL_SKIPLIST_ENTRIES (e)
461     if (arg == NULL || number_is_in_list (arg, e->number))
462       {
463         e->enabled = 0;
464         found = 1;
465       }
466
467   if (!found)
468     error (_("No skiplist entries found with number %s."), arg);
469 }
470
471 static void
472 skip_delete_command (char *arg, int from_tty)
473 {
474   struct skiplist_entry *e, *temp, *b_prev;
475   int found = 0;
476
477   b_prev = 0;
478   ALL_SKIPLIST_ENTRIES_SAFE (e, temp)
479     if (arg == NULL || number_is_in_list (arg, e->number))
480       {
481         if (b_prev != NULL)
482           b_prev->next = e->next;
483         else
484           skiplist_entry_chain = e->next;
485
486         free_skiplist_entry (e);
487         found = 1;
488       }
489     else
490       {
491         b_prev = e;
492       }
493
494   if (!found)
495     error (_("No skiplist entries found with number %s."), arg);
496 }
497
498 /* Add the given skiplist entry to our list, and set the entry's number.  */
499
500 static void
501 add_skiplist_entry (struct skiplist_entry *e)
502 {
503   struct skiplist_entry *e1;
504
505   e->number = ++skiplist_entry_count;
506
507   /* Add to the end of the chain so that the list of
508      skiplist entries will be in numerical order.  */
509
510   e1 = skiplist_entry_chain;
511   if (e1 == NULL)
512     skiplist_entry_chain = e;
513   else
514     {
515       while (e1->next)
516         e1 = e1->next;
517       e1->next = e;
518     }
519 }
520
521 /* Return non-zero if we're stopped at a file to be skipped.  */
522
523 static int
524 skip_file_p (struct skiplist_entry *e,
525              const struct symtab_and_line *function_sal)
526 {
527   gdb_assert (e->file != NULL && !e->file_is_glob);
528
529   if (function_sal->symtab == NULL)
530     return 0;
531
532   /* Check first sole SYMTAB->FILENAME.  It may not be a substring of
533      symtab_to_fullname as it may contain "./" etc.  */
534   if (compare_filenames_for_search (function_sal->symtab->filename, e->file))
535     return 1;
536
537   /* Before we invoke realpath, which can get expensive when many
538      files are involved, do a quick comparison of the basenames.  */
539   if (!basenames_may_differ
540       && filename_cmp (lbasename (function_sal->symtab->filename),
541                        lbasename (e->file)) != 0)
542     return 0;
543
544   /* Note: symtab_to_fullname caches its result, thus we don't have to.  */
545   {
546     const char *fullname = symtab_to_fullname (function_sal->symtab);
547
548     if (compare_filenames_for_search (fullname, e->file))
549       return 1;
550   }
551
552   return 0;
553 }
554
555 /* Return non-zero if we're stopped at a globbed file to be skipped.  */
556
557 static int
558 skip_gfile_p (struct skiplist_entry *e,
559               const struct symtab_and_line *function_sal)
560 {
561   gdb_assert (e->file != NULL && e->file_is_glob);
562
563   if (function_sal->symtab == NULL)
564     return 0;
565
566   /* Check first sole SYMTAB->FILENAME.  It may not be a substring of
567      symtab_to_fullname as it may contain "./" etc.  */
568   if (gdb_filename_fnmatch (e->file, function_sal->symtab->filename,
569                             FNM_FILE_NAME | FNM_NOESCAPE) == 0)
570     return 1;
571
572   /* Before we invoke symtab_to_fullname, which is expensive, do a quick
573      comparison of the basenames.
574      Note that we assume that lbasename works with glob-style patterns.
575      If the basename of the glob pattern is something like "*.c" then this
576      isn't much of a win.  Oh well.  */
577   if (!basenames_may_differ
578       && gdb_filename_fnmatch (lbasename (e->file),
579                                lbasename (function_sal->symtab->filename),
580                                FNM_FILE_NAME | FNM_NOESCAPE) != 0)
581     return 0;
582
583   /* Note: symtab_to_fullname caches its result, thus we don't have to.  */
584   {
585     const char *fullname = symtab_to_fullname (function_sal->symtab);
586
587     if (compare_glob_filenames_for_search (fullname, e->file))
588       return 1;
589   }
590
591   return 0;
592 }
593
594 /* Return non-zero if we're stopped at a function to be skipped.  */
595
596 static int
597 skip_function_p (struct skiplist_entry *e, const char *function_name)
598 {
599   gdb_assert (e->function != NULL && !e->function_is_regexp);
600   return strcmp_iw (function_name, e->function) == 0;
601 }
602
603 /* Return non-zero if we're stopped at a function regexp to be skipped.  */
604
605 static int
606 skip_rfunction_p (struct skiplist_entry *e, const char *function_name)
607 {
608   gdb_assert (e->function != NULL && e->function_is_regexp
609               && e->compiled_function_regexp_is_valid);
610   return (regexec (&e->compiled_function_regexp, function_name, 0, NULL, 0)
611           == 0);
612 }
613
614 /* See skip.h.  */
615
616 int
617 function_name_is_marked_for_skip (const char *function_name,
618                                   const struct symtab_and_line *function_sal)
619 {
620   struct skiplist_entry *e;
621
622   if (function_name == NULL)
623     return 0;
624
625   ALL_SKIPLIST_ENTRIES (e)
626     {
627       int skip_by_file = 0;
628       int skip_by_function = 0;
629
630       if (!e->enabled)
631         continue;
632
633       if (e->file != NULL)
634         {
635           if (e->file_is_glob)
636             {
637               if (skip_gfile_p (e, function_sal))
638                 skip_by_file = 1;
639             }
640           else
641             {
642               if (skip_file_p (e, function_sal))
643                 skip_by_file = 1;
644             }
645         }
646       if (e->function != NULL)
647         {
648           if (e->function_is_regexp)
649             {
650               if (skip_rfunction_p (e, function_name))
651                 skip_by_function = 1;
652             }
653           else
654             {
655               if (skip_function_p (e, function_name))
656                 skip_by_function = 1;
657             }
658         }
659
660       /* If both file and function must match, make sure we don't errantly
661          exit if only one of them match.  */
662       if (e->file != NULL && e->function != NULL)
663         {
664           if (skip_by_file && skip_by_function)
665             return 1;
666         }
667       /* Only one of file/function is specified.  */
668       else if (skip_by_file || skip_by_function)
669         return 1;
670     }
671
672   return 0;
673 }
674
675 /* Provide a prototype to silence -Wmissing-prototypes.  */
676 extern initialize_file_ftype _initialize_step_skip;
677
678 void
679 _initialize_step_skip (void)
680 {
681   static struct cmd_list_element *skiplist = NULL;
682   struct cmd_list_element *c;
683
684   skiplist_entry_chain = 0;
685   skiplist_entry_count = 0;
686
687   add_prefix_cmd ("skip", class_breakpoint, skip_command, _("\
688 Ignore a function while stepping.\n\
689 \n\
690 Usage: skip [FUNCTION-NAME]\n\
691        skip [<file-spec>] [<function-spec>]\n\
692 If no arguments are given, ignore the current function.\n\
693 \n\
694 <file-spec> is one of:\n\
695        -fi|-file FILE-NAME\n\
696        -gfi|-gfile GLOB-FILE-PATTERN\n\
697 <function-spec> is one of:\n\
698        -fu|-function FUNCTION-NAME\n\
699        -rfu|-rfunction FUNCTION-NAME-REGULAR-EXPRESSION"),
700                   &skiplist, "skip ", 1, &cmdlist);
701
702   c = add_cmd ("file", class_breakpoint, skip_file_command, _("\
703 Ignore a file while stepping.\n\
704 Usage: skip file [FILE-NAME]\n\
705 If no filename is given, ignore the current file."),
706                &skiplist);
707   set_cmd_completer (c, filename_completer);
708
709   c = add_cmd ("function", class_breakpoint, skip_function_command, _("\
710 Ignore a function while stepping.\n\
711 Usage: skip function [FUNCTION-NAME]\n\
712 If no function name is given, skip the current function."),
713                &skiplist);
714   set_cmd_completer (c, location_completer);
715
716   add_cmd ("enable", class_breakpoint, skip_enable_command, _("\
717 Enable skip entries.  You can specify numbers (e.g. \"skip enable 1 3\"), \
718 ranges (e.g. \"skip enable 4-8\"), or both (e.g. \"skip enable 1 3 4-8\").\n\n\
719 If you don't specify any numbers or ranges, we'll enable all skip entries.\n\n\
720 Usage: skip enable [NUMBERS AND/OR RANGES]"),
721            &skiplist);
722
723   add_cmd ("disable", class_breakpoint, skip_disable_command, _("\
724 Disable skip entries.  You can specify numbers (e.g. \"skip disable 1 3\"), \
725 ranges (e.g. \"skip disable 4-8\"), or both (e.g. \"skip disable 1 3 4-8\").\n\n\
726 If you don't specify any numbers or ranges, we'll disable all skip entries.\n\n\
727 Usage: skip disable [NUMBERS AND/OR RANGES]"),
728            &skiplist);
729
730   add_cmd ("delete", class_breakpoint, skip_delete_command, _("\
731 Delete skip entries.  You can specify numbers (e.g. \"skip delete 1 3\"), \
732 ranges (e.g. \"skip delete 4-8\"), or both (e.g. \"skip delete 1 3 4-8\").\n\n\
733 If you don't specify any numbers or ranges, we'll delete all skip entries.\n\n\
734 Usage: skip delete [NUMBERS AND/OR RANGES]"),
735            &skiplist);
736
737   add_info ("skip", skip_info, _("\
738 Display the status of skips.  You can specify numbers (e.g. \"skip info 1 3\"), \
739 ranges (e.g. \"skip info 4-8\"), or both (e.g. \"skip info 1 3 4-8\").\n\n\
740 If you don't specify any numbers or ranges, we'll show all skips.\n\n\
741 Usage: skip info [NUMBERS AND/OR RANGES]\n\
742 The \"Type\" column indicates one of:\n\
743 \tfile        - ignored file\n\
744 \tfunction    - ignored function"));
745 }