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