1 /* Skipping uninteresting files and functions while stepping.
3 Copyright (C) 2011-2020 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 ());
142 m_compiled_function_regexp
.emplace (m_function
.c_str (),
143 REG_NOSUB
| REG_EXTENDED
,
149 skiplist_entry::add_entry (bool file_is_glob
, std::string
&&file
,
150 bool function_is_regexp
, std::string
&&function
)
152 skiplist_entries
.emplace_back (file_is_glob
,
155 std::move (function
),
158 /* Incremented after push_back, in case push_back throws. */
159 skiplist_entries
.back ().m_number
= ++highest_skiplist_entry_num
;
163 skip_file_command (const char *arg
, int from_tty
)
165 struct symtab
*symtab
;
166 const char *filename
= NULL
;
168 /* If no argument was given, try to default to the last
169 displayed codepoint. */
172 symtab
= get_last_displayed_symtab ();
174 error (_("No default file now."));
176 /* It is not a typo, symtab_to_filename_for_display would be needlessly
178 filename
= symtab_to_fullname (symtab
);
183 skiplist_entry::add_entry (false, std::string (filename
),
184 false, std::string ());
186 printf_filtered (_("File %s will be skipped when stepping.\n"), filename
);
189 /* Create a skiplist entry for the given function NAME and add it to the
193 skip_function (const char *name
)
195 skiplist_entry::add_entry (false, std::string (), false, std::string (name
));
197 printf_filtered (_("Function %s will be skipped when stepping.\n"), name
);
201 skip_function_command (const char *arg
, int from_tty
)
203 /* Default to the current function if no argument is given. */
206 frame_info
*fi
= get_selected_frame (_("No default function now."));
207 struct symbol
*sym
= get_frame_function (fi
);
208 const char *name
= NULL
;
211 name
= sym
->print_name ();
213 error (_("No function found containing current program point %s."),
214 paddress (get_current_arch (), get_frame_pc (fi
)));
215 skip_function (name
);
222 /* Process "skip ..." that does not match "skip file" or "skip function". */
225 skip_command (const char *arg
, int from_tty
)
227 const char *file
= NULL
;
228 const char *gfile
= NULL
;
229 const char *function
= NULL
;
230 const char *rfunction
= NULL
;
235 skip_function_command (arg
, from_tty
);
241 for (i
= 0; argv
[i
] != NULL
; ++i
)
243 const char *p
= argv
[i
];
244 const char *value
= argv
[i
+ 1];
246 if (strcmp (p
, "-fi") == 0
247 || strcmp (p
, "-file") == 0)
250 error (_("Missing value for %s option."), p
);
254 else if (strcmp (p
, "-gfi") == 0
255 || strcmp (p
, "-gfile") == 0)
258 error (_("Missing value for %s option."), p
);
262 else if (strcmp (p
, "-fu") == 0
263 || strcmp (p
, "-function") == 0)
266 error (_("Missing value for %s option."), p
);
270 else if (strcmp (p
, "-rfu") == 0
271 || strcmp (p
, "-rfunction") == 0)
274 error (_("Missing value for %s option."), p
);
279 error (_("Invalid skip option: %s"), p
);
282 /* Assume the user entered "skip FUNCTION-NAME".
283 FUNCTION-NAME may be `foo (int)', and therefore we pass the
284 complete original arg to skip_function command as if the user
285 typed "skip function arg". */
286 skip_function_command (arg
, from_tty
);
290 error (_("Invalid argument: %s"), p
);
293 if (file
!= NULL
&& gfile
!= NULL
)
294 error (_("Cannot specify both -file and -gfile."));
296 if (function
!= NULL
&& rfunction
!= NULL
)
297 error (_("Cannot specify both -function and -rfunction."));
299 /* This shouldn't happen as "skip" by itself gets punted to
300 skip_function_command. */
301 gdb_assert (file
!= NULL
|| gfile
!= NULL
302 || function
!= NULL
|| rfunction
!= NULL
);
304 std::string entry_file
;
307 else if (gfile
!= NULL
)
310 std::string entry_function
;
311 if (function
!= NULL
)
312 entry_function
= function
;
313 else if (rfunction
!= NULL
)
314 entry_function
= rfunction
;
316 skiplist_entry::add_entry (gfile
!= NULL
, std::move (entry_file
),
317 rfunction
!= NULL
, std::move (entry_function
));
319 /* I18N concerns drive some of the choices here (we can't piece together
320 the output too much). OTOH we want to keep this simple. Therefore the
321 only polish we add to the output is to append "(s)" to "File" or
322 "Function" if they're a glob/regexp. */
324 const char *file_to_print
= file
!= NULL
? file
: gfile
;
325 const char *function_to_print
= function
!= NULL
? function
: rfunction
;
326 const char *file_text
= gfile
!= NULL
? _("File(s)") : _("File");
327 const char *lower_file_text
= gfile
!= NULL
? _("file(s)") : _("file");
328 const char *function_text
329 = rfunction
!= NULL
? _("Function(s)") : _("Function");
331 if (function_to_print
== NULL
)
333 printf_filtered (_("%s %s will be skipped when stepping.\n"),
334 file_text
, file_to_print
);
336 else if (file_to_print
== NULL
)
338 printf_filtered (_("%s %s will be skipped when stepping.\n"),
339 function_text
, function_to_print
);
343 printf_filtered (_("%s %s in %s %s will be skipped"
344 " when stepping.\n"),
345 function_text
, function_to_print
,
346 lower_file_text
, file_to_print
);
352 info_skip_command (const char *arg
, int from_tty
)
354 int num_printable_entries
= 0;
355 struct value_print_options opts
;
357 get_user_print_options (&opts
);
359 /* Count the number of rows in the table and see if we need space for a
360 64-bit address anywhere. */
361 for (const skiplist_entry
&e
: skiplist_entries
)
362 if (arg
== NULL
|| number_is_in_list (arg
, e
.number ()))
363 num_printable_entries
++;
365 if (num_printable_entries
== 0)
368 current_uiout
->message (_("Not skipping any files or functions.\n"));
370 current_uiout
->message (
371 _("No skiplist entries found with number %s.\n"), arg
);
376 ui_out_emit_table
table_emitter (current_uiout
, 6, num_printable_entries
,
379 current_uiout
->table_header (5, ui_left
, "number", "Num"); /* 1 */
380 current_uiout
->table_header (3, ui_left
, "enabled", "Enb"); /* 2 */
381 current_uiout
->table_header (4, ui_right
, "regexp", "Glob"); /* 3 */
382 current_uiout
->table_header (20, ui_left
, "file", "File"); /* 4 */
383 current_uiout
->table_header (2, ui_right
, "regexp", "RE"); /* 5 */
384 current_uiout
->table_header (40, ui_noalign
, "function", "Function"); /* 6 */
385 current_uiout
->table_body ();
387 for (const skiplist_entry
&e
: skiplist_entries
)
390 if (arg
!= NULL
&& !number_is_in_list (arg
, e
.number ()))
393 ui_out_emit_tuple
tuple_emitter (current_uiout
, "blklst-entry");
394 current_uiout
->field_signed ("number", e
.number ()); /* 1 */
397 current_uiout
->field_string ("enabled", "y"); /* 2 */
399 current_uiout
->field_string ("enabled", "n"); /* 2 */
401 if (e
.file_is_glob ())
402 current_uiout
->field_string ("regexp", "y"); /* 3 */
404 current_uiout
->field_string ("regexp", "n"); /* 3 */
406 current_uiout
->field_string ("file",
407 e
.file ().empty () ? "<none>"
408 : e
.file ().c_str (),
410 ? metadata_style
.style ()
411 : file_name_style
.style ()); /* 4 */
412 if (e
.function_is_regexp ())
413 current_uiout
->field_string ("regexp", "y"); /* 5 */
415 current_uiout
->field_string ("regexp", "n"); /* 5 */
417 current_uiout
->field_string ("function",
418 e
.function ().empty () ? "<none>"
419 : e
.function ().c_str (),
420 e
.function ().empty ()
421 ? metadata_style
.style ()
422 : function_name_style
.style ()); /* 6 */
424 current_uiout
->text ("\n");
429 skip_enable_command (const char *arg
, int from_tty
)
433 for (skiplist_entry
&e
: skiplist_entries
)
434 if (arg
== NULL
|| number_is_in_list (arg
, e
.number ()))
441 error (_("No skiplist entries found with number %s."), arg
);
445 skip_disable_command (const char *arg
, int from_tty
)
449 for (skiplist_entry
&e
: skiplist_entries
)
450 if (arg
== NULL
|| number_is_in_list (arg
, e
.number ()))
457 error (_("No skiplist entries found with number %s."), arg
);
461 skip_delete_command (const char *arg
, int from_tty
)
465 for (auto it
= skiplist_entries
.begin (),
466 end
= skiplist_entries
.end ();
469 const skiplist_entry
&e
= *it
;
471 if (arg
== NULL
|| number_is_in_list (arg
, e
.number ()))
473 it
= skiplist_entries
.erase (it
);
481 error (_("No skiplist entries found with number %s."), arg
);
485 skiplist_entry::do_skip_file_p (const symtab_and_line
&function_sal
) const
488 fprintf_unfiltered (gdb_stdlog
,
489 "skip: checking if file %s matches non-glob %s...",
490 function_sal
.symtab
->filename
, m_file
.c_str ());
494 /* Check first sole SYMTAB->FILENAME. It may not be a substring of
495 symtab_to_fullname as it may contain "./" etc. */
496 if (compare_filenames_for_search (function_sal
.symtab
->filename
,
500 /* Before we invoke realpath, which can get expensive when many
501 files are involved, do a quick comparison of the basenames. */
502 else if (!basenames_may_differ
503 && filename_cmp (lbasename (function_sal
.symtab
->filename
),
504 lbasename (m_file
.c_str ())) != 0)
508 /* Note: symtab_to_fullname caches its result, thus we don't have to. */
509 const char *fullname
= symtab_to_fullname (function_sal
.symtab
);
511 result
= compare_filenames_for_search (fullname
, m_file
.c_str ());
515 fprintf_unfiltered (gdb_stdlog
, result
? "yes.\n" : "no.\n");
521 skiplist_entry::do_skip_gfile_p (const symtab_and_line
&function_sal
) const
524 fprintf_unfiltered (gdb_stdlog
,
525 "skip: checking if file %s matches glob %s...",
526 function_sal
.symtab
->filename
, m_file
.c_str ());
530 /* Check first sole SYMTAB->FILENAME. It may not be a substring of
531 symtab_to_fullname as it may contain "./" etc. */
532 if (gdb_filename_fnmatch (m_file
.c_str (), function_sal
.symtab
->filename
,
533 FNM_FILE_NAME
| FNM_NOESCAPE
) == 0)
536 /* Before we invoke symtab_to_fullname, which is expensive, do a quick
537 comparison of the basenames.
538 Note that we assume that lbasename works with glob-style patterns.
539 If the basename of the glob pattern is something like "*.c" then this
540 isn't much of a win. Oh well. */
541 else if (!basenames_may_differ
542 && gdb_filename_fnmatch (lbasename (m_file
.c_str ()),
543 lbasename (function_sal
.symtab
->filename
),
544 FNM_FILE_NAME
| FNM_NOESCAPE
) != 0)
548 /* Note: symtab_to_fullname caches its result, thus we don't have to. */
549 const char *fullname
= symtab_to_fullname (function_sal
.symtab
);
551 result
= compare_glob_filenames_for_search (fullname
, m_file
.c_str ());
555 fprintf_unfiltered (gdb_stdlog
, result
? "yes.\n" : "no.\n");
561 skiplist_entry::skip_file_p (const symtab_and_line
&function_sal
) const
566 if (function_sal
.symtab
== NULL
)
570 return do_skip_gfile_p (function_sal
);
572 return do_skip_file_p (function_sal
);
576 skiplist_entry::skip_function_p (const char *function_name
) const
578 if (m_function
.empty ())
583 if (m_function_is_regexp
)
586 fprintf_unfiltered (gdb_stdlog
,
587 "skip: checking if function %s matches regex %s...",
588 function_name
, m_function
.c_str ());
590 gdb_assert (m_compiled_function_regexp
);
592 = (m_compiled_function_regexp
->exec (function_name
, 0, NULL
, 0) == 0);
597 fprintf_unfiltered (gdb_stdlog
,
598 ("skip: checking if function %s matches non-regex "
600 function_name
, m_function
.c_str ());
601 result
= (strcmp_iw (function_name
, m_function
.c_str ()) == 0);
605 fprintf_unfiltered (gdb_stdlog
, result
? "yes.\n" : "no.\n");
613 function_name_is_marked_for_skip (const char *function_name
,
614 const symtab_and_line
&function_sal
)
616 if (function_name
== NULL
)
619 for (const skiplist_entry
&e
: skiplist_entries
)
624 bool skip_by_file
= e
.skip_file_p (function_sal
);
625 bool skip_by_function
= e
.skip_function_p (function_name
);
627 /* If both file and function must match, make sure we don't errantly
628 exit if only one of them match. */
629 if (!e
.file ().empty () && !e
.function ().empty ())
631 if (skip_by_file
&& skip_by_function
)
634 /* Only one of file/function is specified. */
635 else if (skip_by_file
|| skip_by_function
)
642 /* Completer for skip numbers. */
645 complete_skip_number (cmd_list_element
*cmd
,
646 completion_tracker
&completer
,
647 const char *text
, const char *word
)
649 size_t word_len
= strlen (word
);
651 for (const skiplist_entry
&entry
: skiplist_entries
)
653 gdb::unique_xmalloc_ptr
<char> name (xstrprintf ("%d", entry
.number ()));
654 if (strncmp (word
, name
.get (), word_len
) == 0)
655 completer
.add_completion (std::move (name
));
659 void _initialize_step_skip ();
661 _initialize_step_skip ()
663 static struct cmd_list_element
*skiplist
= NULL
;
664 struct cmd_list_element
*c
;
666 add_prefix_cmd ("skip", class_breakpoint
, skip_command
, _("\
667 Ignore a function while stepping.\n\
669 Usage: skip [FUNCTION-NAME]\n\
670 skip [FILE-SPEC] [FUNCTION-SPEC]\n\
671 If no arguments are given, ignore the current function.\n\
673 FILE-SPEC is one of:\n\
674 -fi|-file FILE-NAME\n\
675 -gfi|-gfile GLOB-FILE-PATTERN\n\
676 FUNCTION-SPEC is one of:\n\
677 -fu|-function FUNCTION-NAME\n\
678 -rfu|-rfunction FUNCTION-NAME-REGULAR-EXPRESSION"),
679 &skiplist
, "skip ", 1, &cmdlist
);
681 c
= add_cmd ("file", class_breakpoint
, skip_file_command
, _("\
682 Ignore a file while stepping.\n\
683 Usage: skip file [FILE-NAME]\n\
684 If no filename is given, ignore the current file."),
686 set_cmd_completer (c
, filename_completer
);
688 c
= add_cmd ("function", class_breakpoint
, skip_function_command
, _("\
689 Ignore a function while stepping.\n\
690 Usage: skip function [FUNCTION-NAME]\n\
691 If no function name is given, skip the current function."),
693 set_cmd_completer (c
, location_completer
);
695 c
= add_cmd ("enable", class_breakpoint
, skip_enable_command
, _("\
696 Enable skip entries.\n\
697 Usage: skip enable [NUMBER | RANGE]...\n\
698 You can specify numbers (e.g. \"skip enable 1 3\"),\n\
699 ranges (e.g. \"skip enable 4-8\"), or both (e.g. \"skip enable 1 3 4-8\").\n\n\
700 If you don't specify any numbers or ranges, we'll enable all skip entries."),
702 set_cmd_completer (c
, complete_skip_number
);
704 c
= add_cmd ("disable", class_breakpoint
, skip_disable_command
, _("\
705 Disable skip entries.\n\
706 Usage: skip disable [NUMBER | RANGE]...\n\
707 You can specify numbers (e.g. \"skip disable 1 3\"),\n\
708 ranges (e.g. \"skip disable 4-8\"), or both (e.g. \"skip disable 1 3 4-8\").\n\n\
709 If you don't specify any numbers or ranges, we'll disable all skip entries."),
711 set_cmd_completer (c
, complete_skip_number
);
713 c
= add_cmd ("delete", class_breakpoint
, skip_delete_command
, _("\
714 Delete skip entries.\n\
715 Usage: skip delete [NUMBER | RANGES]...\n\
716 You can specify numbers (e.g. \"skip delete 1 3\"),\n\
717 ranges (e.g. \"skip delete 4-8\"), or both (e.g. \"skip delete 1 3 4-8\").\n\n\
718 If you don't specify any numbers or ranges, we'll delete all skip entries."),
720 set_cmd_completer (c
, complete_skip_number
);
722 add_info ("skip", info_skip_command
, _("\
723 Display the status of skips.\n\
724 Usage: info skip [NUMBER | RANGES]...\n\
725 You can specify numbers (e.g. \"info skip 1 3\"), \n\
726 ranges (e.g. \"info skip 4-8\"), or both (e.g. \"info skip 1 3 4-8\").\n\n\
727 If you don't specify any numbers or ranges, we'll show all skips."));
728 set_cmd_completer (c
, complete_skip_number
);
730 add_setshow_boolean_cmd ("skip", class_maintenance
,
732 Set whether to print the debug output about skipping files and functions."),
734 Show whether the debug output about skipping files and functions is printed."),
736 When non-zero, debug output about skipping files and functions is displayed."),
738 &setdebuglist
, &showdebuglist
);