1/* Support for GDB maintenance commands.
2
3   Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
4   2002, 2003, 2004 Free Software Foundation, Inc.
5
6   Written by Fred Fish at Cygnus Support.
7
8   This file is part of GDB.
9
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 2 of the License, or
13   (at your option) any later version.
14
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 59 Temple Place - Suite 330,
23   Boston, MA 02111-1307, USA.  */
24
25
26#include "defs.h"
27#include <ctype.h>
28#include <signal.h>
29#include "command.h"
30#include "gdbcmd.h"
31#include "symtab.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
41#include "cli/cli-decode.h"
42
43extern void _initialize_maint_cmds (void);
44
45static void maintenance_command (char *, int);
46
47static void maintenance_dump_me (char *, int);
48
49static void maintenance_internal_error (char *args, int from_tty);
50
51static void maintenance_demangle (char *, int);
52
53static void maintenance_time_display (char *, int);
54
55static void maintenance_space_display (char *, int);
56
57static void maintenance_info_command (char *, int);
58
59static void maintenance_info_sections (char *, int);
60
61static void maintenance_print_command (char *, int);
62
63static void maintenance_do_deprecate (char *, int);
64
65/* Set this to the maximum number of seconds to wait instead of waiting forever
66   in target_wait().  If this timer times out, then it generates an error and
67   the command is aborted.  This replaces most of the need for timeouts in the
68   GDB test suite, and makes it possible to distinguish between a hung target
69   and one with slow communications.  */
70
71int watchdog = 0;
72
73/*
74
75   LOCAL FUNCTION
76
77   maintenance_command -- access the maintenance subcommands
78
79   SYNOPSIS
80
81   void maintenance_command (char *args, int from_tty)
82
83   DESCRIPTION
84
85 */
86
87static void
88maintenance_command (char *args, int from_tty)
89{
90  printf_unfiltered ("\"maintenance\" must be followed by the name of a maintenance command.\n");
91  help_list (maintenancelist, "maintenance ", -1, gdb_stdout);
92}
93
94#ifndef _WIN32
95static void
96maintenance_dump_me (char *args, int from_tty)
97{
98  if (query ("Should GDB dump core? "))
99    {
100#ifdef __DJGPP__
101      /* SIGQUIT by default is ignored, so use SIGABRT instead.  */
102      signal (SIGABRT, SIG_DFL);
103      kill (getpid (), SIGABRT);
104#else
105      signal (SIGQUIT, SIG_DFL);
106      kill (getpid (), SIGQUIT);
107#endif
108    }
109}
110#endif
111
112/* Stimulate the internal error mechanism that GDB uses when an
113   internal problem is detected.  Allows testing of the mechanism.
114   Also useful when the user wants to drop a core file but not exit
115   GDB. */
116
117static void
118maintenance_internal_error (char *args, int from_tty)
119{
120  internal_error (__FILE__, __LINE__, "%s", (args == NULL ? "" : args));
121}
122
123/* Stimulate the internal error mechanism that GDB uses when an
124   internal problem is detected.  Allows testing of the mechanism.
125   Also useful when the user wants to drop a core file but not exit
126   GDB. */
127
128static void
129maintenance_internal_warning (char *args, int from_tty)
130{
131  internal_warning (__FILE__, __LINE__, "%s", (args == NULL ? "" : args));
132}
133
134/* Someday we should allow demangling for things other than just
135   explicit strings.  For example, we might want to be able to specify
136   the address of a string in either GDB's process space or the
137   debuggee's process space, and have gdb fetch and demangle that
138   string.  If we have a char* pointer "ptr" that points to a string,
139   we might want to be able to given just the name and have GDB
140   demangle and print what it points to, etc.  (FIXME) */
141
142static void
143maintenance_demangle (char *args, int from_tty)
144{
145  char *demangled;
146
147  if (args == NULL || *args == '\0')
148    {
149      printf_unfiltered ("\"maintenance demangle\" takes an argument to demangle.\n");
150    }
151  else
152    {
153      demangled = language_demangle (current_language, args,
154				     DMGL_ANSI | DMGL_PARAMS);
155      if (demangled != NULL)
156	{
157	  printf_unfiltered ("%s\n", demangled);
158	  xfree (demangled);
159	}
160      else
161	{
162	  printf_unfiltered ("Can't demangle \"%s\"\n", args);
163	}
164    }
165}
166
167static void
168maintenance_time_display (char *args, int from_tty)
169{
170  extern int display_time;
171
172  if (args == NULL || *args == '\0')
173    printf_unfiltered ("\"maintenance time\" takes a numeric argument.\n");
174  else
175    display_time = strtol (args, NULL, 10);
176}
177
178static void
179maintenance_space_display (char *args, int from_tty)
180{
181  extern int display_space;
182
183  if (args == NULL || *args == '\0')
184    printf_unfiltered ("\"maintenance space\" takes a numeric argument.\n");
185  else
186    display_space = strtol (args, NULL, 10);
187}
188
189/* The "maintenance info" command is defined as a prefix, with
190   allow_unknown 0.  Therefore, its own definition is called only for
191   "maintenance info" with no args.  */
192
193static void
194maintenance_info_command (char *arg, int from_tty)
195{
196  printf_unfiltered ("\"maintenance info\" must be followed by the name of an info command.\n");
197  help_list (maintenanceinfolist, "maintenance info ", -1, gdb_stdout);
198}
199
200/* Mini tokenizing lexer for 'maint info sections' command.  */
201
202static int
203match_substring (const char *string, const char *substr)
204{
205  int substr_len = strlen(substr);
206  const char *tok;
207
208  while ((tok = strstr (string, substr)) != NULL)
209    {
210      /* Got a partial match.  Is it a whole word? */
211      if (tok == string
212	  || tok[-1] == ' '
213	  || tok[-1] == '\t')
214      {
215	/* Token is delimited at the front... */
216	if (tok[substr_len] == ' '
217	    || tok[substr_len] == '\t'
218	    || tok[substr_len] == '\0')
219	{
220	  /* Token is delimited at the rear.  Got a whole-word match.  */
221	  return 1;
222	}
223      }
224      /* Token didn't match as a whole word.  Advance and try again.  */
225      string = tok + 1;
226    }
227  return 0;
228}
229
230static int
231match_bfd_flags (char *string, flagword flags)
232{
233  if (flags & SEC_ALLOC)
234    if (match_substring (string, "ALLOC"))
235      return 1;
236  if (flags & SEC_LOAD)
237    if (match_substring (string, "LOAD"))
238      return 1;
239  if (flags & SEC_RELOC)
240    if (match_substring (string, "RELOC"))
241      return 1;
242  if (flags & SEC_READONLY)
243    if (match_substring (string, "READONLY"))
244      return 1;
245  if (flags & SEC_CODE)
246    if (match_substring (string, "CODE"))
247      return 1;
248  if (flags & SEC_DATA)
249    if (match_substring (string, "DATA"))
250      return 1;
251  if (flags & SEC_ROM)
252    if (match_substring (string, "ROM"))
253      return 1;
254  if (flags & SEC_CONSTRUCTOR)
255    if (match_substring (string, "CONSTRUCTOR"))
256      return 1;
257  if (flags & SEC_HAS_CONTENTS)
258    if (match_substring (string, "HAS_CONTENTS"))
259      return 1;
260  if (flags & SEC_NEVER_LOAD)
261    if (match_substring (string, "NEVER_LOAD"))
262      return 1;
263  if (flags & SEC_COFF_SHARED_LIBRARY)
264    if (match_substring (string, "COFF_SHARED_LIBRARY"))
265      return 1;
266  if (flags & SEC_IS_COMMON)
267    if (match_substring (string, "IS_COMMON"))
268      return 1;
269
270  return 0;
271}
272
273static void
274print_bfd_flags (flagword flags)
275{
276  if (flags & SEC_ALLOC)
277    printf_filtered (" ALLOC");
278  if (flags & SEC_LOAD)
279    printf_filtered (" LOAD");
280  if (flags & SEC_RELOC)
281    printf_filtered (" RELOC");
282  if (flags & SEC_READONLY)
283    printf_filtered (" READONLY");
284  if (flags & SEC_CODE)
285    printf_filtered (" CODE");
286  if (flags & SEC_DATA)
287    printf_filtered (" DATA");
288  if (flags & SEC_ROM)
289    printf_filtered (" ROM");
290  if (flags & SEC_CONSTRUCTOR)
291    printf_filtered (" CONSTRUCTOR");
292  if (flags & SEC_HAS_CONTENTS)
293    printf_filtered (" HAS_CONTENTS");
294  if (flags & SEC_NEVER_LOAD)
295    printf_filtered (" NEVER_LOAD");
296  if (flags & SEC_COFF_SHARED_LIBRARY)
297    printf_filtered (" COFF_SHARED_LIBRARY");
298  if (flags & SEC_IS_COMMON)
299    printf_filtered (" IS_COMMON");
300}
301
302static void
303maint_print_section_info (const char *name, flagword flags,
304			  CORE_ADDR addr, CORE_ADDR endaddr,
305			  unsigned long filepos)
306{
307  /* FIXME-32x64: Need print_address_numeric with field width.  */
308  printf_filtered ("    0x%s", paddr (addr));
309  printf_filtered ("->0x%s", paddr (endaddr));
310  printf_filtered (" at %s",
311		   local_hex_string_custom ((unsigned long) filepos, "08l"));
312  printf_filtered (": %s", name);
313  print_bfd_flags (flags);
314  printf_filtered ("\n");
315}
316
317static void
318print_bfd_section_info (bfd *abfd,
319			asection *asect,
320			void *arg)
321{
322  flagword flags = bfd_get_section_flags (abfd, asect);
323  const char *name = bfd_section_name (abfd, asect);
324
325  if (arg == NULL || *((char *) arg) == '\0'
326      || match_substring ((char *) arg, name)
327      || match_bfd_flags ((char *) arg, flags))
328    {
329      CORE_ADDR addr, endaddr;
330
331      addr = bfd_section_vma (abfd, asect);
332      endaddr = addr + bfd_section_size (abfd, asect);
333      maint_print_section_info (name, flags, addr, endaddr, asect->filepos);
334    }
335}
336
337static void
338print_objfile_section_info (bfd *abfd,
339			    struct obj_section *asect,
340			    char *string)
341{
342  flagword flags = bfd_get_section_flags (abfd, asect->the_bfd_section);
343  const char *name = bfd_section_name (abfd, asect->the_bfd_section);
344
345  if (string == NULL || *string == '\0'
346      || match_substring (string, name)
347      || match_bfd_flags (string, flags))
348    {
349      maint_print_section_info (name, flags, asect->addr, asect->endaddr,
350			  asect->the_bfd_section->filepos);
351    }
352}
353
354static void
355maintenance_info_sections (char *arg, int from_tty)
356{
357  if (exec_bfd)
358    {
359      printf_filtered ("Exec file:\n");
360      printf_filtered ("    `%s', ", bfd_get_filename (exec_bfd));
361      wrap_here ("        ");
362      printf_filtered ("file type %s.\n", bfd_get_target (exec_bfd));
363      if (arg && *arg && match_substring (arg, "ALLOBJ"))
364	{
365	  struct objfile *ofile;
366	  struct obj_section *osect;
367
368	  /* Only this function cares about the 'ALLOBJ' argument;
369	     if 'ALLOBJ' is the only argument, discard it rather than
370	     passing it down to print_objfile_section_info (which
371	     wouldn't know how to handle it).  */
372	  if (strcmp (arg, "ALLOBJ") == 0)
373	    arg = NULL;
374
375	  ALL_OBJFILES (ofile)
376	    {
377	      printf_filtered ("  Object file: %s\n",
378			       bfd_get_filename (ofile->obfd));
379	      ALL_OBJFILE_OSECTIONS (ofile, osect)
380		{
381		  print_objfile_section_info (ofile->obfd, osect, arg);
382		}
383	    }
384	}
385      else
386	bfd_map_over_sections (exec_bfd, print_bfd_section_info, arg);
387    }
388
389  if (core_bfd)
390    {
391      printf_filtered ("Core file:\n");
392      printf_filtered ("    `%s', ", bfd_get_filename (core_bfd));
393      wrap_here ("        ");
394      printf_filtered ("file type %s.\n", bfd_get_target (core_bfd));
395      bfd_map_over_sections (core_bfd, print_bfd_section_info, arg);
396    }
397}
398
399void
400maintenance_print_statistics (char *args, int from_tty)
401{
402  print_objfile_statistics ();
403  print_symbol_bcache_statistics ();
404}
405
406static void
407maintenance_print_architecture (char *args, int from_tty)
408{
409  if (args == NULL)
410    gdbarch_dump (current_gdbarch, gdb_stdout);
411  else
412    {
413      struct ui_file *file = gdb_fopen (args, "w");
414      if (file == NULL)
415	perror_with_name ("maintenance print architecture");
416      gdbarch_dump (current_gdbarch, file);
417      ui_file_delete (file);
418    }
419}
420
421/* The "maintenance print" command is defined as a prefix, with
422   allow_unknown 0.  Therefore, its own definition is called only for
423   "maintenance print" with no args.  */
424
425static void
426maintenance_print_command (char *arg, int from_tty)
427{
428  printf_unfiltered ("\"maintenance print\" must be followed by the name of a print command.\n");
429  help_list (maintenanceprintlist, "maintenance print ", -1, gdb_stdout);
430}
431
432/* The "maintenance translate-address" command converts a section and address
433   to a symbol.  This can be called in two ways:
434   maintenance translate-address <secname> <addr>
435   or   maintenance translate-address <addr>
436 */
437
438static void
439maintenance_translate_address (char *arg, int from_tty)
440{
441  CORE_ADDR address;
442  asection *sect;
443  char *p;
444  struct minimal_symbol *sym;
445  struct objfile *objfile;
446
447  if (arg == NULL || *arg == 0)
448    error ("requires argument (address or section + address)");
449
450  sect = NULL;
451  p = arg;
452
453  if (!isdigit (*p))
454    {				/* See if we have a valid section name */
455      while (*p && !isspace (*p))	/* Find end of section name */
456	p++;
457      if (*p == '\000')		/* End of command? */
458	error ("Need to specify <section-name> and <address>");
459      *p++ = '\000';
460      while (isspace (*p))
461	p++;			/* Skip whitespace */
462
463      ALL_OBJFILES (objfile)
464      {
465	sect = bfd_get_section_by_name (objfile->obfd, arg);
466	if (sect != NULL)
467	  break;
468      }
469
470      if (!sect)
471	error ("Unknown section %s.", arg);
472    }
473
474  address = parse_and_eval_address (p);
475
476  if (sect)
477    sym = lookup_minimal_symbol_by_pc_section (address, sect);
478  else
479    sym = lookup_minimal_symbol_by_pc (address);
480
481  if (sym)
482    printf_filtered ("%s+%s\n",
483		     SYMBOL_PRINT_NAME (sym),
484		     paddr_u (address - SYMBOL_VALUE_ADDRESS (sym)));
485  else if (sect)
486    printf_filtered ("no symbol at %s:0x%s\n", sect->name, paddr (address));
487  else
488    printf_filtered ("no symbol at 0x%s\n", paddr (address));
489
490  return;
491}
492
493
494/* When a command is deprecated the user will be warned the first time
495   the command is used.  If possible, a replacement will be
496   offered. */
497
498static void
499maintenance_deprecate (char *args, int from_tty)
500{
501  if (args == NULL || *args == '\0')
502    {
503      printf_unfiltered ("\"maintenance deprecate\" takes an argument, \n\
504the command you want to deprecate, and optionally the replacement command \n\
505enclosed in quotes.\n");
506    }
507
508  maintenance_do_deprecate (args, 1);
509
510}
511
512
513static void
514maintenance_undeprecate (char *args, int from_tty)
515{
516  if (args == NULL || *args == '\0')
517    {
518      printf_unfiltered ("\"maintenance undeprecate\" takes an argument, \n\
519the command you want to undeprecate.\n");
520    }
521
522  maintenance_do_deprecate (args, 0);
523
524}
525
526/* You really shouldn't be using this. It is just for the testsuite.
527   Rather, you should use deprecate_cmd() when the command is created
528   in _initialize_blah().
529
530   This function deprecates a command and optionally assigns it a
531   replacement.  */
532
533static void
534maintenance_do_deprecate (char *text, int deprecate)
535{
536
537  struct cmd_list_element *alias = NULL;
538  struct cmd_list_element *prefix_cmd = NULL;
539  struct cmd_list_element *cmd = NULL;
540
541  char *start_ptr = NULL;
542  char *end_ptr = NULL;
543  int len;
544  char *replacement = NULL;
545
546  if (text == NULL)
547    return;
548
549  if (!lookup_cmd_composition (text, &alias, &prefix_cmd, &cmd))
550    {
551      printf_filtered ("Can't find command '%s' to deprecate.\n", text);
552      return;
553    }
554
555  if (deprecate)
556    {
557      /* look for a replacement command */
558      start_ptr = strchr (text, '\"');
559      if (start_ptr != NULL)
560	{
561	  start_ptr++;
562	  end_ptr = strrchr (start_ptr, '\"');
563	  if (end_ptr != NULL)
564	    {
565	      len = end_ptr - start_ptr;
566	      start_ptr[len] = '\0';
567	      replacement = xstrdup (start_ptr);
568	    }
569	}
570    }
571
572  if (!start_ptr || !end_ptr)
573    replacement = NULL;
574
575
576  /* If they used an alias, we only want to deprecate the alias.
577
578     Note the MALLOCED_REPLACEMENT test.  If the command's replacement
579     string was allocated at compile time we don't want to free the
580     memory. */
581  if (alias)
582    {
583
584      if (alias->flags & MALLOCED_REPLACEMENT)
585	xfree (alias->replacement);
586
587      if (deprecate)
588	alias->flags |= (DEPRECATED_WARN_USER | CMD_DEPRECATED);
589      else
590	alias->flags &= ~(DEPRECATED_WARN_USER | CMD_DEPRECATED);
591      alias->replacement = replacement;
592      alias->flags |= MALLOCED_REPLACEMENT;
593      return;
594    }
595  else if (cmd)
596    {
597      if (cmd->flags & MALLOCED_REPLACEMENT)
598	xfree (cmd->replacement);
599
600      if (deprecate)
601	cmd->flags |= (DEPRECATED_WARN_USER | CMD_DEPRECATED);
602      else
603	cmd->flags &= ~(DEPRECATED_WARN_USER | CMD_DEPRECATED);
604      cmd->replacement = replacement;
605      cmd->flags |= MALLOCED_REPLACEMENT;
606      return;
607    }
608}
609
610/* Maintenance set/show framework.  */
611
612static struct cmd_list_element *maintenance_set_cmdlist;
613static struct cmd_list_element *maintenance_show_cmdlist;
614
615static void
616maintenance_set_cmd (char *args, int from_tty)
617{
618  printf_unfiltered ("\"maintenance set\" must be followed by the name of a set command.\n");
619  help_list (maintenance_set_cmdlist, "maintenance set ", -1, gdb_stdout);
620}
621
622static void
623maintenance_show_cmd (char *args, int from_tty)
624{
625  cmd_show_list (maintenance_show_cmdlist, from_tty, "");
626}
627
628/* Profiling support.  */
629
630static int maintenance_profile_p;
631
632#if defined (HAVE_MONSTARTUP) && defined (HAVE__MCLEANUP)
633
634#ifdef HAVE__ETEXT
635extern char _etext;
636#define TEXTEND &_etext
637#else
638extern char etext;
639#define TEXTEND &etext
640#endif
641
642static int profiling_state;
643
644static void
645mcleanup_wrapper (void)
646{
647  extern void _mcleanup (void);
648
649  if (profiling_state)
650    _mcleanup ();
651}
652
653static void
654maintenance_set_profile_cmd (char *args, int from_tty, struct cmd_list_element *c)
655{
656  if (maintenance_profile_p == profiling_state)
657    return;
658
659  profiling_state = maintenance_profile_p;
660
661  if (maintenance_profile_p)
662    {
663      static int profiling_initialized;
664
665      extern void monstartup (unsigned long, unsigned long);
666      extern int main();
667
668      if (!profiling_initialized)
669	{
670	  atexit (mcleanup_wrapper);
671	  profiling_initialized = 1;
672	}
673
674      /* "main" is now always the first function in the text segment, so use
675	 its address for monstartup.  */
676      monstartup ((unsigned long) &main, (unsigned long) TEXTEND);
677    }
678  else
679    {
680      extern void _mcleanup (void);
681      _mcleanup ();
682    }
683}
684#else
685static void
686maintenance_set_profile_cmd (char *args, int from_tty, struct cmd_list_element *c)
687{
688  error ("Profiling support is not available on this system.");
689}
690#endif
691
692void
693_initialize_maint_cmds (void)
694{
695  struct cmd_list_element *tmpcmd;
696
697  add_prefix_cmd ("maintenance", class_maintenance, maintenance_command,
698		  "Commands for use by GDB maintainers.\n\
699Includes commands to dump specific internal GDB structures in\n\
700a human readable form, to cause GDB to deliberately dump core,\n\
701to test internal functions such as the C++/ObjC demangler, etc.",
702		  &maintenancelist, "maintenance ", 0,
703		  &cmdlist);
704
705  add_com_alias ("mt", "maintenance", class_maintenance, 1);
706
707  add_prefix_cmd ("info", class_maintenance, maintenance_info_command,
708     "Commands for showing internal info about the program being debugged.",
709		  &maintenanceinfolist, "maintenance info ", 0,
710		  &maintenancelist);
711  add_alias_cmd ("i", "info", class_maintenance, 1, &maintenancelist);
712
713  add_cmd ("sections", class_maintenance, maintenance_info_sections,
714	   "List the BFD sections of the exec and core files. \n\
715Arguments may be any combination of:\n\
716	[one or more section names]\n\
717	ALLOC LOAD RELOC READONLY CODE DATA ROM CONSTRUCTOR\n\
718	HAS_CONTENTS NEVER_LOAD COFF_SHARED_LIBRARY IS_COMMON\n\
719Sections matching any argument will be listed (no argument\n\
720implies all sections).  In addition, the special argument\n\
721	ALLOBJ\n\
722lists all sections from all object files, including shared libraries.",
723	   &maintenanceinfolist);
724
725  add_prefix_cmd ("print", class_maintenance, maintenance_print_command,
726		  "Maintenance command for printing GDB internal state.",
727		  &maintenanceprintlist, "maintenance print ", 0,
728		  &maintenancelist);
729
730  add_prefix_cmd ("set", class_maintenance, maintenance_set_cmd, "\
731Set GDB internal variables used by the GDB maintainer.\n\
732Configure variables internal to GDB that aid in GDB's maintenance",
733		  &maintenance_set_cmdlist, "maintenance set ",
734		  0/*allow-unknown*/,
735		  &maintenancelist);
736
737  add_prefix_cmd ("show", class_maintenance, maintenance_show_cmd, "\
738Show GDB internal variables used by the GDB maintainer.\n\
739Configure variables internal to GDB that aid in GDB's maintenance",
740		  &maintenance_show_cmdlist, "maintenance show ",
741		  0/*allow-unknown*/,
742		  &maintenancelist);
743
744#ifndef _WIN32
745  add_cmd ("dump-me", class_maintenance, maintenance_dump_me,
746	   "Get fatal error; make debugger dump its core.\n\
747GDB sets its handling of SIGQUIT back to SIG_DFL and then sends\n\
748itself a SIGQUIT signal.",
749	   &maintenancelist);
750#endif
751
752  add_cmd ("internal-error", class_maintenance, maintenance_internal_error,
753	   "Give GDB an internal error.\n\
754Cause GDB to behave as if an internal error was detected.",
755	   &maintenancelist);
756
757  add_cmd ("internal-warning", class_maintenance, maintenance_internal_warning,
758	   "Give GDB an internal warning.\n\
759Cause GDB to behave as if an internal warning was reported.",
760	   &maintenancelist);
761
762  add_cmd ("demangle", class_maintenance, maintenance_demangle,
763	   "Demangle a C++/ObjC mangled name.\n\
764Call internal GDB demangler routine to demangle a C++ link name\n\
765and prints the result.",
766	   &maintenancelist);
767
768  add_cmd ("time", class_maintenance, maintenance_time_display,
769	   "Set the display of time usage.\n\
770If nonzero, will cause the execution time for each command to be\n\
771displayed, following the command's output.",
772	   &maintenancelist);
773
774  add_cmd ("space", class_maintenance, maintenance_space_display,
775	   "Set the display of space usage.\n\
776If nonzero, will cause the execution space for each command to be\n\
777displayed, following the command's output.",
778	   &maintenancelist);
779
780  add_cmd ("type", class_maintenance, maintenance_print_type,
781	   "Print a type chain for a given symbol.\n\
782For each node in a type chain, print the raw data for each member of\n\
783the type structure, and the interpretation of the data.",
784	   &maintenanceprintlist);
785
786  add_cmd ("symbols", class_maintenance, maintenance_print_symbols,
787	   "Print dump of current symbol definitions.\n\
788Entries in the full symbol table are dumped to file OUTFILE.\n\
789If a SOURCE file is specified, dump only that file's symbols.",
790	   &maintenanceprintlist);
791
792  add_cmd ("msymbols", class_maintenance, maintenance_print_msymbols,
793	   "Print dump of current minimal symbol definitions.\n\
794Entries in the minimal symbol table are dumped to file OUTFILE.\n\
795If a SOURCE file is specified, dump only that file's minimal symbols.",
796	   &maintenanceprintlist);
797
798  add_cmd ("psymbols", class_maintenance, maintenance_print_psymbols,
799	   "Print dump of current partial symbol definitions.\n\
800Entries in the partial symbol table are dumped to file OUTFILE.\n\
801If a SOURCE file is specified, dump only that file's partial symbols.",
802	   &maintenanceprintlist);
803
804  add_cmd ("objfiles", class_maintenance, maintenance_print_objfiles,
805	   "Print dump of current object file definitions.",
806	   &maintenanceprintlist);
807
808  add_cmd ("symtabs", class_maintenance, maintenance_info_symtabs,
809	   "List the full symbol tables for all object files.\n\
810This does not include information about individual symbols, blocks, or\n\
811linetables --- just the symbol table structures themselves.\n\
812With an argument REGEXP, list the symbol tables whose names that match that.",
813	   &maintenanceinfolist);
814
815  add_cmd ("psymtabs", class_maintenance, maintenance_info_psymtabs,
816	   "List the partial symbol tables for all object files.\n\
817This does not include information about individual partial symbols,\n\
818just the symbol table structures themselves.",
819	   &maintenanceinfolist);
820
821  add_cmd ("statistics", class_maintenance, maintenance_print_statistics,
822	   "Print statistics about internal gdb state.",
823	   &maintenanceprintlist);
824
825  add_cmd ("architecture", class_maintenance, maintenance_print_architecture,
826	   "Print the internal architecture configuration.\
827Takes an optional file parameter.",
828	   &maintenanceprintlist);
829
830  add_cmd ("check-symtabs", class_maintenance, maintenance_check_symtabs,
831	   "Check consistency of psymtabs and symtabs.",
832	   &maintenancelist);
833
834  add_cmd ("translate-address", class_maintenance, maintenance_translate_address,
835	   "Translate a section name and address to a symbol.",
836	   &maintenancelist);
837
838  add_cmd ("deprecate", class_maintenance, maintenance_deprecate,
839	   "Deprecate a command.  Note that this is just in here so the \n\
840testsuite can check the comamnd deprecator. You probably shouldn't use this,\n\
841rather you should use the C function deprecate_cmd().  If you decide you \n\
842want to use it: maintenance deprecate 'commandname' \"replacement\". The \n\
843replacement is optional.", &maintenancelist);
844
845  add_cmd ("undeprecate", class_maintenance, maintenance_undeprecate,
846	   "Undeprecate a command.  Note that this is just in here so the \n\
847testsuite can check the comamnd deprecator. You probably shouldn't use this,\n\
848If you decide you want to use it: maintenance undeprecate 'commandname'",
849	   &maintenancelist);
850
851  add_show_from_set (
852		      add_set_cmd ("watchdog", class_maintenance, var_zinteger, (char *) &watchdog,
853				   "Set watchdog timer.\n\
854When non-zero, this timeout is used instead of waiting forever for a target to\n\
855finish a low-level step or continue operation.  If the specified amount of time\n\
856passes without a response from the target, an error occurs.", &setlist),
857		      &showlist);
858
859
860  add_setshow_boolean_cmd ("profile", class_maintenance,
861			   &maintenance_profile_p,
862			   "Set internal profiling.\n"
863			   "When enabled GDB is profiled.",
864			   "Show internal profiling.\n",
865			   maintenance_set_profile_cmd, NULL,
866			   &maintenance_set_cmdlist,
867			   &maintenance_show_cmdlist);
868}
869