1 /* Skipping uninteresting files and functions while stepping.
3 Copyright (C) 2011-2019 Free Software Foundation, Inc.
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.
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.
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/>. */
26 #include "completer.h"
28 #include "cli/cli-utils.h"
29 #include "arch-utils.h"
32 #include "breakpoint.h" /* for get_sal_arch () */
34 #include "filenames.h"
36 #include "gdb_regex.h"
37 #include "gdbsupport/gdb_optional.h"
39 #include "cli/cli-style.h"
41 /* True if we want to print debug printouts related to file/function
43 static bool debug_skip
= false;
48 /* Create a skiplist_entry object and add it to the chain. */
49 static void add_entry (bool file_is_glob
,
51 bool function_is_regexp
,
52 std::string
&&function
);
54 /* Return true if the skip entry has a file or glob-style file
55 pattern that matches FUNCTION_SAL. */
56 bool skip_file_p (const symtab_and_line
&function_sal
) const;
58 /* Return true if the skip entry has a function or function regexp
59 that matches FUNCTION_NAME. */
60 bool skip_function_p (const char *function_name
) const;
63 int number () const { return m_number
; };
64 bool enabled () const { return m_enabled
; };
65 bool file_is_glob () const { return m_file_is_glob
; }
66 const std::string
&file () const { return m_file
; }
67 const std::string
&function () const { return m_function
; }
68 bool function_is_regexp () const { return m_function_is_regexp
; }
71 void enable () { m_enabled
= true; };
72 void disable () { m_enabled
= false; };
75 skiplist_entry (const skiplist_entry
&) = delete;
76 void operator= (const skiplist_entry
&) = delete;
79 /* Key that grants access to the constructor. */
80 struct private_key
{};
82 /* Public so we can construct with container::emplace_back. Since
83 it requires a private class key, it can't be called from outside.
84 Use the add_entry static factory method to construct instead. */
85 skiplist_entry (bool file_is_glob
, std::string
&&file
,
86 bool function_is_regexp
, std::string
&&function
,
90 /* Return true if we're stopped at a file to be skipped. */
91 bool do_skip_file_p (const symtab_and_line
&function_sal
) const;
93 /* Return true if we're stopped at a globbed file to be skipped. */
94 bool do_skip_gfile_p (const symtab_and_line
&function_sal
) const;
99 /* True if FILE is a glob-style pattern.
100 Otherwise it is the plain file name (possibly with directories). */
103 /* The name of the file or empty if no name. */
106 /* True if FUNCTION is a regexp.
107 Otherwise it is a plain function name (possibly with arguments,
109 bool m_function_is_regexp
;
111 /* The name of the function or empty if no name. */
112 std::string m_function
;
114 /* If this is a function regexp, the compiled form. */
115 gdb::optional
<compiled_regex
> m_compiled_function_regexp
;
117 /* Enabled/disabled state. */
118 bool m_enabled
= true;
121 static std::list
<skiplist_entry
> skiplist_entries
;
122 static int highest_skiplist_entry_num
= 0;
124 skiplist_entry::skiplist_entry (bool file_is_glob
,
126 bool function_is_regexp
,
127 std::string
&&function
,
129 : m_file_is_glob (file_is_glob
),
130 m_file (std::move (file
)),
131 m_function_is_regexp (function_is_regexp
),
132 m_function (std::move (function
))
134 gdb_assert (!m_file
.empty () || !m_function
.empty ());
137 gdb_assert (!m_file
.empty ());
139 if (m_function_is_regexp
)
141 gdb_assert (!m_function
.empty ());
143 int flags
= REG_NOSUB
;
145 flags
|= REG_EXTENDED
;
148 gdb_assert (!m_function
.empty ());
149 m_compiled_function_regexp
.emplace (m_function
.c_str (), flags
,
155 skiplist_entry::add_entry (bool file_is_glob
, std::string
&&file
,
156 bool function_is_regexp
, std::string
&&function
)
158 skiplist_entries
.emplace_back (file_is_glob
,
161 std::move (function
),
164 /* Incremented after push_back, in case push_back throws. */
165 skiplist_entries
.back ().m_number
= ++highest_skiplist_entry_num
;
169 skip_file_command (const char *arg
, int from_tty
)
171 struct symtab
*symtab
;
172 const char *filename
= NULL
;
174 /* If no argument was given, try to default to the last
175 displayed codepoint. */
178 symtab
= get_last_displayed_symtab ();
180 error (_("No default file now."));
182 /* It is not a typo, symtab_to_filename_for_display woule be needlessly
184 filename
= symtab_to_fullname (symtab
);
189 skiplist_entry::add_entry (false, std::string (filename
),
190 false, std::string ());
192 printf_filtered (_("File %s will be skipped when stepping.\n"), filename
);
195 /* Create a skiplist entry for the given function NAME and add it to the
199 skip_function (const char *name
)
201 skiplist_entry::add_entry (false, std::string (), false, std::string (name
));
203 printf_filtered (_("Function %s will be skipped when stepping.\n"), name
);
207 skip_function_command (const char *arg
, int from_tty
)
209 /* Default to the current function if no argument is given. */
212 const char *name
= NULL
;
215 if (!last_displayed_sal_is_valid ())
216 error (_("No default function now."));
218 pc
= get_last_displayed_addr ();
219 if (!find_pc_partial_function (pc
, &name
, NULL
, NULL
))
221 error (_("No function found containing current program point %s."),
222 paddress (get_current_arch (), pc
));
224 skip_function (name
);
231 /* Process "skip ..." that does not match "skip file" or "skip function". */
234 skip_command (const char *arg
, int from_tty
)
236 const char *file
= NULL
;
237 const char *gfile
= NULL
;
238 const char *function
= NULL
;
239 const char *rfunction
= NULL
;
244 skip_function_command (arg
, from_tty
);
250 for (i
= 0; argv
[i
] != NULL
; ++i
)
252 const char *p
= argv
[i
];
253 const char *value
= argv
[i
+ 1];
255 if (strcmp (p
, "-fi") == 0
256 || strcmp (p
, "-file") == 0)
259 error (_("Missing value for %s option."), p
);
263 else if (strcmp (p
, "-gfi") == 0
264 || strcmp (p
, "-gfile") == 0)
267 error (_("Missing value for %s option."), p
);
271 else if (strcmp (p
, "-fu") == 0
272 || strcmp (p
, "-function") == 0)
275 error (_("Missing value for %s option."), p
);
279 else if (strcmp (p
, "-rfu") == 0
280 || strcmp (p
, "-rfunction") == 0)
283 error (_("Missing value for %s option."), p
);
288 error (_("Invalid skip option: %s"), p
);
291 /* Assume the user entered "skip FUNCTION-NAME".
292 FUNCTION-NAME may be `foo (int)', and therefore we pass the
293 complete original arg to skip_function command as if the user
294 typed "skip function arg". */
295 skip_function_command (arg
, from_tty
);
299 error (_("Invalid argument: %s"), p
);
302 if (file
!= NULL
&& gfile
!= NULL
)
303 error (_("Cannot specify both -file and -gfile."));
305 if (function
!= NULL
&& rfunction
!= NULL
)
306 error (_("Cannot specify both -function and -rfunction."));
308 /* This shouldn't happen as "skip" by itself gets punted to
309 skip_function_command. */
310 gdb_assert (file
!= NULL
|| gfile
!= NULL
311 || function
!= NULL
|| rfunction
!= NULL
);
313 std::string entry_file
;
316 else if (gfile
!= NULL
)
319 std::string entry_function
;
320 if (function
!= NULL
)
321 entry_function
= function
;
322 else if (rfunction
!= NULL
)
323 entry_function
= rfunction
;
325 skiplist_entry::add_entry (gfile
!= NULL
, std::move (entry_file
),
326 rfunction
!= NULL
, std::move (entry_function
));
328 /* I18N concerns drive some of the choices here (we can't piece together
329 the output too much). OTOH we want to keep this simple. Therefore the
330 only polish we add to the output is to append "(s)" to "File" or
331 "Function" if they're a glob/regexp. */
333 const char *file_to_print
= file
!= NULL
? file
: gfile
;
334 const char *function_to_print
= function
!= NULL
? function
: rfunction
;
335 const char *file_text
= gfile
!= NULL
? _("File(s)") : _("File");
336 const char *lower_file_text
= gfile
!= NULL
? _("file(s)") : _("file");
337 const char *function_text
338 = rfunction
!= NULL
? _("Function(s)") : _("Function");
340 if (function_to_print
== NULL
)
342 printf_filtered (_("%s %s will be skipped when stepping.\n"),
343 file_text
, file_to_print
);
345 else if (file_to_print
== NULL
)
347 printf_filtered (_("%s %s will be skipped when stepping.\n"),
348 function_text
, function_to_print
);
352 printf_filtered (_("%s %s in %s %s will be skipped"
353 " when stepping.\n"),
354 function_text
, function_to_print
,
355 lower_file_text
, file_to_print
);
361 info_skip_command (const char *arg
, int from_tty
)
363 int num_printable_entries
= 0;
364 struct value_print_options opts
;
366 get_user_print_options (&opts
);
368 /* Count the number of rows in the table and see if we need space for a
369 64-bit address anywhere. */
370 for (const skiplist_entry
&e
: skiplist_entries
)
371 if (arg
== NULL
|| number_is_in_list (arg
, e
.number ()))
372 num_printable_entries
++;
374 if (num_printable_entries
== 0)
377 current_uiout
->message (_("Not skipping any files or functions.\n"));
379 current_uiout
->message (
380 _("No skiplist entries found with number %s.\n"), arg
);
385 ui_out_emit_table
table_emitter (current_uiout
, 6, num_printable_entries
,
388 current_uiout
->table_header (5, ui_left
, "number", "Num"); /* 1 */
389 current_uiout
->table_header (3, ui_left
, "enabled", "Enb"); /* 2 */
390 current_uiout
->table_header (4, ui_right
, "regexp", "Glob"); /* 3 */
391 current_uiout
->table_header (20, ui_left
, "file", "File"); /* 4 */
392 current_uiout
->table_header (2, ui_right
, "regexp", "RE"); /* 5 */
393 current_uiout
->table_header (40, ui_noalign
, "function", "Function"); /* 6 */
394 current_uiout
->table_body ();
396 for (const skiplist_entry
&e
: skiplist_entries
)
399 if (arg
!= NULL
&& !number_is_in_list (arg
, e
.number ()))
402 ui_out_emit_tuple
tuple_emitter (current_uiout
, "blklst-entry");
403 current_uiout
->field_signed ("number", e
.number ()); /* 1 */
406 current_uiout
->field_string ("enabled", "y"); /* 2 */
408 current_uiout
->field_string ("enabled", "n"); /* 2 */
410 if (e
.file_is_glob ())
411 current_uiout
->field_string ("regexp", "y"); /* 3 */
413 current_uiout
->field_string ("regexp", "n"); /* 3 */
415 current_uiout
->field_string ("file",
416 e
.file ().empty () ? "<none>"
417 : e
.file ().c_str (),
418 file_name_style
.style ()); /* 4 */
419 if (e
.function_is_regexp ())
420 current_uiout
->field_string ("regexp", "y"); /* 5 */
422 current_uiout
->field_string ("regexp", "n"); /* 5 */
424 current_uiout
->field_string ("function",
425 e
.function ().empty () ? "<none>"
426 : e
.function ().c_str (),
427 function_name_style
.style ()); /* 6 */
429 current_uiout
->text ("\n");
434 skip_enable_command (const char *arg
, int from_tty
)
438 for (skiplist_entry
&e
: skiplist_entries
)
439 if (arg
== NULL
|| number_is_in_list (arg
, e
.number ()))
446 error (_("No skiplist entries found with number %s."), arg
);
450 skip_disable_command (const char *arg
, int from_tty
)
454 for (skiplist_entry
&e
: skiplist_entries
)
455 if (arg
== NULL
|| number_is_in_list (arg
, e
.number ()))
462 error (_("No skiplist entries found with number %s."), arg
);
466 skip_delete_command (const char *arg
, int from_tty
)
470 for (auto it
= skiplist_entries
.begin (),
471 end
= skiplist_entries
.end ();
474 const skiplist_entry
&e
= *it
;
476 if (arg
== NULL
|| number_is_in_list (arg
, e
.number ()))
478 it
= skiplist_entries
.erase (it
);
486 error (_("No skiplist entries found with number %s."), arg
);
490 skiplist_entry::do_skip_file_p (const symtab_and_line
&function_sal
) const
493 fprintf_unfiltered (gdb_stdlog
,
494 "skip: checking if file %s matches non-glob %s...",
495 function_sal
.symtab
->filename
, m_file
.c_str ());
499 /* Check first sole SYMTAB->FILENAME. It may not be a substring of
500 symtab_to_fullname as it may contain "./" etc. */
501 if (compare_filenames_for_search (function_sal
.symtab
->filename
,
505 /* Before we invoke realpath, which can get expensive when many
506 files are involved, do a quick comparison of the basenames. */
507 else if (!basenames_may_differ
508 && filename_cmp (lbasename (function_sal
.symtab
->filename
),
509 lbasename (m_file
.c_str ())) != 0)
513 /* Note: symtab_to_fullname caches its result, thus we don't have to. */
514 const char *fullname
= symtab_to_fullname (function_sal
.symtab
);
516 result
= compare_filenames_for_search (fullname
, m_file
.c_str ());
520 fprintf_unfiltered (gdb_stdlog
, result
? "yes.\n" : "no.\n");
526 skiplist_entry::do_skip_gfile_p (const symtab_and_line
&function_sal
) const
529 fprintf_unfiltered (gdb_stdlog
,
530 "skip: checking if file %s matches glob %s...",
531 function_sal
.symtab
->filename
, m_file
.c_str ());
535 /* Check first sole SYMTAB->FILENAME. It may not be a substring of
536 symtab_to_fullname as it may contain "./" etc. */
537 if (gdb_filename_fnmatch (m_file
.c_str (), function_sal
.symtab
->filename
,
538 FNM_FILE_NAME
| FNM_NOESCAPE
) == 0)
541 /* Before we invoke symtab_to_fullname, which is expensive, do a quick
542 comparison of the basenames.
543 Note that we assume that lbasename works with glob-style patterns.
544 If the basename of the glob pattern is something like "*.c" then this
545 isn't much of a win. Oh well. */
546 else if (!basenames_may_differ
547 && gdb_filename_fnmatch (lbasename (m_file
.c_str ()),
548 lbasename (function_sal
.symtab
->filename
),
549 FNM_FILE_NAME
| FNM_NOESCAPE
) != 0)
553 /* Note: symtab_to_fullname caches its result, thus we don't have to. */
554 const char *fullname
= symtab_to_fullname (function_sal
.symtab
);
556 result
= compare_glob_filenames_for_search (fullname
, m_file
.c_str ());
560 fprintf_unfiltered (gdb_stdlog
, result
? "yes.\n" : "no.\n");
566 skiplist_entry::skip_file_p (const symtab_and_line
&function_sal
) const
571 if (function_sal
.symtab
== NULL
)
575 return do_skip_gfile_p (function_sal
);
577 return do_skip_file_p (function_sal
);
581 skiplist_entry::skip_function_p (const char *function_name
) const
583 if (m_function
.empty ())
588 if (m_function_is_regexp
)
591 fprintf_unfiltered (gdb_stdlog
,
592 "skip: checking if function %s matches regex %s...",
593 function_name
, m_function
.c_str ());
595 gdb_assert (m_compiled_function_regexp
);
597 = (m_compiled_function_regexp
->exec (function_name
, 0, NULL
, 0) == 0);
602 fprintf_unfiltered (gdb_stdlog
,
603 ("skip: checking if function %s matches non-regex "
605 function_name
, m_function
.c_str ());
606 result
= (strcmp_iw (function_name
, m_function
.c_str ()) == 0);
610 fprintf_unfiltered (gdb_stdlog
, result
? "yes.\n" : "no.\n");
618 function_name_is_marked_for_skip (const char *function_name
,
619 const symtab_and_line
&function_sal
)
621 if (function_name
== NULL
)
624 for (const skiplist_entry
&e
: skiplist_entries
)
629 bool skip_by_file
= e
.skip_file_p (function_sal
);
630 bool skip_by_function
= e
.skip_function_p (function_name
);
632 /* If both file and function must match, make sure we don't errantly
633 exit if only one of them match. */
634 if (!e
.file ().empty () && !e
.function ().empty ())
636 if (skip_by_file
&& skip_by_function
)
639 /* Only one of file/function is specified. */
640 else if (skip_by_file
|| skip_by_function
)
647 /* Completer for skip numbers. */
650 complete_skip_number (cmd_list_element
*cmd
,
651 completion_tracker
&completer
,
652 const char *text
, const char *word
)
654 size_t word_len
= strlen (word
);
656 for (const skiplist_entry
&entry
: skiplist_entries
)
658 gdb::unique_xmalloc_ptr
<char> name (xstrprintf ("%d", entry
.number ()));
659 if (strncmp (word
, name
.get (), word_len
) == 0)
660 completer
.add_completion (std::move (name
));
665 _initialize_step_skip (void)
667 static struct cmd_list_element
*skiplist
= NULL
;
668 struct cmd_list_element
*c
;
670 add_prefix_cmd ("skip", class_breakpoint
, skip_command
, _("\
671 Ignore a function while stepping.\n\
673 Usage: skip [FUNCTION-NAME]\n\
674 skip [FILE-SPEC] [FUNCTION-SPEC]\n\
675 If no arguments are given, ignore the current function.\n\
677 FILE-SPEC is one of:\n\
678 -fi|-file FILE-NAME\n\
679 -gfi|-gfile GLOB-FILE-PATTERN\n\
680 FUNCTION-SPEC is one of:\n\
681 -fu|-function FUNCTION-NAME\n\
682 -rfu|-rfunction FUNCTION-NAME-REGULAR-EXPRESSION"),
683 &skiplist
, "skip ", 1, &cmdlist
);
685 c
= add_cmd ("file", class_breakpoint
, skip_file_command
, _("\
686 Ignore a file while stepping.\n\
687 Usage: skip file [FILE-NAME]\n\
688 If no filename is given, ignore the current file."),
690 set_cmd_completer (c
, filename_completer
);
692 c
= add_cmd ("function", class_breakpoint
, skip_function_command
, _("\
693 Ignore a function while stepping.\n\
694 Usage: skip function [FUNCTION-NAME]\n\
695 If no function name is given, skip the current function."),
697 set_cmd_completer (c
, location_completer
);
699 c
= add_cmd ("enable", class_breakpoint
, skip_enable_command
, _("\
700 Enable skip entries.\n\
701 Usage: skip enable [NUMBER | RANGE]...\n\
702 You can specify numbers (e.g. \"skip enable 1 3\"),\n\
703 ranges (e.g. \"skip enable 4-8\"), or both (e.g. \"skip enable 1 3 4-8\").\n\n\
704 If you don't specify any numbers or ranges, we'll enable all skip entries."),
706 set_cmd_completer (c
, complete_skip_number
);
708 c
= add_cmd ("disable", class_breakpoint
, skip_disable_command
, _("\
709 Disable skip entries.\n\
710 Usage: skip disable [NUMBER | RANGE]...\n\
711 You can specify numbers (e.g. \"skip disable 1 3\"),\n\
712 ranges (e.g. \"skip disable 4-8\"), or both (e.g. \"skip disable 1 3 4-8\").\n\n\
713 If you don't specify any numbers or ranges, we'll disable all skip entries."),
715 set_cmd_completer (c
, complete_skip_number
);
717 c
= add_cmd ("delete", class_breakpoint
, skip_delete_command
, _("\
718 Delete skip entries.\n\
719 Usage: skip delete [NUMBER | RANGES]...\n\
720 You can specify numbers (e.g. \"skip delete 1 3\"),\n\
721 ranges (e.g. \"skip delete 4-8\"), or both (e.g. \"skip delete 1 3 4-8\").\n\n\
722 If you don't specify any numbers or ranges, we'll delete all skip entries."),
724 set_cmd_completer (c
, complete_skip_number
);
726 add_info ("skip", info_skip_command
, _("\
727 Display the status of skips.\n\
728 Usage: info skip [NUMBER | RANGES]...\n\
729 You can specify numbers (e.g. \"info skip 1 3\"), \n\
730 ranges (e.g. \"info skip 4-8\"), or both (e.g. \"info skip 1 3 4-8\").\n\n\
731 If you don't specify any numbers or ranges, we'll show all skips."));
732 set_cmd_completer (c
, complete_skip_number
);
734 add_setshow_boolean_cmd ("skip", class_maintenance
,
736 Set whether to print the debug output about skipping files and functions."),
738 Show whether the debug output about skipping files and functions is printed."),
740 When non-zero, debug output about skipping files and functions is displayed."),
742 &setdebuglist
, &showdebuglist
);