Automatic date update in version.in
[binutils-gdb.git] / gdb / skip.c
blobf2818eccb34cbd6c3e406a0c2398612ad3d01b0c
1 /* Skipping uninteresting files and functions while stepping.
3 Copyright (C) 2011-2024 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/>. */
18 #include "skip.h"
19 #include "value.h"
20 #include "valprint.h"
21 #include "ui-out.h"
22 #include "symtab.h"
23 #include "gdbcmd.h"
24 #include "command.h"
25 #include "completer.h"
26 #include "stack.h"
27 #include "cli/cli-utils.h"
28 #include "arch-utils.h"
29 #include "linespec.h"
30 #include "objfiles.h"
31 #include "breakpoint.h"
32 #include "source.h"
33 #include "filenames.h"
34 #include "fnmatch.h"
35 #include "gdbsupport/gdb_regex.h"
36 #include <optional>
37 #include <list>
38 #include "cli/cli-style.h"
39 #include "gdbsupport/buildargv.h"
41 /* True if we want to print debug printouts related to file/function
42 skipping. */
43 static bool debug_skip = false;
45 class skiplist_entry
47 public:
48 /* Create a skiplist_entry object and add it to the chain. */
49 static void add_entry (bool file_is_glob,
50 std::string &&file,
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;
62 /* Getters. */
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; }
70 /* Setters. */
71 void enable () { m_enabled = true; };
72 void disable () { m_enabled = false; };
74 /* Disable copy. */
75 skiplist_entry (const skiplist_entry &) = delete;
76 void operator= (const skiplist_entry &) = delete;
78 private:
79 /* Key that grants access to the constructor. */
80 struct private_key {};
81 public:
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,
87 private_key);
89 private:
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;
96 private: /* data */
97 int m_number = -1;
99 /* True if FILE is a glob-style pattern.
100 Otherwise it is the plain file name (possibly with directories). */
101 bool m_file_is_glob;
103 /* The name of the file or empty if no name. */
104 std::string m_file;
106 /* True if FUNCTION is a regexp.
107 Otherwise it is a plain function name (possibly with arguments,
108 for C++). */
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 std::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,
125 std::string &&file,
126 bool function_is_regexp,
127 std::string &&function,
128 private_key)
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 ());
136 if (m_file_is_glob)
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,
144 _("regexp"));
148 void
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,
153 std::move (file),
154 function_is_regexp,
155 std::move (function),
156 private_key {});
158 /* Incremented after push_back, in case push_back throws. */
159 skiplist_entries.back ().m_number = ++highest_skiplist_entry_num;
162 static void
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. */
170 if (arg == NULL)
172 symtab = get_last_displayed_symtab ();
173 if (symtab == NULL)
174 error (_("No default file now."));
176 /* It is not a typo, symtab_to_filename_for_display would be needlessly
177 ambiguous. */
178 filename = symtab_to_fullname (symtab);
180 else
181 filename = arg;
183 skiplist_entry::add_entry (false, std::string (filename),
184 false, std::string ());
186 gdb_printf (_("File %s will be skipped when stepping.\n"), filename);
189 /* Create a skiplist entry for the given function NAME and add it to the
190 list. */
192 static void
193 skip_function (const char *name)
195 skiplist_entry::add_entry (false, std::string (), false, std::string (name));
197 gdb_printf (_("Function %s will be skipped when stepping.\n"), name);
200 static void
201 skip_function_command (const char *arg, int from_tty)
203 /* Default to the current function if no argument is given. */
204 if (arg == NULL)
206 frame_info_ptr fi = get_selected_frame (_("No default function now."));
207 struct symbol *sym = get_frame_function (fi);
208 const char *name = NULL;
210 if (sym != NULL)
211 name = sym->print_name ();
212 else
213 error (_("No function found containing current program point %s."),
214 paddress (get_current_arch (), get_frame_pc (fi)));
215 skip_function (name);
216 return;
219 skip_function (arg);
222 /* Process "skip ..." that does not match "skip file" or "skip function". */
224 static void
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;
231 int i;
233 if (arg == NULL)
235 skip_function_command (arg, from_tty);
236 return;
239 gdb_argv argv (arg);
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)
249 if (value == NULL)
250 error (_("Missing value for %s option."), p);
251 file = value;
252 ++i;
254 else if (strcmp (p, "-gfi") == 0
255 || strcmp (p, "-gfile") == 0)
257 if (value == NULL)
258 error (_("Missing value for %s option."), p);
259 gfile = value;
260 ++i;
262 else if (strcmp (p, "-fu") == 0
263 || strcmp (p, "-function") == 0)
265 if (value == NULL)
266 error (_("Missing value for %s option."), p);
267 function = value;
268 ++i;
270 else if (strcmp (p, "-rfu") == 0
271 || strcmp (p, "-rfunction") == 0)
273 if (value == NULL)
274 error (_("Missing value for %s option."), p);
275 rfunction = value;
276 ++i;
278 else if (*p == '-')
279 error (_("Invalid skip option: %s"), p);
280 else if (i == 0)
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);
287 return;
289 else
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;
305 if (file != NULL)
306 entry_file = file;
307 else if (gfile != NULL)
308 entry_file = gfile;
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 gdb_printf (_("%s %s will be skipped when stepping.\n"),
334 file_text, file_to_print);
336 else if (file_to_print == NULL)
338 gdb_printf (_("%s %s will be skipped when stepping.\n"),
339 function_text, function_to_print);
341 else
343 gdb_printf (_("%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);
351 static void
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)
367 if (arg == NULL)
368 current_uiout->message (_("Not skipping any files or functions.\n"));
369 else
370 current_uiout->message (
371 _("No skiplist entries found with number %s.\n"), arg);
373 return;
376 ui_out_emit_table table_emitter (current_uiout, 6, num_printable_entries,
377 "SkiplistTable");
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)
389 QUIT;
390 if (arg != NULL && !number_is_in_list (arg, e.number ()))
391 continue;
393 ui_out_emit_tuple tuple_emitter (current_uiout, "blklst-entry");
394 current_uiout->field_signed ("number", e.number ()); /* 1 */
396 if (e.enabled ())
397 current_uiout->field_string ("enabled", "y"); /* 2 */
398 else
399 current_uiout->field_string ("enabled", "n"); /* 2 */
401 if (e.file_is_glob ())
402 current_uiout->field_string ("regexp", "y"); /* 3 */
403 else
404 current_uiout->field_string ("regexp", "n"); /* 3 */
406 current_uiout->field_string ("file",
407 e.file ().empty () ? "<none>"
408 : e.file ().c_str (),
409 e.file ().empty ()
410 ? metadata_style.style ()
411 : file_name_style.style ()); /* 4 */
412 if (e.function_is_regexp ())
413 current_uiout->field_string ("regexp", "y"); /* 5 */
414 else
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");
428 static void
429 skip_enable_command (const char *arg, int from_tty)
431 bool found = false;
433 for (skiplist_entry &e : skiplist_entries)
434 if (arg == NULL || number_is_in_list (arg, e.number ()))
436 e.enable ();
437 found = true;
440 if (!found)
441 error (_("No skiplist entries found with number %s."), arg);
444 static void
445 skip_disable_command (const char *arg, int from_tty)
447 bool found = false;
449 for (skiplist_entry &e : skiplist_entries)
450 if (arg == NULL || number_is_in_list (arg, e.number ()))
452 e.disable ();
453 found = true;
456 if (!found)
457 error (_("No skiplist entries found with number %s."), arg);
460 static void
461 skip_delete_command (const char *arg, int from_tty)
463 bool found = false;
465 for (auto it = skiplist_entries.begin (),
466 end = skiplist_entries.end ();
467 it != end;)
469 const skiplist_entry &e = *it;
471 if (arg == NULL || number_is_in_list (arg, e.number ()))
473 it = skiplist_entries.erase (it);
474 found = true;
476 else
477 ++it;
480 if (!found)
481 error (_("No skiplist entries found with number %s."), arg);
484 bool
485 skiplist_entry::do_skip_file_p (const symtab_and_line &function_sal) const
487 if (debug_skip)
488 gdb_printf (gdb_stdlog,
489 "skip: checking if file %s matches non-glob %s...",
490 function_sal.symtab->filename, m_file.c_str ());
492 bool result;
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,
497 m_file.c_str ()))
498 result = true;
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)
505 result = false;
506 else
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 ());
514 if (debug_skip)
515 gdb_printf (gdb_stdlog, result ? "yes.\n" : "no.\n");
517 return result;
520 bool
521 skiplist_entry::do_skip_gfile_p (const symtab_and_line &function_sal) const
523 if (debug_skip)
524 gdb_printf (gdb_stdlog,
525 "skip: checking if file %s matches glob %s...",
526 function_sal.symtab->filename, m_file.c_str ());
528 bool result;
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)
534 result = true;
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)
545 result = false;
546 else
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 ());
554 if (debug_skip)
555 gdb_printf (gdb_stdlog, result ? "yes.\n" : "no.\n");
557 return result;
560 bool
561 skiplist_entry::skip_file_p (const symtab_and_line &function_sal) const
563 if (m_file.empty ())
564 return false;
566 if (function_sal.symtab == NULL)
567 return false;
569 if (m_file_is_glob)
570 return do_skip_gfile_p (function_sal);
571 else
572 return do_skip_file_p (function_sal);
575 bool
576 skiplist_entry::skip_function_p (const char *function_name) const
578 if (m_function.empty ())
579 return false;
581 bool result;
583 if (m_function_is_regexp)
585 if (debug_skip)
586 gdb_printf (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);
591 result
592 = (m_compiled_function_regexp->exec (function_name, 0, NULL, 0) == 0);
594 else
596 if (debug_skip)
597 gdb_printf (gdb_stdlog,
598 ("skip: checking if function %s matches non-regex "
599 "%s..."),
600 function_name, m_function.c_str ());
601 result = (strcmp_iw (function_name, m_function.c_str ()) == 0);
604 if (debug_skip)
605 gdb_printf (gdb_stdlog, result ? "yes.\n" : "no.\n");
607 return result;
610 /* See skip.h. */
612 bool
613 function_name_is_marked_for_skip (const char *function_name,
614 const symtab_and_line &function_sal)
616 if (function_name == NULL)
617 return false;
619 for (const skiplist_entry &e : skiplist_entries)
621 if (!e.enabled ())
622 continue;
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)
632 return true;
634 /* Only one of file/function is specified. */
635 else if (skip_by_file || skip_by_function)
636 return true;
639 return false;
642 /* Completer for skip numbers. */
644 static void
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 ();
660 void
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, 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."),
685 &skiplist);
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."),
692 &skiplist);
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."),
701 &skiplist);
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."),
710 &skiplist);
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."),
719 &skiplist);
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,
731 &debug_skip, _("\
732 Set whether to print the debug output about skipping files and functions."),
733 _("\
734 Show whether the debug output about skipping files and functions is printed."),
735 _("\
736 When non-zero, debug output about skipping files and functions is displayed."),
737 NULL, NULL,
738 &setdebuglist, &showdebuglist);