xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/maint.c (revision c9055873d0546e63388f027d3d7f85381cde0545)
1 /* Support for GDB maintenance commands.
2 
3    Copyright (C) 1992-2023 Free Software Foundation, Inc.
4 
5    Written by Fred Fish at Cygnus Support.
6 
7    This file is part of GDB.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21 
22 
23 #include "defs.h"
24 #include "arch-utils.h"
25 #include <ctype.h>
26 #include <cmath>
27 #include <signal.h>
28 #include "command.h"
29 #include "gdbcmd.h"
30 #include "symtab.h"
31 #include "block.h"
32 #include "gdbtypes.h"
33 #include "demangle.h"
34 #include "gdbcore.h"
35 #include "expression.h"		/* For language.h */
36 #include "language.h"
37 #include "symfile.h"
38 #include "objfiles.h"
39 #include "value.h"
40 #include "top.h"
41 #include "maint.h"
42 #include "gdbsupport/selftest.h"
43 #include "inferior.h"
44 #include "gdbsupport/thread-pool.h"
45 
46 #include "cli/cli-decode.h"
47 #include "cli/cli-utils.h"
48 #include "cli/cli-setshow.h"
49 #include "cli/cli-cmds.h"
50 
51 static void maintenance_do_deprecate (const char *, int);
52 
53 #ifndef _WIN32
54 static void
55 maintenance_dump_me (const char *args, int from_tty)
56 {
57   if (query (_("Should GDB dump core? ")))
58     {
59 #ifdef __DJGPP__
60       /* SIGQUIT by default is ignored, so use SIGABRT instead.  */
61       signal (SIGABRT, SIG_DFL);
62       kill (getpid (), SIGABRT);
63 #else
64       signal (SIGQUIT, SIG_DFL);
65       kill (getpid (), SIGQUIT);
66 #endif
67     }
68 }
69 #endif
70 
71 /* Stimulate the internal error mechanism that GDB uses when an
72    internal problem is detected.  Allows testing of the mechanism.
73    Also useful when the user wants to drop a core file but not exit
74    GDB.  */
75 
76 static void
77 maintenance_internal_error (const char *args, int from_tty)
78 {
79   internal_error ("%s", (args == NULL ? "" : args));
80 }
81 
82 /* Stimulate the internal error mechanism that GDB uses when an
83    internal problem is detected.  Allows testing of the mechanism.
84    Also useful when the user wants to drop a core file but not exit
85    GDB.  */
86 
87 static void
88 maintenance_internal_warning (const char *args, int from_tty)
89 {
90   internal_warning ("%s", (args == NULL ? "" : args));
91 }
92 
93 /* Stimulate the internal error mechanism that GDB uses when an
94    demangler problem is detected.  Allows testing of the mechanism.  */
95 
96 static void
97 maintenance_demangler_warning (const char *args, int from_tty)
98 {
99   demangler_warning (__FILE__, __LINE__, "%s", (args == NULL ? "" : args));
100 }
101 
102 /* Old command to demangle a string.  The command has been moved to "demangle".
103    It is kept for now because otherwise "mt demangle" gets interpreted as
104    "mt demangler-warning" which artificially creates an internal gdb error.  */
105 
106 static void
107 maintenance_demangle (const char *args, int from_tty)
108 {
109   gdb_printf (_("This command has been moved to \"demangle\".\n"));
110 }
111 
112 static void
113 maintenance_time_display (const char *args, int from_tty)
114 {
115   if (args == NULL || *args == '\0')
116     gdb_printf (_("\"maintenance time\" takes a numeric argument.\n"));
117   else
118     set_per_command_time (strtol (args, NULL, 10));
119 }
120 
121 static void
122 maintenance_space_display (const char *args, int from_tty)
123 {
124   if (args == NULL || *args == '\0')
125     gdb_printf ("\"maintenance space\" takes a numeric argument.\n");
126   else
127     set_per_command_space (strtol (args, NULL, 10));
128 }
129 
130 /* Mini tokenizing lexer for 'maint info sections' command.  */
131 
132 static bool
133 match_substring (const char *string, const char *substr)
134 {
135   int substr_len = strlen (substr);
136   const char *tok;
137 
138   while ((tok = strstr (string, substr)) != NULL)
139     {
140       /* Got a partial match.  Is it a whole word?  */
141       if (tok == string
142 	  || tok[-1] == ' '
143 	  || tok[-1] == '\t')
144       {
145 	/* Token is delimited at the front...  */
146 	if (tok[substr_len] == ' '
147 	    || tok[substr_len] == '\t'
148 	    || tok[substr_len] == '\0')
149 	{
150 	  /* Token is delimited at the rear.  Got a whole-word match.  */
151 	  return true;
152 	}
153       }
154       /* Token didn't match as a whole word.  Advance and try again.  */
155       string = tok + 1;
156     }
157   return false;
158 }
159 
160 /* Structure holding information about a single bfd section flag.  This is
161    used by the "maintenance info sections" command to print the sections,
162    and for filtering which sections are printed.  */
163 
164 struct single_bfd_flag_info
165 {
166   /* The name of the section.  This is what is printed for the flag, and
167      what the user enter in order to filter by flag.  */
168   const char *name;
169 
170   /* The bfd defined SEC_* flagword value for this flag.  */
171   flagword value;
172 };
173 
174 /* Vector of all the known bfd flags.  */
175 
176 static const single_bfd_flag_info bfd_flag_info[] =
177   {
178     { "ALLOC", SEC_ALLOC },
179     { "LOAD", SEC_LOAD },
180     { "RELOC", SEC_RELOC },
181     { "READONLY", SEC_READONLY },
182     { "CODE", SEC_CODE },
183     { "DATA", SEC_DATA },
184     { "ROM", SEC_ROM },
185     { "CONSTRUCTOR", SEC_CONSTRUCTOR },
186     { "HAS_CONTENTS", SEC_HAS_CONTENTS },
187     { "NEVER_LOAD", SEC_NEVER_LOAD },
188     { "COFF_SHARED_LIBRARY", SEC_COFF_SHARED_LIBRARY },
189     { "IS_COMMON", SEC_IS_COMMON }
190   };
191 
192 /* For each flag in the global BFD_FLAG_INFO list, if FLAGS has a flag's
193    flagword value set, and STRING contains the flag's name then return
194    true, otherwise return false.  STRING is never nullptr.  */
195 
196 static bool
197 match_bfd_flags (const char *string, flagword flags)
198 {
199   gdb_assert (string != nullptr);
200 
201   for (const auto &f : bfd_flag_info)
202     {
203       if (flags & f.value
204 	  && match_substring (string, f.name))
205 	return true;
206     }
207 
208   return false;
209 }
210 
211 /* Print the names of all flags set in FLAGS.  The names are taken from the
212    BFD_FLAG_INFO global.  */
213 
214 static void
215 print_bfd_flags (flagword flags)
216 {
217   for (const auto &f : bfd_flag_info)
218     {
219       if (flags & f.value)
220 	gdb_printf (" %s", f.name);
221     }
222 }
223 
224 static void
225 maint_print_section_info (const char *name, flagword flags,
226 			  CORE_ADDR addr, CORE_ADDR endaddr,
227 			  unsigned long filepos, int addr_size)
228 {
229   gdb_printf ("    %s", hex_string_custom (addr, addr_size));
230   gdb_printf ("->%s", hex_string_custom (endaddr, addr_size));
231   gdb_printf (" at %s",
232 	      hex_string_custom ((unsigned long) filepos, 8));
233   gdb_printf (": %s", name);
234   print_bfd_flags (flags);
235   gdb_printf ("\n");
236 }
237 
238 /* Return the number of digits required to display COUNT in decimal.
239 
240    Used when pretty printing index numbers to ensure all of the indexes line
241    up.*/
242 
243 static int
244 index_digits (int count)
245 {
246   return ((int) log10 ((float) count)) + 1;
247 }
248 
249 /* Helper function to pretty-print the section index of ASECT from ABFD.
250    The INDEX_DIGITS is the number of digits in the largest index that will
251    be printed, and is used to pretty-print the resulting string.  */
252 
253 static void
254 print_section_index (bfd *abfd,
255 		     asection *asect,
256 		     int index_digits)
257 {
258   std::string result
259     = string_printf (" [%d] ", gdb_bfd_section_index (abfd, asect));
260   /* The '+ 4' for the leading and trailing characters.  */
261   gdb_printf ("%-*s", (index_digits + 4), result.c_str ());
262 }
263 
264 /* Print information about ASECT from ABFD.  The section will be printed using
265    the VMA's from the bfd, which will not be the relocated addresses for bfds
266    that should be relocated.  The information must be printed with the same
267    layout as PRINT_OBJFILE_SECTION_INFO below.
268 
269    ARG is the argument string passed by the user to the top level maintenance
270    info sections command.  Used for filtering which sections are printed.  */
271 
272 static void
273 print_bfd_section_info (bfd *abfd, asection *asect, const char *arg,
274 			int index_digits)
275 {
276   flagword flags = bfd_section_flags (asect);
277   const char *name = bfd_section_name (asect);
278 
279   if (arg == NULL || *arg == '\0'
280       || match_substring (arg, name)
281       || match_bfd_flags (arg, flags))
282     {
283       struct gdbarch *gdbarch = gdbarch_from_bfd (abfd);
284       int addr_size = gdbarch_addr_bit (gdbarch) / 8;
285       CORE_ADDR addr, endaddr;
286 
287       addr = bfd_section_vma (asect);
288       endaddr = addr + bfd_section_size (asect);
289       print_section_index (abfd, asect, index_digits);
290       maint_print_section_info (name, flags, addr, endaddr,
291 				asect->filepos, addr_size);
292     }
293 }
294 
295 /* Print information about ASECT which is GDB's wrapper around a section
296    from ABFD.  The information must be printed with the same layout as
297    PRINT_BFD_SECTION_INFO above.  PRINT_DATA holds information used to
298    filter which sections are printed, and for formatting the output.
299 
300    ARG is the argument string passed by the user to the top level maintenance
301    info sections command.  Used for filtering which sections are printed.  */
302 
303 static void
304 print_objfile_section_info (bfd *abfd, struct obj_section *asect,
305 			    const char *arg, int index_digits)
306 {
307   flagword flags = bfd_section_flags (asect->the_bfd_section);
308   const char *name = bfd_section_name (asect->the_bfd_section);
309 
310   if (arg == NULL || *arg == '\0'
311       || match_substring (arg, name)
312       || match_bfd_flags (arg, flags))
313     {
314       struct gdbarch *gdbarch = gdbarch_from_bfd (abfd);
315       int addr_size = gdbarch_addr_bit (gdbarch) / 8;
316 
317       print_section_index (abfd, asect->the_bfd_section, index_digits);
318       maint_print_section_info (name, flags,
319 				asect->addr (), asect->endaddr (),
320 				asect->the_bfd_section->filepos,
321 				addr_size);
322     }
323 }
324 
325 /* Find an obj_section, GDB's wrapper around a bfd section for ASECTION
326    from ABFD.  It might be that no such wrapper exists (for example debug
327    sections don't have such wrappers) in which case nullptr is returned.  */
328 
329 obj_section *
330 maint_obj_section_from_bfd_section (bfd *abfd,
331 				    asection *asection,
332 				    objfile *ofile)
333 {
334   if (ofile->sections == nullptr)
335     return nullptr;
336 
337   obj_section *osect
338     = &ofile->sections[gdb_bfd_section_index (abfd, asection)];
339 
340   if (osect >= ofile->sections_end)
341     return nullptr;
342 
343   return osect;
344 }
345 
346 /* Print information about all sections from ABFD, which is the bfd
347    corresponding to OBJFILE.  It is fine for OBJFILE to be nullptr, but
348    ABFD must never be nullptr.  If OBJFILE is provided then the sections of
349    ABFD will (potentially) be displayed relocated (i.e. the object file was
350    loaded with add-symbol-file and custom offsets were provided).
351 
352    HEADER is a string that describes this file, e.g. 'Exec file: ', or
353    'Core file: '.
354 
355    ARG is a string used for filtering which sections are printed, this can
356    be nullptr for no filtering.  See the top level 'maint info sections'
357    for a fuller description of the possible filtering strings.  */
358 
359 static void
360 maint_print_all_sections (const char *header, bfd *abfd, objfile *objfile,
361 			  const char *arg)
362 {
363   gdb_puts (header);
364   gdb_stdout->wrap_here (8);
365   gdb_printf ("`%s', ", bfd_get_filename (abfd));
366   gdb_stdout->wrap_here (8);
367   gdb_printf (_("file type %s.\n"), bfd_get_target (abfd));
368 
369   int section_count = gdb_bfd_count_sections (abfd);
370   int digits = index_digits (section_count);
371 
372   for (asection *sect : gdb_bfd_sections (abfd))
373     {
374       obj_section *osect = nullptr;
375 
376       if (objfile != nullptr)
377 	{
378 	  gdb_assert (objfile->sections != nullptr);
379 	  osect
380 	    = maint_obj_section_from_bfd_section (abfd, sect, objfile);
381 	  if (osect->the_bfd_section == nullptr)
382 	    osect = nullptr;
383 	}
384 
385       if (osect == nullptr)
386 	print_bfd_section_info (abfd, sect, arg, digits);
387       else
388 	print_objfile_section_info (abfd, osect, arg, digits);
389     }
390 }
391 
392 /* The options for the "maintenance info sections" command.  */
393 
394 struct maint_info_sections_opts
395 {
396   /* For "-all-objects".  */
397   bool all_objects = false;
398 };
399 
400 static const gdb::option::option_def maint_info_sections_option_defs[] = {
401 
402   gdb::option::flag_option_def<maint_info_sections_opts> {
403     "all-objects",
404     [] (maint_info_sections_opts *opts) { return &opts->all_objects; },
405     N_("Display information from all loaded object files."),
406   },
407 };
408 
409 /* Create an option_def_group for the "maintenance info sections" options,
410    with CC_OPTS as context.  */
411 
412 static inline gdb::option::option_def_group
413 make_maint_info_sections_options_def_group (maint_info_sections_opts *cc_opts)
414 {
415   return {{maint_info_sections_option_defs}, cc_opts};
416 }
417 
418 /* Completion for the "maintenance info sections" command.  */
419 
420 static void
421 maint_info_sections_completer (struct cmd_list_element *cmd,
422 			       completion_tracker &tracker,
423 			       const char *text, const char * /* word */)
424 {
425   /* Complete command options.  */
426   const auto group = make_maint_info_sections_options_def_group (nullptr);
427   if (gdb::option::complete_options
428       (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group))
429     return;
430   const char *word = advance_to_expression_complete_word_point (tracker, text);
431 
432   /* Offer completion for section flags, but not section names.  This is
433      only a maintenance command after all, no point going over the top.  */
434   std::vector<const char *> flags;
435   for (const auto &f : bfd_flag_info)
436     flags.push_back (f.name);
437   flags.push_back (nullptr);
438   complete_on_enum (tracker, flags.data (), text, word);
439 }
440 
441 /* Implement the "maintenance info sections" command.  */
442 
443 static void
444 maintenance_info_sections (const char *arg, int from_tty)
445 {
446   /* Check if the "-all-objects" flag was passed.  */
447   maint_info_sections_opts opts;
448   const auto group = make_maint_info_sections_options_def_group (&opts);
449   gdb::option::process_options
450     (&arg, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group);
451 
452   for (objfile *ofile : current_program_space->objfiles ())
453     {
454       if (ofile->obfd == current_program_space->exec_bfd ())
455 	maint_print_all_sections (_("Exec file: "), ofile->obfd.get (),
456 				  ofile, arg);
457       else if (opts.all_objects)
458 	maint_print_all_sections (_("Object file: "), ofile->obfd.get (),
459 				  ofile, arg);
460     }
461 
462   if (core_bfd)
463     maint_print_all_sections (_("Core file: "), core_bfd, nullptr, arg);
464 }
465 
466 /* Implement the "maintenance info target-sections" command.  */
467 
468 static void
469 maintenance_info_target_sections (const char *arg, int from_tty)
470 {
471   bfd *abfd = nullptr;
472   int digits = 0;
473   const target_section_table *table
474     = target_get_section_table (current_inferior ()->top_target ());
475   if (table == nullptr)
476     return;
477 
478   for (const target_section &sec : *table)
479     {
480       if (abfd == nullptr || sec.the_bfd_section->owner != abfd)
481 	{
482 	  abfd = sec.the_bfd_section->owner;
483 	  digits = std::max (index_digits (gdb_bfd_count_sections (abfd)),
484 			     digits);
485 	}
486     }
487 
488   struct gdbarch *gdbarch = nullptr;
489   int addr_size = 0;
490   abfd = nullptr;
491   for (const target_section &sec : *table)
492    {
493       if (sec.the_bfd_section->owner != abfd)
494 	{
495 	  abfd = sec.the_bfd_section->owner;
496 	  gdbarch = gdbarch_from_bfd (abfd);
497 	  addr_size = gdbarch_addr_bit (gdbarch) / 8;
498 
499 	  gdb_printf (_("From '%s', file type %s:\n"),
500 		      bfd_get_filename (abfd), bfd_get_target (abfd));
501 	}
502       print_bfd_section_info (abfd,
503 			      sec.the_bfd_section,
504 			      nullptr,
505 			      digits);
506       /* The magic '8 + digits' here ensures that the 'Start' is aligned
507 	 with the output of print_bfd_section_info.  */
508       gdb_printf ("%*sStart: %s, End: %s, Owner token: %p\n",
509 		  (8 + digits), "",
510 		  hex_string_custom (sec.addr, addr_size),
511 		  hex_string_custom (sec.endaddr, addr_size),
512 		  sec.owner);
513     }
514 }
515 
516 static void
517 maintenance_print_statistics (const char *args, int from_tty)
518 {
519   print_objfile_statistics ();
520 }
521 
522 static void
523 maintenance_print_architecture (const char *args, int from_tty)
524 {
525   struct gdbarch *gdbarch = get_current_arch ();
526 
527   if (args == NULL)
528     gdbarch_dump (gdbarch, gdb_stdout);
529   else
530     {
531       stdio_file file;
532 
533       if (!file.open (args, "w"))
534 	perror_with_name (_("maintenance print architecture"));
535       gdbarch_dump (gdbarch, &file);
536     }
537 }
538 
539 /* The "maintenance translate-address" command converts a section and address
540    to a symbol.  This can be called in two ways:
541    maintenance translate-address <secname> <addr>
542    or   maintenance translate-address <addr>.  */
543 
544 static void
545 maintenance_translate_address (const char *arg, int from_tty)
546 {
547   CORE_ADDR address;
548   struct obj_section *sect;
549   const char *p;
550   struct bound_minimal_symbol sym;
551 
552   if (arg == NULL || *arg == 0)
553     error (_("requires argument (address or section + address)"));
554 
555   sect = NULL;
556   p = arg;
557 
558   if (!isdigit (*p))
559     {				/* See if we have a valid section name.  */
560       while (*p && !isspace (*p))	/* Find end of section name.  */
561 	p++;
562       if (*p == '\000')		/* End of command?  */
563 	error (_("Need to specify section name and address"));
564 
565       int arg_len = p - arg;
566       p = skip_spaces (p + 1);
567 
568       for (objfile *objfile : current_program_space->objfiles ())
569 	ALL_OBJFILE_OSECTIONS (objfile, sect)
570 	  {
571 	    if (strncmp (sect->the_bfd_section->name, arg, arg_len) == 0)
572 	      goto found;
573 	  }
574 
575       error (_("Unknown section %s."), arg);
576     found: ;
577     }
578 
579   address = parse_and_eval_address (p);
580 
581   if (sect)
582     sym = lookup_minimal_symbol_by_pc_section (address, sect);
583   else
584     sym = lookup_minimal_symbol_by_pc (address);
585 
586   if (sym.minsym)
587     {
588       const char *symbol_name = sym.minsym->print_name ();
589       const char *symbol_offset
590 	= pulongest (address - sym.value_address ());
591 
592       sect = sym.obj_section ();
593       if (sect != NULL)
594 	{
595 	  const char *section_name;
596 	  const char *obj_name;
597 
598 	  gdb_assert (sect->the_bfd_section && sect->the_bfd_section->name);
599 	  section_name = sect->the_bfd_section->name;
600 
601 	  gdb_assert (sect->objfile && objfile_name (sect->objfile));
602 	  obj_name = objfile_name (sect->objfile);
603 
604 	  if (current_program_space->multi_objfile_p ())
605 	    gdb_printf (_("%s + %s in section %s of %s\n"),
606 			symbol_name, symbol_offset,
607 			section_name, obj_name);
608 	  else
609 	    gdb_printf (_("%s + %s in section %s\n"),
610 			symbol_name, symbol_offset, section_name);
611 	}
612       else
613 	gdb_printf (_("%s + %s\n"), symbol_name, symbol_offset);
614     }
615   else if (sect)
616     gdb_printf (_("no symbol at %s:%s\n"),
617 		sect->the_bfd_section->name, hex_string (address));
618   else
619     gdb_printf (_("no symbol at %s\n"), hex_string (address));
620 
621   return;
622 }
623 
624 
625 /* When a command is deprecated the user will be warned the first time
626    the command is used.  If possible, a replacement will be
627    offered.  */
628 
629 static void
630 maintenance_deprecate (const char *args, int from_tty)
631 {
632   if (args == NULL || *args == '\0')
633     {
634       gdb_printf (_("\"maintenance deprecate\" takes an argument,\n\
635 the command you want to deprecate, and optionally the replacement command\n\
636 enclosed in quotes.\n"));
637     }
638 
639   maintenance_do_deprecate (args, 1);
640 }
641 
642 
643 static void
644 maintenance_undeprecate (const char *args, int from_tty)
645 {
646   if (args == NULL || *args == '\0')
647     {
648       gdb_printf (_("\"maintenance undeprecate\" takes an argument, \n\
649 the command you want to undeprecate.\n"));
650     }
651 
652   maintenance_do_deprecate (args, 0);
653 }
654 
655 /* You really shouldn't be using this.  It is just for the testsuite.
656    Rather, you should use deprecate_cmd() when the command is created
657    in _initialize_blah().
658 
659    This function deprecates a command and optionally assigns it a
660    replacement.  */
661 
662 static void
663 maintenance_do_deprecate (const char *text, int deprecate)
664 {
665   struct cmd_list_element *alias = NULL;
666   struct cmd_list_element *prefix_cmd = NULL;
667   struct cmd_list_element *cmd = NULL;
668 
669   const char *start_ptr = NULL;
670   const char *end_ptr = NULL;
671   int len;
672   char *replacement = NULL;
673 
674   if (text == NULL)
675     return;
676 
677   if (!lookup_cmd_composition (text, &alias, &prefix_cmd, &cmd))
678     {
679       gdb_printf (_("Can't find command '%s' to deprecate.\n"), text);
680       return;
681     }
682 
683   if (deprecate)
684     {
685       /* Look for a replacement command.  */
686       start_ptr = strchr (text, '\"');
687       if (start_ptr != NULL)
688 	{
689 	  start_ptr++;
690 	  end_ptr = strrchr (start_ptr, '\"');
691 	  if (end_ptr != NULL)
692 	    {
693 	      len = end_ptr - start_ptr;
694 	      replacement = savestring (start_ptr, len);
695 	    }
696 	}
697     }
698 
699   if (!start_ptr || !end_ptr)
700     replacement = NULL;
701 
702 
703   /* If they used an alias, we only want to deprecate the alias.
704 
705      Note the MALLOCED_REPLACEMENT test.  If the command's replacement
706      string was allocated at compile time we don't want to free the
707      memory.  */
708   if (alias)
709     {
710       if (alias->malloced_replacement)
711 	xfree ((char *) alias->replacement);
712 
713       if (deprecate)
714 	{
715 	  alias->deprecated_warn_user = 1;
716 	  alias->cmd_deprecated = 1;
717 	}
718       else
719 	{
720 	  alias->deprecated_warn_user = 0;
721 	  alias->cmd_deprecated = 0;
722 	}
723       alias->replacement = replacement;
724       alias->malloced_replacement = 1;
725       return;
726     }
727   else if (cmd)
728     {
729       if (cmd->malloced_replacement)
730 	xfree ((char *) cmd->replacement);
731 
732       if (deprecate)
733 	{
734 	  cmd->deprecated_warn_user = 1;
735 	  cmd->cmd_deprecated = 1;
736 	}
737       else
738 	{
739 	  cmd->deprecated_warn_user = 0;
740 	  cmd->cmd_deprecated = 0;
741 	}
742       cmd->replacement = replacement;
743       cmd->malloced_replacement = 1;
744       return;
745     }
746   xfree (replacement);
747 }
748 
749 /* Maintenance set/show framework.  */
750 
751 struct cmd_list_element *maintenance_set_cmdlist;
752 struct cmd_list_element *maintenance_show_cmdlist;
753 
754 /* "maintenance with" command.  */
755 
756 static void
757 maintenance_with_cmd (const char *args, int from_tty)
758 {
759   with_command_1 ("maintenance set ", maintenance_set_cmdlist, args, from_tty);
760 }
761 
762 /* "maintenance with" command completer.  */
763 
764 static void
765 maintenance_with_cmd_completer (struct cmd_list_element *ignore,
766 				completion_tracker &tracker,
767 				const char *text, const char * /*word*/)
768 {
769   with_command_completer_1 ("maintenance set ", tracker,  text);
770 }
771 
772 /* Profiling support.  */
773 
774 static bool maintenance_profile_p;
775 static void
776 show_maintenance_profile_p (struct ui_file *file, int from_tty,
777 			    struct cmd_list_element *c, const char *value)
778 {
779   gdb_printf (file, _("Internal profiling is %s.\n"), value);
780 }
781 
782 #ifdef HAVE__ETEXT
783 extern char _etext;
784 #define TEXTEND &_etext
785 #elif defined (HAVE_ETEXT)
786 extern char etext;
787 #define TEXTEND &etext
788 #endif
789 
790 #if defined (HAVE_MONSTARTUP) && defined (HAVE__MCLEANUP) && defined (TEXTEND)
791 
792 static int profiling_state;
793 
794 EXTERN_C void _mcleanup (void);
795 
796 static void
797 mcleanup_wrapper (void)
798 {
799   if (profiling_state)
800     _mcleanup ();
801 }
802 
803 EXTERN_C void monstartup (unsigned long, unsigned long);
804 extern int main (int, char **);
805 
806 static void
807 maintenance_set_profile_cmd (const char *args, int from_tty,
808 			     struct cmd_list_element *c)
809 {
810   if (maintenance_profile_p == profiling_state)
811     return;
812 
813   profiling_state = maintenance_profile_p;
814 
815   if (maintenance_profile_p)
816     {
817       static int profiling_initialized;
818 
819       if (!profiling_initialized)
820 	{
821 	  atexit (mcleanup_wrapper);
822 	  profiling_initialized = 1;
823 	}
824 
825       /* "main" is now always the first function in the text segment, so use
826 	 its address for monstartup.  */
827       monstartup ((unsigned long) &main, (unsigned long) TEXTEND);
828     }
829   else
830     {
831       extern void _mcleanup (void);
832 
833       _mcleanup ();
834     }
835 }
836 #else
837 static void
838 maintenance_set_profile_cmd (const char *args, int from_tty,
839 			     struct cmd_list_element *c)
840 {
841   error (_("Profiling support is not available on this system."));
842 }
843 #endif
844 
845 static int n_worker_threads = -1;
846 
847 /* Update the thread pool for the desired number of threads.  */
848 static void
849 update_thread_pool_size ()
850 {
851 #if CXX_STD_THREAD
852   int n_threads = n_worker_threads;
853 
854   if (n_threads < 0)
855     n_threads = std::thread::hardware_concurrency ();
856 
857   gdb::thread_pool::g_thread_pool->set_thread_count (n_threads);
858 #endif
859 }
860 
861 static void
862 maintenance_set_worker_threads (const char *args, int from_tty,
863 				struct cmd_list_element *c)
864 {
865   update_thread_pool_size ();
866 }
867 
868 static void
869 maintenance_show_worker_threads (struct ui_file *file, int from_tty,
870 				 struct cmd_list_element *c,
871 				 const char *value)
872 {
873 #if CXX_STD_THREAD
874   if (n_worker_threads == -1)
875     {
876       gdb_printf (file, _("The number of worker threads GDB "
877 			  "can use is unlimited (currently %zu).\n"),
878 		  gdb::thread_pool::g_thread_pool->thread_count ());
879       return;
880     }
881 #endif
882 
883   int report_threads = 0;
884 #if CXX_STD_THREAD
885   report_threads = n_worker_threads;
886 #endif
887   gdb_printf (file, _("The number of worker threads GDB "
888 		      "can use is %d.\n"),
889 	      report_threads);
890 }
891 
892 
893 /* If true, display time usage both at startup and for each command.  */
894 
895 static bool per_command_time;
896 
897 /* If true, display space usage both at startup and for each command.  */
898 
899 static bool per_command_space;
900 
901 /* If true, display basic symtab stats for each command.  */
902 
903 static bool per_command_symtab;
904 
905 /* mt per-command commands.  */
906 
907 static struct cmd_list_element *per_command_setlist;
908 static struct cmd_list_element *per_command_showlist;
909 
910 /* Set whether to display time statistics to NEW_VALUE
911    (non-zero means true).  */
912 
913 void
914 set_per_command_time (int new_value)
915 {
916   per_command_time = new_value;
917 }
918 
919 /* Set whether to display space statistics to NEW_VALUE
920    (non-zero means true).  */
921 
922 void
923 set_per_command_space (int new_value)
924 {
925   per_command_space = new_value;
926 }
927 
928 /* Count the number of symtabs and blocks.  */
929 
930 static void
931 count_symtabs_and_blocks (int *nr_symtabs_ptr, int *nr_compunit_symtabs_ptr,
932 			  int *nr_blocks_ptr)
933 {
934   int nr_symtabs = 0;
935   int nr_compunit_symtabs = 0;
936   int nr_blocks = 0;
937 
938   /* When collecting statistics during startup, this is called before
939      pretty much anything in gdb has been initialized, and thus
940      current_program_space may be NULL.  */
941   if (current_program_space != NULL)
942     {
943       for (objfile *o : current_program_space->objfiles ())
944 	{
945 	  for (compunit_symtab *cu : o->compunits ())
946 	    {
947 	      ++nr_compunit_symtabs;
948 	      nr_blocks += cu->blockvector ()->num_blocks ();
949 	      nr_symtabs += std::distance (cu->filetabs ().begin (),
950 					   cu->filetabs ().end ());
951 	    }
952 	}
953     }
954 
955   *nr_symtabs_ptr = nr_symtabs;
956   *nr_compunit_symtabs_ptr = nr_compunit_symtabs;
957   *nr_blocks_ptr = nr_blocks;
958 }
959 
960 /* As indicated by display_time and display_space, report GDB's
961    elapsed time and space usage from the base time and space recorded
962    in this object.  */
963 
964 scoped_command_stats::~scoped_command_stats ()
965 {
966   /* Early exit if we're not reporting any stats.  It can be expensive to
967      compute the pre-command values so don't collect them at all if we're
968      not reporting stats.  Alas this doesn't work in the startup case because
969      we don't know yet whether we will be reporting the stats.  For the
970      startup case collect the data anyway (it should be cheap at this point),
971      and leave it to the reporter to decide whether to print them.  */
972   if (m_msg_type
973       && !per_command_time
974       && !per_command_space
975       && !per_command_symtab)
976     return;
977 
978   if (m_time_enabled && per_command_time)
979     {
980       print_time (_("command finished"));
981 
982       using namespace std::chrono;
983 
984       run_time_clock::duration cmd_time
985 	= run_time_clock::now () - m_start_cpu_time;
986 
987       steady_clock::duration wall_time
988 	= steady_clock::now () - m_start_wall_time;
989       /* Subtract time spend in prompt_for_continue from walltime.  */
990       wall_time -= get_prompt_for_continue_wait_time ();
991 
992       gdb_printf (gdb_stdlog,
993 		  !m_msg_type
994 		  ? _("Startup time: %.6f (cpu), %.6f (wall)\n")
995 		  : _("Command execution time: %.6f (cpu), %.6f (wall)\n"),
996 		  duration<double> (cmd_time).count (),
997 		  duration<double> (wall_time).count ());
998     }
999 
1000   if (m_space_enabled && per_command_space)
1001     {
1002 #ifdef HAVE_USEFUL_SBRK
1003       char *lim = (char *) sbrk (0);
1004 
1005       long space_now = lim - lim_at_start;
1006       long space_diff = space_now - m_start_space;
1007 
1008       gdb_printf (gdb_stdlog,
1009 		  !m_msg_type
1010 		  ? _("Space used: %ld (%s%ld during startup)\n")
1011 		  : _("Space used: %ld (%s%ld for this command)\n"),
1012 		  space_now,
1013 		  (space_diff >= 0 ? "+" : ""),
1014 		  space_diff);
1015 #endif
1016     }
1017 
1018   if (m_symtab_enabled && per_command_symtab)
1019     {
1020       int nr_symtabs, nr_compunit_symtabs, nr_blocks;
1021 
1022       count_symtabs_and_blocks (&nr_symtabs, &nr_compunit_symtabs, &nr_blocks);
1023       gdb_printf (gdb_stdlog,
1024 		  _("#symtabs: %d (+%d),"
1025 		    " #compunits: %d (+%d),"
1026 		    " #blocks: %d (+%d)\n"),
1027 		  nr_symtabs,
1028 		  nr_symtabs - m_start_nr_symtabs,
1029 		  nr_compunit_symtabs,
1030 		  (nr_compunit_symtabs
1031 		   - m_start_nr_compunit_symtabs),
1032 		  nr_blocks,
1033 		  nr_blocks - m_start_nr_blocks);
1034     }
1035 }
1036 
1037 scoped_command_stats::scoped_command_stats (bool msg_type)
1038 : m_msg_type (msg_type)
1039 {
1040   if (!m_msg_type || per_command_space)
1041     {
1042 #ifdef HAVE_USEFUL_SBRK
1043       char *lim = (char *) sbrk (0);
1044       m_start_space = lim - lim_at_start;
1045       m_space_enabled = 1;
1046 #endif
1047     }
1048   else
1049     m_space_enabled = 0;
1050 
1051   if (msg_type == 0 || per_command_time)
1052     {
1053       using namespace std::chrono;
1054 
1055       m_start_cpu_time = run_time_clock::now ();
1056       m_start_wall_time = steady_clock::now ();
1057       m_time_enabled = 1;
1058 
1059       if (per_command_time)
1060 	print_time (_("command started"));
1061     }
1062   else
1063     m_time_enabled = 0;
1064 
1065   if (msg_type == 0 || per_command_symtab)
1066     {
1067       int nr_symtabs, nr_compunit_symtabs, nr_blocks;
1068 
1069       count_symtabs_and_blocks (&nr_symtabs, &nr_compunit_symtabs, &nr_blocks);
1070       m_start_nr_symtabs = nr_symtabs;
1071       m_start_nr_compunit_symtabs = nr_compunit_symtabs;
1072       m_start_nr_blocks = nr_blocks;
1073       m_symtab_enabled = 1;
1074     }
1075   else
1076     m_symtab_enabled = 0;
1077 
1078   /* Initialize timer to keep track of how long we waited for the user.  */
1079   reset_prompt_for_continue_wait_time ();
1080 }
1081 
1082 /* See maint.h.  */
1083 
1084 void
1085 scoped_command_stats::print_time (const char *msg)
1086 {
1087   using namespace std::chrono;
1088 
1089   auto now = system_clock::now ();
1090   auto ticks = now.time_since_epoch ().count () / (1000 * 1000);
1091   auto millis = ticks % 1000;
1092 
1093   std::time_t as_time = system_clock::to_time_t (now);
1094   struct tm tm;
1095   localtime_r (&as_time, &tm);
1096 
1097   char out[100];
1098   strftime (out, sizeof (out), "%F %H:%M:%S", &tm);
1099 
1100   gdb_printf (gdb_stdlog, "%s.%03d - %s\n", out, (int) millis, msg);
1101 }
1102 
1103 /* Handle unknown "mt set per-command" arguments.
1104    In this case have "mt set per-command on|off" affect every setting.  */
1105 
1106 static void
1107 set_per_command_cmd (const char *args, int from_tty)
1108 {
1109   struct cmd_list_element *list;
1110   int val;
1111 
1112   val = parse_cli_boolean_value (args);
1113   if (val < 0)
1114     error (_("Bad value for 'mt set per-command no'."));
1115 
1116   for (list = per_command_setlist; list != NULL; list = list->next)
1117     if (list->var->type () == var_boolean)
1118       {
1119 	gdb_assert (list->type == set_cmd);
1120 	do_set_command (args, from_tty, list);
1121       }
1122 }
1123 
1124 /* Options affecting the "maintenance selftest" command.  */
1125 
1126 struct maintenance_selftest_options
1127 {
1128   bool verbose = false;
1129 } user_maintenance_selftest_options;
1130 
1131 static const gdb::option::option_def maintenance_selftest_option_defs[] = {
1132   gdb::option::boolean_option_def<maintenance_selftest_options> {
1133     "verbose",
1134     [] (maintenance_selftest_options *opt) { return &opt->verbose; },
1135     nullptr,
1136     N_("Set whether selftests run in verbose mode."),
1137     N_("Show whether selftests run in verbose mode."),
1138     N_("\
1139 When on, selftests may print verbose information."),
1140   },
1141 };
1142 
1143 /* Make option groups for the "maintenance selftest" command.  */
1144 
1145 static std::array<gdb::option::option_def_group, 1>
1146 make_maintenance_selftest_option_group (maintenance_selftest_options *opts)
1147 {
1148   return {{
1149     {{maintenance_selftest_option_defs}, opts},
1150   }};
1151 }
1152 
1153 /* The "maintenance selftest" command.  */
1154 
1155 static void
1156 maintenance_selftest (const char *args, int from_tty)
1157 {
1158 #if GDB_SELF_TEST
1159   maintenance_selftest_options opts = user_maintenance_selftest_options;
1160   auto grp = make_maintenance_selftest_option_group (&opts);
1161   gdb::option::process_options
1162     (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp);
1163   const gdb_argv argv (args);
1164   selftests::run_tests (argv.as_array_view (), opts.verbose);
1165 #else
1166   gdb_printf (_("\
1167 Selftests have been disabled for this build.\n"));
1168 #endif
1169 }
1170 
1171 /* Completer for the "maintenance selftest" command.  */
1172 
1173 static void
1174 maintenance_selftest_completer (cmd_list_element *cmd,
1175 				completion_tracker &tracker,
1176 				const char *text,
1177 				const char *word)
1178 {
1179   auto grp = make_maintenance_selftest_option_group (nullptr);
1180 
1181   if (gdb::option::complete_options
1182 	(tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp))
1183     return;
1184 
1185 #if GDB_SELF_TEST
1186   for (const auto &test : selftests::all_selftests ())
1187     {
1188       if (startswith (test.name.c_str (), text))
1189 	tracker.add_completion (make_unique_xstrdup (test.name.c_str ()));
1190     }
1191 #endif
1192 }
1193 
1194 static void
1195 maintenance_info_selftests (const char *arg, int from_tty)
1196 {
1197 #if GDB_SELF_TEST
1198   gdb_printf ("Registered selftests:\n");
1199   for (const auto &test : selftests::all_selftests ())
1200     gdb_printf (" - %s\n", test.name.c_str ());
1201 #else
1202   gdb_printf (_("\
1203 Selftests have been disabled for this build.\n"));
1204 #endif
1205 }
1206 
1207 
1208 void _initialize_maint_cmds ();
1209 void
1210 _initialize_maint_cmds ()
1211 {
1212   struct cmd_list_element *cmd;
1213 
1214   cmd_list_element *maintenance_cmd
1215     = add_basic_prefix_cmd ("maintenance", class_maintenance, _("\
1216 Commands for use by GDB maintainers.\n\
1217 Includes commands to dump specific internal GDB structures in\n\
1218 a human readable form, to cause GDB to deliberately dump core, etc."),
1219 			    &maintenancelist, 0,
1220 			    &cmdlist);
1221 
1222   add_com_alias ("mt", maintenance_cmd, class_maintenance, 1);
1223 
1224   cmd_list_element *maintenance_info_cmd
1225     = add_basic_prefix_cmd ("info", class_maintenance, _("\
1226 Commands for showing internal info about the program being debugged."),
1227 			    &maintenanceinfolist, 0,
1228 			    &maintenancelist);
1229   add_alias_cmd ("i", maintenance_info_cmd, class_maintenance, 1,
1230 		 &maintenancelist);
1231 
1232   const auto opts = make_maint_info_sections_options_def_group (nullptr);
1233   static std::string maint_info_sections_command_help
1234     = gdb::option::build_help (_("\
1235 List the BFD sections of the exec and core files.\n\
1236 \n\
1237 Usage: maintenance info sections [-all-objects] [FILTERS]\n\
1238 \n\
1239 FILTERS is a list of words, each word is either:\n\
1240   + A section name - any section with this name will be printed, or\n\
1241   + A section flag - any section with this flag will be printed.  The\n\
1242         known flags are:\n\
1243 	  ALLOC LOAD RELOC READONLY CODE DATA ROM CONSTRUCTOR\n\
1244 	  HAS_CONTENTS NEVER_LOAD COFF_SHARED_LIBRARY IS_COMMON\n\
1245 \n\
1246 Sections matching any of the FILTERS will be listed (no FILTERS implies\n\
1247 all sections should be printed).\n\
1248 \n\
1249 Options:\n\
1250 %OPTIONS%"), opts);
1251   cmd = add_cmd ("sections", class_maintenance, maintenance_info_sections,
1252 		 maint_info_sections_command_help.c_str (),
1253 		 &maintenanceinfolist);
1254   set_cmd_completer_handle_brkchars (cmd, maint_info_sections_completer);
1255 
1256   add_cmd ("target-sections", class_maintenance,
1257 	   maintenance_info_target_sections, _("\
1258 List GDB's internal section table.\n\
1259 \n\
1260 Print the current targets section list.  This is a sub-set of all\n\
1261 sections, from all objects currently loaded.  Usually the ALLOC\n\
1262 sectoins."),
1263 	   &maintenanceinfolist);
1264 
1265   add_basic_prefix_cmd ("print", class_maintenance,
1266 			_("Maintenance command for printing GDB internal state."),
1267 			&maintenanceprintlist, 0,
1268 			&maintenancelist);
1269 
1270   add_basic_prefix_cmd ("flush", class_maintenance,
1271 			_("Maintenance command for flushing GDB internal caches."),
1272 			&maintenanceflushlist, 0,
1273 			&maintenancelist);
1274 
1275   add_basic_prefix_cmd ("set", class_maintenance, _("\
1276 Set GDB internal variables used by the GDB maintainer.\n\
1277 Configure variables internal to GDB that aid in GDB's maintenance"),
1278 			&maintenance_set_cmdlist,
1279 			0/*allow-unknown*/,
1280 			&maintenancelist);
1281 
1282   add_show_prefix_cmd ("show", class_maintenance, _("\
1283 Show GDB internal variables used by the GDB maintainer.\n\
1284 Configure variables internal to GDB that aid in GDB's maintenance"),
1285 		       &maintenance_show_cmdlist,
1286 		       0/*allow-unknown*/,
1287 		       &maintenancelist);
1288 
1289   cmd = add_cmd ("with", class_maintenance, maintenance_with_cmd, _("\
1290 Like \"with\", but works with \"maintenance set\" variables.\n\
1291 Usage: maintenance with SETTING [VALUE] [-- COMMAND]\n\
1292 With no COMMAND, repeats the last executed command.\n\
1293 SETTING is any setting you can change with the \"maintenance set\"\n\
1294 subcommands."),
1295 		 &maintenancelist);
1296   set_cmd_completer_handle_brkchars (cmd, maintenance_with_cmd_completer);
1297 
1298 #ifndef _WIN32
1299   add_cmd ("dump-me", class_maintenance, maintenance_dump_me, _("\
1300 Get fatal error; make debugger dump its core.\n\
1301 GDB sets its handling of SIGQUIT back to SIG_DFL and then sends\n\
1302 itself a SIGQUIT signal."),
1303 	   &maintenancelist);
1304 #endif
1305 
1306   add_cmd ("internal-error", class_maintenance,
1307 	   maintenance_internal_error, _("\
1308 Give GDB an internal error.\n\
1309 Cause GDB to behave as if an internal error was detected."),
1310 	   &maintenancelist);
1311 
1312   add_cmd ("internal-warning", class_maintenance,
1313 	   maintenance_internal_warning, _("\
1314 Give GDB an internal warning.\n\
1315 Cause GDB to behave as if an internal warning was reported."),
1316 	   &maintenancelist);
1317 
1318   add_cmd ("demangler-warning", class_maintenance,
1319 	   maintenance_demangler_warning, _("\
1320 Give GDB a demangler warning.\n\
1321 Cause GDB to behave as if a demangler warning was reported."),
1322 	   &maintenancelist);
1323 
1324   cmd = add_cmd ("demangle", class_maintenance, maintenance_demangle, _("\
1325 This command has been moved to \"demangle\"."),
1326 		 &maintenancelist);
1327   deprecate_cmd (cmd, "demangle");
1328 
1329   add_prefix_cmd ("per-command", class_maintenance, set_per_command_cmd, _("\
1330 Per-command statistics settings."),
1331 		    &per_command_setlist,
1332 		    1/*allow-unknown*/, &maintenance_set_cmdlist);
1333 
1334   add_show_prefix_cmd ("per-command", class_maintenance, _("\
1335 Show per-command statistics settings."),
1336 		       &per_command_showlist,
1337 		       0/*allow-unknown*/, &maintenance_show_cmdlist);
1338 
1339   add_setshow_boolean_cmd ("time", class_maintenance,
1340 			   &per_command_time, _("\
1341 Set whether to display per-command execution time."), _("\
1342 Show whether to display per-command execution time."),
1343 			   _("\
1344 If enabled, the execution time for each command will be\n\
1345 displayed following the command's output."),
1346 			   NULL, NULL,
1347 			   &per_command_setlist, &per_command_showlist);
1348 
1349   add_setshow_boolean_cmd ("space", class_maintenance,
1350 			   &per_command_space, _("\
1351 Set whether to display per-command space usage."), _("\
1352 Show whether to display per-command space usage."),
1353 			   _("\
1354 If enabled, the space usage for each command will be\n\
1355 displayed following the command's output."),
1356 			   NULL, NULL,
1357 			   &per_command_setlist, &per_command_showlist);
1358 
1359   add_setshow_boolean_cmd ("symtab", class_maintenance,
1360 			   &per_command_symtab, _("\
1361 Set whether to display per-command symtab statistics."), _("\
1362 Show whether to display per-command symtab statistics."),
1363 			   _("\
1364 If enabled, the basic symtab statistics for each command will be\n\
1365 displayed following the command's output."),
1366 			   NULL, NULL,
1367 			   &per_command_setlist, &per_command_showlist);
1368 
1369   /* This is equivalent to "mt set per-command time on".
1370      Kept because some people are used to typing "mt time 1".  */
1371   add_cmd ("time", class_maintenance, maintenance_time_display, _("\
1372 Set the display of time usage.\n\
1373 If nonzero, will cause the execution time for each command to be\n\
1374 displayed, following the command's output."),
1375 	   &maintenancelist);
1376 
1377   /* This is equivalent to "mt set per-command space on".
1378      Kept because some people are used to typing "mt space 1".  */
1379   add_cmd ("space", class_maintenance, maintenance_space_display, _("\
1380 Set the display of space usage.\n\
1381 If nonzero, will cause the execution space for each command to be\n\
1382 displayed, following the command's output."),
1383 	   &maintenancelist);
1384 
1385   cmd = add_cmd ("type", class_maintenance, maintenance_print_type, _("\
1386 Print a type chain for a given symbol.\n\
1387 For each node in a type chain, print the raw data for each member of\n\
1388 the type structure, and the interpretation of the data."),
1389 	   &maintenanceprintlist);
1390   set_cmd_completer (cmd, expression_completer);
1391 
1392   add_cmd ("statistics", class_maintenance, maintenance_print_statistics,
1393 	   _("Print statistics about internal gdb state."),
1394 	   &maintenanceprintlist);
1395 
1396   add_cmd ("architecture", class_maintenance,
1397 	   maintenance_print_architecture, _("\
1398 Print the internal architecture configuration.\n\
1399 Takes an optional file parameter."),
1400 	   &maintenanceprintlist);
1401 
1402   add_basic_prefix_cmd ("check", class_maintenance, _("\
1403 Commands for checking internal gdb state."),
1404 			&maintenancechecklist, 0,
1405 			&maintenancelist);
1406 
1407   add_cmd ("translate-address", class_maintenance,
1408 	   maintenance_translate_address,
1409 	   _("Translate a section name and address to a symbol."),
1410 	   &maintenancelist);
1411 
1412   add_cmd ("deprecate", class_maintenance, maintenance_deprecate, _("\
1413 Deprecate a command (for testing purposes).\n\
1414 Usage: maintenance deprecate COMMANDNAME [\"REPLACEMENT\"]\n\
1415 This is used by the testsuite to check the command deprecator.\n\
1416 You probably shouldn't use this,\n\
1417 rather you should use the C function deprecate_cmd()."), &maintenancelist);
1418 
1419   add_cmd ("undeprecate", class_maintenance, maintenance_undeprecate, _("\
1420 Undeprecate a command (for testing purposes).\n\
1421 Usage: maintenance undeprecate COMMANDNAME\n\
1422 This is used by the testsuite to check the command deprecator.\n\
1423 You probably shouldn't use this."),
1424 	   &maintenancelist);
1425 
1426   cmd_list_element *maintenance_selftest_cmd
1427     = add_cmd ("selftest", class_maintenance, maintenance_selftest, _("\
1428 Run gdb's unit tests.\n\
1429 Usage: maintenance selftest [FILTER]\n\
1430 This will run any unit tests that were built in to gdb.\n\
1431 If a filter is given, only the tests with that value in their name will ran."),
1432 	       &maintenancelist);
1433   set_cmd_completer_handle_brkchars (maintenance_selftest_cmd,
1434 				     maintenance_selftest_completer);
1435 
1436   add_cmd ("selftests", class_maintenance, maintenance_info_selftests,
1437 	 _("List the registered selftests."), &maintenanceinfolist);
1438 
1439   add_setshow_boolean_cmd ("profile", class_maintenance,
1440 			   &maintenance_profile_p, _("\
1441 Set internal profiling."), _("\
1442 Show internal profiling."), _("\
1443 When enabled GDB is profiled."),
1444 			   maintenance_set_profile_cmd,
1445 			   show_maintenance_profile_p,
1446 			   &maintenance_set_cmdlist,
1447 			   &maintenance_show_cmdlist);
1448 
1449   add_setshow_zuinteger_unlimited_cmd ("worker-threads",
1450 				       class_maintenance,
1451 				       &n_worker_threads, _("\
1452 Set the number of worker threads GDB can use."), _("\
1453 Show the number of worker threads GDB can use."), _("\
1454 GDB may use multiple threads to speed up certain CPU-intensive operations,\n\
1455 such as demangling symbol names."),
1456 				       maintenance_set_worker_threads,
1457 				       maintenance_show_worker_threads,
1458 				       &maintenance_set_cmdlist,
1459 				       &maintenance_show_cmdlist);
1460 
1461   /* Add the "maint set/show selftest" commands.  */
1462   static cmd_list_element *set_selftest_cmdlist = nullptr;
1463   static cmd_list_element *show_selftest_cmdlist = nullptr;
1464 
1465   add_setshow_prefix_cmd ("selftest", class_maintenance,
1466 			  _("Self tests-related settings."),
1467 			  _("Self tests-related settings."),
1468 			  &set_selftest_cmdlist, &show_selftest_cmdlist,
1469 			  &maintenance_set_cmdlist, &maintenance_show_cmdlist);
1470 
1471   /* Add setting commands matching "maintenance selftest" options.  */
1472   gdb::option::add_setshow_cmds_for_options (class_maintenance,
1473 					     &user_maintenance_selftest_options,
1474 					     maintenance_selftest_option_defs,
1475 					     &set_selftest_cmdlist,
1476 					     &show_selftest_cmdlist);
1477 
1478   update_thread_pool_size ();
1479 }
1480