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