gdb: Remove deprecated_set_gdbarch_data
[deliverable/binutils-gdb.git] / gdb / skip.c
... / ...
CommitLineData
1/* Skipping uninteresting files and functions while stepping.
2
3 Copyright (C) 2011-2020 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#include "gdbsupport/gdb_optional.h"
38#include <list>
39#include "cli/cli-style.h"
40
41/* True if we want to print debug printouts related to file/function
42 skipping. */
43static bool debug_skip = false;
44
45class skiplist_entry
46{
47public:
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);
53
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;
57
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;
61
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; }
69
70 /* Setters. */
71 void enable () { m_enabled = true; };
72 void disable () { m_enabled = false; };
73
74 /* Disable copy. */
75 skiplist_entry (const skiplist_entry &) = delete;
76 void operator= (const skiplist_entry &) = delete;
77
78private:
79 /* Key that grants access to the constructor. */
80 struct private_key {};
81public:
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);
88
89private:
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;
92
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;
95
96private: /* data */
97 int m_number = -1;
98
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;
102
103 /* The name of the file or empty if no name. */
104 std::string m_file;
105
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;
110
111 /* The name of the function or empty if no name. */
112 std::string m_function;
113
114 /* If this is a function regexp, the compiled form. */
115 gdb::optional<compiled_regex> m_compiled_function_regexp;
116
117 /* Enabled/disabled state. */
118 bool m_enabled = true;
119};
120
121static std::list<skiplist_entry> skiplist_entries;
122static int highest_skiplist_entry_num = 0;
123
124skiplist_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))
133{
134 gdb_assert (!m_file.empty () || !m_function.empty ());
135
136 if (m_file_is_glob)
137 gdb_assert (!m_file.empty ());
138
139 if (m_function_is_regexp)
140 {
141 gdb_assert (!m_function.empty ());
142
143 int flags = REG_NOSUB;
144#ifdef REG_EXTENDED
145 flags |= REG_EXTENDED;
146#endif
147
148 gdb_assert (!m_function.empty ());
149 m_compiled_function_regexp.emplace (m_function.c_str (), flags,
150 _("regexp"));
151 }
152}
153
154void
155skiplist_entry::add_entry (bool file_is_glob, std::string &&file,
156 bool function_is_regexp, std::string &&function)
157{
158 skiplist_entries.emplace_back (file_is_glob,
159 std::move (file),
160 function_is_regexp,
161 std::move (function),
162 private_key {});
163
164 /* Incremented after push_back, in case push_back throws. */
165 skiplist_entries.back ().m_number = ++highest_skiplist_entry_num;
166}
167
168static void
169skip_file_command (const char *arg, int from_tty)
170{
171 struct symtab *symtab;
172 const char *filename = NULL;
173
174 /* If no argument was given, try to default to the last
175 displayed codepoint. */
176 if (arg == NULL)
177 {
178 symtab = get_last_displayed_symtab ();
179 if (symtab == NULL)
180 error (_("No default file now."));
181
182 /* It is not a typo, symtab_to_filename_for_display would be needlessly
183 ambiguous. */
184 filename = symtab_to_fullname (symtab);
185 }
186 else
187 filename = arg;
188
189 skiplist_entry::add_entry (false, std::string (filename),
190 false, std::string ());
191
192 printf_filtered (_("File %s will be skipped when stepping.\n"), filename);
193}
194
195/* Create a skiplist entry for the given function NAME and add it to the
196 list. */
197
198static void
199skip_function (const char *name)
200{
201 skiplist_entry::add_entry (false, std::string (), false, std::string (name));
202
203 printf_filtered (_("Function %s will be skipped when stepping.\n"), name);
204}
205
206static void
207skip_function_command (const char *arg, int from_tty)
208{
209 /* Default to the current function if no argument is given. */
210 if (arg == NULL)
211 {
212 frame_info *fi = get_selected_frame (_("No default function now."));
213 struct symbol *sym = get_frame_function (fi);
214 const char *name = NULL;
215
216 if (sym != NULL)
217 name = sym->print_name ();
218 else
219 error (_("No function found containing current program point %s."),
220 paddress (get_current_arch (), get_frame_pc (fi)));
221 skip_function (name);
222 return;
223 }
224
225 skip_function (arg);
226}
227
228/* Process "skip ..." that does not match "skip file" or "skip function". */
229
230static void
231skip_command (const char *arg, int from_tty)
232{
233 const char *file = NULL;
234 const char *gfile = NULL;
235 const char *function = NULL;
236 const char *rfunction = NULL;
237 int i;
238
239 if (arg == NULL)
240 {
241 skip_function_command (arg, from_tty);
242 return;
243 }
244
245 gdb_argv argv (arg);
246
247 for (i = 0; argv[i] != NULL; ++i)
248 {
249 const char *p = argv[i];
250 const char *value = argv[i + 1];
251
252 if (strcmp (p, "-fi") == 0
253 || strcmp (p, "-file") == 0)
254 {
255 if (value == NULL)
256 error (_("Missing value for %s option."), p);
257 file = value;
258 ++i;
259 }
260 else if (strcmp (p, "-gfi") == 0
261 || strcmp (p, "-gfile") == 0)
262 {
263 if (value == NULL)
264 error (_("Missing value for %s option."), p);
265 gfile = value;
266 ++i;
267 }
268 else if (strcmp (p, "-fu") == 0
269 || strcmp (p, "-function") == 0)
270 {
271 if (value == NULL)
272 error (_("Missing value for %s option."), p);
273 function = value;
274 ++i;
275 }
276 else if (strcmp (p, "-rfu") == 0
277 || strcmp (p, "-rfunction") == 0)
278 {
279 if (value == NULL)
280 error (_("Missing value for %s option."), p);
281 rfunction = value;
282 ++i;
283 }
284 else if (*p == '-')
285 error (_("Invalid skip option: %s"), p);
286 else if (i == 0)
287 {
288 /* Assume the user entered "skip FUNCTION-NAME".
289 FUNCTION-NAME may be `foo (int)', and therefore we pass the
290 complete original arg to skip_function command as if the user
291 typed "skip function arg". */
292 skip_function_command (arg, from_tty);
293 return;
294 }
295 else
296 error (_("Invalid argument: %s"), p);
297 }
298
299 if (file != NULL && gfile != NULL)
300 error (_("Cannot specify both -file and -gfile."));
301
302 if (function != NULL && rfunction != NULL)
303 error (_("Cannot specify both -function and -rfunction."));
304
305 /* This shouldn't happen as "skip" by itself gets punted to
306 skip_function_command. */
307 gdb_assert (file != NULL || gfile != NULL
308 || function != NULL || rfunction != NULL);
309
310 std::string entry_file;
311 if (file != NULL)
312 entry_file = file;
313 else if (gfile != NULL)
314 entry_file = gfile;
315
316 std::string entry_function;
317 if (function != NULL)
318 entry_function = function;
319 else if (rfunction != NULL)
320 entry_function = rfunction;
321
322 skiplist_entry::add_entry (gfile != NULL, std::move (entry_file),
323 rfunction != NULL, std::move (entry_function));
324
325 /* I18N concerns drive some of the choices here (we can't piece together
326 the output too much). OTOH we want to keep this simple. Therefore the
327 only polish we add to the output is to append "(s)" to "File" or
328 "Function" if they're a glob/regexp. */
329 {
330 const char *file_to_print = file != NULL ? file : gfile;
331 const char *function_to_print = function != NULL ? function : rfunction;
332 const char *file_text = gfile != NULL ? _("File(s)") : _("File");
333 const char *lower_file_text = gfile != NULL ? _("file(s)") : _("file");
334 const char *function_text
335 = rfunction != NULL ? _("Function(s)") : _("Function");
336
337 if (function_to_print == NULL)
338 {
339 printf_filtered (_("%s %s will be skipped when stepping.\n"),
340 file_text, file_to_print);
341 }
342 else if (file_to_print == NULL)
343 {
344 printf_filtered (_("%s %s will be skipped when stepping.\n"),
345 function_text, function_to_print);
346 }
347 else
348 {
349 printf_filtered (_("%s %s in %s %s will be skipped"
350 " when stepping.\n"),
351 function_text, function_to_print,
352 lower_file_text, file_to_print);
353 }
354 }
355}
356
357static void
358info_skip_command (const char *arg, int from_tty)
359{
360 int num_printable_entries = 0;
361 struct value_print_options opts;
362
363 get_user_print_options (&opts);
364
365 /* Count the number of rows in the table and see if we need space for a
366 64-bit address anywhere. */
367 for (const skiplist_entry &e : skiplist_entries)
368 if (arg == NULL || number_is_in_list (arg, e.number ()))
369 num_printable_entries++;
370
371 if (num_printable_entries == 0)
372 {
373 if (arg == NULL)
374 current_uiout->message (_("Not skipping any files or functions.\n"));
375 else
376 current_uiout->message (
377 _("No skiplist entries found with number %s.\n"), arg);
378
379 return;
380 }
381
382 ui_out_emit_table table_emitter (current_uiout, 6, num_printable_entries,
383 "SkiplistTable");
384
385 current_uiout->table_header (5, ui_left, "number", "Num"); /* 1 */
386 current_uiout->table_header (3, ui_left, "enabled", "Enb"); /* 2 */
387 current_uiout->table_header (4, ui_right, "regexp", "Glob"); /* 3 */
388 current_uiout->table_header (20, ui_left, "file", "File"); /* 4 */
389 current_uiout->table_header (2, ui_right, "regexp", "RE"); /* 5 */
390 current_uiout->table_header (40, ui_noalign, "function", "Function"); /* 6 */
391 current_uiout->table_body ();
392
393 for (const skiplist_entry &e : skiplist_entries)
394 {
395 QUIT;
396 if (arg != NULL && !number_is_in_list (arg, e.number ()))
397 continue;
398
399 ui_out_emit_tuple tuple_emitter (current_uiout, "blklst-entry");
400 current_uiout->field_signed ("number", e.number ()); /* 1 */
401
402 if (e.enabled ())
403 current_uiout->field_string ("enabled", "y"); /* 2 */
404 else
405 current_uiout->field_string ("enabled", "n"); /* 2 */
406
407 if (e.file_is_glob ())
408 current_uiout->field_string ("regexp", "y"); /* 3 */
409 else
410 current_uiout->field_string ("regexp", "n"); /* 3 */
411
412 current_uiout->field_string ("file",
413 e.file ().empty () ? "<none>"
414 : e.file ().c_str (),
415 e.file ().empty ()
416 ? metadata_style.style ()
417 : file_name_style.style ()); /* 4 */
418 if (e.function_is_regexp ())
419 current_uiout->field_string ("regexp", "y"); /* 5 */
420 else
421 current_uiout->field_string ("regexp", "n"); /* 5 */
422
423 current_uiout->field_string ("function",
424 e.function ().empty () ? "<none>"
425 : e.function ().c_str (),
426 e.function ().empty ()
427 ? metadata_style.style ()
428 : function_name_style.style ()); /* 6 */
429
430 current_uiout->text ("\n");
431 }
432}
433
434static void
435skip_enable_command (const char *arg, int from_tty)
436{
437 bool found = false;
438
439 for (skiplist_entry &e : skiplist_entries)
440 if (arg == NULL || number_is_in_list (arg, e.number ()))
441 {
442 e.enable ();
443 found = true;
444 }
445
446 if (!found)
447 error (_("No skiplist entries found with number %s."), arg);
448}
449
450static void
451skip_disable_command (const char *arg, int from_tty)
452{
453 bool found = false;
454
455 for (skiplist_entry &e : skiplist_entries)
456 if (arg == NULL || number_is_in_list (arg, e.number ()))
457 {
458 e.disable ();
459 found = true;
460 }
461
462 if (!found)
463 error (_("No skiplist entries found with number %s."), arg);
464}
465
466static void
467skip_delete_command (const char *arg, int from_tty)
468{
469 bool found = false;
470
471 for (auto it = skiplist_entries.begin (),
472 end = skiplist_entries.end ();
473 it != end;)
474 {
475 const skiplist_entry &e = *it;
476
477 if (arg == NULL || number_is_in_list (arg, e.number ()))
478 {
479 it = skiplist_entries.erase (it);
480 found = true;
481 }
482 else
483 ++it;
484 }
485
486 if (!found)
487 error (_("No skiplist entries found with number %s."), arg);
488}
489
490bool
491skiplist_entry::do_skip_file_p (const symtab_and_line &function_sal) const
492{
493 if (debug_skip)
494 fprintf_unfiltered (gdb_stdlog,
495 "skip: checking if file %s matches non-glob %s...",
496 function_sal.symtab->filename, m_file.c_str ());
497
498 bool result;
499
500 /* Check first sole SYMTAB->FILENAME. It may not be a substring of
501 symtab_to_fullname as it may contain "./" etc. */
502 if (compare_filenames_for_search (function_sal.symtab->filename,
503 m_file.c_str ()))
504 result = true;
505
506 /* Before we invoke realpath, which can get expensive when many
507 files are involved, do a quick comparison of the basenames. */
508 else if (!basenames_may_differ
509 && filename_cmp (lbasename (function_sal.symtab->filename),
510 lbasename (m_file.c_str ())) != 0)
511 result = false;
512 else
513 {
514 /* Note: symtab_to_fullname caches its result, thus we don't have to. */
515 const char *fullname = symtab_to_fullname (function_sal.symtab);
516
517 result = compare_filenames_for_search (fullname, m_file.c_str ());
518 }
519
520 if (debug_skip)
521 fprintf_unfiltered (gdb_stdlog, result ? "yes.\n" : "no.\n");
522
523 return result;
524}
525
526bool
527skiplist_entry::do_skip_gfile_p (const symtab_and_line &function_sal) const
528{
529 if (debug_skip)
530 fprintf_unfiltered (gdb_stdlog,
531 "skip: checking if file %s matches glob %s...",
532 function_sal.symtab->filename, m_file.c_str ());
533
534 bool result;
535
536 /* Check first sole SYMTAB->FILENAME. It may not be a substring of
537 symtab_to_fullname as it may contain "./" etc. */
538 if (gdb_filename_fnmatch (m_file.c_str (), function_sal.symtab->filename,
539 FNM_FILE_NAME | FNM_NOESCAPE) == 0)
540 result = true;
541
542 /* Before we invoke symtab_to_fullname, which is expensive, do a quick
543 comparison of the basenames.
544 Note that we assume that lbasename works with glob-style patterns.
545 If the basename of the glob pattern is something like "*.c" then this
546 isn't much of a win. Oh well. */
547 else if (!basenames_may_differ
548 && gdb_filename_fnmatch (lbasename (m_file.c_str ()),
549 lbasename (function_sal.symtab->filename),
550 FNM_FILE_NAME | FNM_NOESCAPE) != 0)
551 result = false;
552 else
553 {
554 /* Note: symtab_to_fullname caches its result, thus we don't have to. */
555 const char *fullname = symtab_to_fullname (function_sal.symtab);
556
557 result = compare_glob_filenames_for_search (fullname, m_file.c_str ());
558 }
559
560 if (debug_skip)
561 fprintf_unfiltered (gdb_stdlog, result ? "yes.\n" : "no.\n");
562
563 return result;
564}
565
566bool
567skiplist_entry::skip_file_p (const symtab_and_line &function_sal) const
568{
569 if (m_file.empty ())
570 return false;
571
572 if (function_sal.symtab == NULL)
573 return false;
574
575 if (m_file_is_glob)
576 return do_skip_gfile_p (function_sal);
577 else
578 return do_skip_file_p (function_sal);
579}
580
581bool
582skiplist_entry::skip_function_p (const char *function_name) const
583{
584 if (m_function.empty ())
585 return false;
586
587 bool result;
588
589 if (m_function_is_regexp)
590 {
591 if (debug_skip)
592 fprintf_unfiltered (gdb_stdlog,
593 "skip: checking if function %s matches regex %s...",
594 function_name, m_function.c_str ());
595
596 gdb_assert (m_compiled_function_regexp);
597 result
598 = (m_compiled_function_regexp->exec (function_name, 0, NULL, 0) == 0);
599 }
600 else
601 {
602 if (debug_skip)
603 fprintf_unfiltered (gdb_stdlog,
604 ("skip: checking if function %s matches non-regex "
605 "%s..."),
606 function_name, m_function.c_str ());
607 result = (strcmp_iw (function_name, m_function.c_str ()) == 0);
608 }
609
610 if (debug_skip)
611 fprintf_unfiltered (gdb_stdlog, result ? "yes.\n" : "no.\n");
612
613 return result;
614}
615
616/* See skip.h. */
617
618bool
619function_name_is_marked_for_skip (const char *function_name,
620 const symtab_and_line &function_sal)
621{
622 if (function_name == NULL)
623 return false;
624
625 for (const skiplist_entry &e : skiplist_entries)
626 {
627 if (!e.enabled ())
628 continue;
629
630 bool skip_by_file = e.skip_file_p (function_sal);
631 bool skip_by_function = e.skip_function_p (function_name);
632
633 /* If both file and function must match, make sure we don't errantly
634 exit if only one of them match. */
635 if (!e.file ().empty () && !e.function ().empty ())
636 {
637 if (skip_by_file && skip_by_function)
638 return true;
639 }
640 /* Only one of file/function is specified. */
641 else if (skip_by_file || skip_by_function)
642 return true;
643 }
644
645 return false;
646}
647
648/* Completer for skip numbers. */
649
650static void
651complete_skip_number (cmd_list_element *cmd,
652 completion_tracker &completer,
653 const char *text, const char *word)
654{
655 size_t word_len = strlen (word);
656
657 for (const skiplist_entry &entry : skiplist_entries)
658 {
659 gdb::unique_xmalloc_ptr<char> name (xstrprintf ("%d", entry.number ()));
660 if (strncmp (word, name.get (), word_len) == 0)
661 completer.add_completion (std::move (name));
662 }
663}
664
665void _initialize_step_skip ();
666void
667_initialize_step_skip ()
668{
669 static struct cmd_list_element *skiplist = NULL;
670 struct cmd_list_element *c;
671
672 add_prefix_cmd ("skip", class_breakpoint, skip_command, _("\
673Ignore a function while stepping.\n\
674\n\
675Usage: skip [FUNCTION-NAME]\n\
676 skip [FILE-SPEC] [FUNCTION-SPEC]\n\
677If no arguments are given, ignore the current function.\n\
678\n\
679FILE-SPEC is one of:\n\
680 -fi|-file FILE-NAME\n\
681 -gfi|-gfile GLOB-FILE-PATTERN\n\
682FUNCTION-SPEC is one of:\n\
683 -fu|-function FUNCTION-NAME\n\
684 -rfu|-rfunction FUNCTION-NAME-REGULAR-EXPRESSION"),
685 &skiplist, "skip ", 1, &cmdlist);
686
687 c = add_cmd ("file", class_breakpoint, skip_file_command, _("\
688Ignore a file while stepping.\n\
689Usage: skip file [FILE-NAME]\n\
690If no filename is given, ignore the current file."),
691 &skiplist);
692 set_cmd_completer (c, filename_completer);
693
694 c = add_cmd ("function", class_breakpoint, skip_function_command, _("\
695Ignore a function while stepping.\n\
696Usage: skip function [FUNCTION-NAME]\n\
697If no function name is given, skip the current function."),
698 &skiplist);
699 set_cmd_completer (c, location_completer);
700
701 c = add_cmd ("enable", class_breakpoint, skip_enable_command, _("\
702Enable skip entries.\n\
703Usage: skip enable [NUMBER | RANGE]...\n\
704You can specify numbers (e.g. \"skip enable 1 3\"),\n\
705ranges (e.g. \"skip enable 4-8\"), or both (e.g. \"skip enable 1 3 4-8\").\n\n\
706If you don't specify any numbers or ranges, we'll enable all skip entries."),
707 &skiplist);
708 set_cmd_completer (c, complete_skip_number);
709
710 c = add_cmd ("disable", class_breakpoint, skip_disable_command, _("\
711Disable skip entries.\n\
712Usage: skip disable [NUMBER | RANGE]...\n\
713You can specify numbers (e.g. \"skip disable 1 3\"),\n\
714ranges (e.g. \"skip disable 4-8\"), or both (e.g. \"skip disable 1 3 4-8\").\n\n\
715If you don't specify any numbers or ranges, we'll disable all skip entries."),
716 &skiplist);
717 set_cmd_completer (c, complete_skip_number);
718
719 c = add_cmd ("delete", class_breakpoint, skip_delete_command, _("\
720Delete skip entries.\n\
721Usage: skip delete [NUMBER | RANGES]...\n\
722You can specify numbers (e.g. \"skip delete 1 3\"),\n\
723ranges (e.g. \"skip delete 4-8\"), or both (e.g. \"skip delete 1 3 4-8\").\n\n\
724If you don't specify any numbers or ranges, we'll delete all skip entries."),
725 &skiplist);
726 set_cmd_completer (c, complete_skip_number);
727
728 add_info ("skip", info_skip_command, _("\
729Display the status of skips.\n\
730Usage: info skip [NUMBER | RANGES]...\n\
731You can specify numbers (e.g. \"info skip 1 3\"), \n\
732ranges (e.g. \"info skip 4-8\"), or both (e.g. \"info skip 1 3 4-8\").\n\n\
733If you don't specify any numbers or ranges, we'll show all skips."));
734 set_cmd_completer (c, complete_skip_number);
735
736 add_setshow_boolean_cmd ("skip", class_maintenance,
737 &debug_skip, _("\
738Set whether to print the debug output about skipping files and functions."),
739 _("\
740Show whether the debug output about skipping files and functions is printed."),
741 _("\
742When non-zero, debug output about skipping files and functions is displayed."),
743 NULL, NULL,
744 &setdebuglist, &showdebuglist);
745}
This page took 0.025275 seconds and 4 git commands to generate.