GDB (API)
/home/stan/gdb/src/gdb/maint.c
Go to the documentation of this file.
00001 /* Support for GDB maintenance commands.
00002 
00003    Copyright (C) 1992-2013 Free Software Foundation, Inc.
00004 
00005    Written by Fred Fish at Cygnus Support.
00006 
00007    This file is part of GDB.
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 3 of the License, or
00012    (at your option) any later version.
00013 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00021 
00022 
00023 #include "defs.h"
00024 #include "arch-utils.h"
00025 #include <ctype.h>
00026 #include <signal.h>
00027 #include <sys/time.h>
00028 #include <time.h>
00029 #include "command.h"
00030 #include "gdbcmd.h"
00031 #include "symtab.h"
00032 #include "block.h"
00033 #include "gdbtypes.h"
00034 #include "demangle.h"
00035 #include "gdbcore.h"
00036 #include "expression.h"         /* For language.h */
00037 #include "language.h"
00038 #include "symfile.h"
00039 #include "objfiles.h"
00040 #include "value.h"
00041 #include "gdb_assert.h"
00042 #include "top.h"
00043 #include "timeval-utils.h"
00044 #include "maint.h"
00045 
00046 #include "cli/cli-decode.h"
00047 #include "cli/cli-utils.h"
00048 #include "cli/cli-setshow.h"
00049 
00050 extern void _initialize_maint_cmds (void);
00051 
00052 static void maintenance_command (char *, int);
00053 
00054 static void maintenance_internal_error (char *args, int from_tty);
00055 
00056 static void maintenance_demangle (char *, int);
00057 
00058 static void maintenance_time_display (char *, int);
00059 
00060 static void maintenance_space_display (char *, int);
00061 
00062 static void maintenance_info_command (char *, int);
00063 
00064 static void maintenance_info_sections (char *, int);
00065 
00066 static void maintenance_print_command (char *, int);
00067 
00068 static void maintenance_do_deprecate (char *, int);
00069 
00070 /* Set this to the maximum number of seconds to wait instead of waiting forever
00071    in target_wait().  If this timer times out, then it generates an error and
00072    the command is aborted.  This replaces most of the need for timeouts in the
00073    GDB test suite, and makes it possible to distinguish between a hung target
00074    and one with slow communications.  */
00075 
00076 int watchdog = 0;
00077 static void
00078 show_watchdog (struct ui_file *file, int from_tty,
00079                struct cmd_list_element *c, const char *value)
00080 {
00081   fprintf_filtered (file, _("Watchdog timer is %s.\n"), value);
00082 }
00083 
00084 /* Access the maintenance subcommands.  */
00085 
00086 static void
00087 maintenance_command (char *args, int from_tty)
00088 {
00089   printf_unfiltered (_("\"maintenance\" must be followed by "
00090                        "the name of a maintenance command.\n"));
00091   help_list (maintenancelist, "maintenance ", -1, gdb_stdout);
00092 }
00093 
00094 #ifndef _WIN32
00095 static void
00096 maintenance_dump_me (char *args, int from_tty)
00097 {
00098   if (query (_("Should GDB dump core? ")))
00099     {
00100 #ifdef __DJGPP__
00101       /* SIGQUIT by default is ignored, so use SIGABRT instead.  */
00102       signal (SIGABRT, SIG_DFL);
00103       kill (getpid (), SIGABRT);
00104 #else
00105       signal (SIGQUIT, SIG_DFL);
00106       kill (getpid (), SIGQUIT);
00107 #endif
00108     }
00109 }
00110 #endif
00111 
00112 /* Stimulate the internal error mechanism that GDB uses when an
00113    internal problem is detected.  Allows testing of the mechanism.
00114    Also useful when the user wants to drop a core file but not exit
00115    GDB.  */
00116 
00117 static void
00118 maintenance_internal_error (char *args, int from_tty)
00119 {
00120   internal_error (__FILE__, __LINE__, "%s", (args == NULL ? "" : args));
00121 }
00122 
00123 /* Stimulate the internal error mechanism that GDB uses when an
00124    internal problem is detected.  Allows testing of the mechanism.
00125    Also useful when the user wants to drop a core file but not exit
00126    GDB.  */
00127 
00128 static void
00129 maintenance_internal_warning (char *args, int from_tty)
00130 {
00131   internal_warning (__FILE__, __LINE__, "%s", (args == NULL ? "" : args));
00132 }
00133 
00134 /* Someday we should allow demangling for things other than just
00135    explicit strings.  For example, we might want to be able to specify
00136    the address of a string in either GDB's process space or the
00137    debuggee's process space, and have gdb fetch and demangle that
00138    string.  If we have a char* pointer "ptr" that points to a string,
00139    we might want to be able to given just the name and have GDB
00140    demangle and print what it points to, etc.  (FIXME)  */
00141 
00142 static void
00143 maintenance_demangle (char *args, int from_tty)
00144 {
00145   char *demangled;
00146 
00147   if (args == NULL || *args == '\0')
00148     {
00149       printf_unfiltered (_("\"maintenance demangle\" takes "
00150                            "an argument to demangle.\n"));
00151     }
00152   else
00153     {
00154       demangled = language_demangle (current_language, args, 
00155                                      DMGL_ANSI | DMGL_PARAMS);
00156       if (demangled != NULL)
00157         {
00158           printf_unfiltered ("%s\n", demangled);
00159           xfree (demangled);
00160         }
00161       else
00162         {
00163           printf_unfiltered (_("Can't demangle \"%s\"\n"), args);
00164         }
00165     }
00166 }
00167 
00168 static void
00169 maintenance_time_display (char *args, int from_tty)
00170 {
00171   if (args == NULL || *args == '\0')
00172     printf_unfiltered (_("\"maintenance time\" takes a numeric argument.\n"));
00173   else
00174     set_per_command_time (strtol (args, NULL, 10));
00175 }
00176 
00177 static void
00178 maintenance_space_display (char *args, int from_tty)
00179 {
00180   if (args == NULL || *args == '\0')
00181     printf_unfiltered ("\"maintenance space\" takes a numeric argument.\n");
00182   else
00183     set_per_command_space (strtol (args, NULL, 10));
00184 }
00185 
00186 /* The "maintenance info" command is defined as a prefix, with
00187    allow_unknown 0.  Therefore, its own definition is called only for
00188    "maintenance info" with no args.  */
00189 
00190 static void
00191 maintenance_info_command (char *arg, int from_tty)
00192 {
00193   printf_unfiltered (_("\"maintenance info\" must be followed "
00194                        "by the name of an info command.\n"));
00195   help_list (maintenanceinfolist, "maintenance info ", -1, gdb_stdout);
00196 }
00197 
00198 /* Mini tokenizing lexer for 'maint info sections' command.  */
00199 
00200 static int
00201 match_substring (const char *string, const char *substr)
00202 {
00203   int substr_len = strlen(substr);
00204   const char *tok;
00205 
00206   while ((tok = strstr (string, substr)) != NULL)
00207     {
00208       /* Got a partial match.  Is it a whole word?  */
00209       if (tok == string
00210           || tok[-1] == ' '
00211           || tok[-1] == '\t')
00212       {
00213         /* Token is delimited at the front...  */
00214         if (tok[substr_len] == ' '
00215             || tok[substr_len] == '\t'
00216             || tok[substr_len] == '\0')
00217         {
00218           /* Token is delimited at the rear.  Got a whole-word match.  */
00219           return 1;
00220         }
00221       }
00222       /* Token didn't match as a whole word.  Advance and try again.  */
00223       string = tok + 1;
00224     }
00225   return 0;
00226 }
00227 
00228 static int 
00229 match_bfd_flags (char *string, flagword flags)
00230 {
00231   if (flags & SEC_ALLOC)
00232     if (match_substring (string, "ALLOC"))
00233       return 1;
00234   if (flags & SEC_LOAD)
00235     if (match_substring (string, "LOAD"))
00236       return 1;
00237   if (flags & SEC_RELOC)
00238     if (match_substring (string, "RELOC"))
00239       return 1;
00240   if (flags & SEC_READONLY)
00241     if (match_substring (string, "READONLY"))
00242       return 1;
00243   if (flags & SEC_CODE)
00244     if (match_substring (string, "CODE"))
00245       return 1;
00246   if (flags & SEC_DATA)
00247     if (match_substring (string, "DATA"))
00248       return 1;
00249   if (flags & SEC_ROM)
00250     if (match_substring (string, "ROM"))
00251       return 1;
00252   if (flags & SEC_CONSTRUCTOR)
00253     if (match_substring (string, "CONSTRUCTOR"))
00254       return 1;
00255   if (flags & SEC_HAS_CONTENTS)
00256     if (match_substring (string, "HAS_CONTENTS"))
00257       return 1;
00258   if (flags & SEC_NEVER_LOAD)
00259     if (match_substring (string, "NEVER_LOAD"))
00260       return 1;
00261   if (flags & SEC_COFF_SHARED_LIBRARY)
00262     if (match_substring (string, "COFF_SHARED_LIBRARY"))
00263       return 1;
00264   if (flags & SEC_IS_COMMON)
00265     if (match_substring (string, "IS_COMMON"))
00266       return 1;
00267 
00268   return 0;
00269 }
00270 
00271 static void
00272 print_bfd_flags (flagword flags)
00273 {
00274   if (flags & SEC_ALLOC)
00275     printf_filtered (" ALLOC");
00276   if (flags & SEC_LOAD)
00277     printf_filtered (" LOAD");
00278   if (flags & SEC_RELOC)
00279     printf_filtered (" RELOC");
00280   if (flags & SEC_READONLY)
00281     printf_filtered (" READONLY");
00282   if (flags & SEC_CODE)
00283     printf_filtered (" CODE");
00284   if (flags & SEC_DATA)
00285     printf_filtered (" DATA");
00286   if (flags & SEC_ROM)
00287     printf_filtered (" ROM");
00288   if (flags & SEC_CONSTRUCTOR)
00289     printf_filtered (" CONSTRUCTOR");
00290   if (flags & SEC_HAS_CONTENTS)
00291     printf_filtered (" HAS_CONTENTS");
00292   if (flags & SEC_NEVER_LOAD)
00293     printf_filtered (" NEVER_LOAD");
00294   if (flags & SEC_COFF_SHARED_LIBRARY)
00295     printf_filtered (" COFF_SHARED_LIBRARY");
00296   if (flags & SEC_IS_COMMON)
00297     printf_filtered (" IS_COMMON");
00298 }
00299 
00300 static void
00301 maint_print_section_info (const char *name, flagword flags, 
00302                           CORE_ADDR addr, CORE_ADDR endaddr, 
00303                           unsigned long filepos, int addr_size)
00304 {
00305   printf_filtered ("    %s", hex_string_custom (addr, addr_size));
00306   printf_filtered ("->%s", hex_string_custom (endaddr, addr_size));
00307   printf_filtered (" at %s",
00308                    hex_string_custom ((unsigned long) filepos, 8));
00309   printf_filtered (": %s", name);
00310   print_bfd_flags (flags);
00311   printf_filtered ("\n");
00312 }
00313 
00314 static void
00315 print_bfd_section_info (bfd *abfd, 
00316                         asection *asect, 
00317                         void *arg)
00318 {
00319   flagword flags = bfd_get_section_flags (abfd, asect);
00320   const char *name = bfd_section_name (abfd, asect);
00321 
00322   if (arg == NULL || *((char *) arg) == '\0'
00323       || match_substring ((char *) arg, name)
00324       || match_bfd_flags ((char *) arg, flags))
00325     {
00326       struct gdbarch *gdbarch = gdbarch_from_bfd (abfd);
00327       int addr_size = gdbarch_addr_bit (gdbarch) / 8;
00328       CORE_ADDR addr, endaddr;
00329 
00330       addr = bfd_section_vma (abfd, asect);
00331       endaddr = addr + bfd_section_size (abfd, asect);
00332       printf_filtered (" [%d] ", gdb_bfd_section_index (abfd, asect));
00333       maint_print_section_info (name, flags, addr, endaddr,
00334                                 asect->filepos, addr_size);
00335     }
00336 }
00337 
00338 static void
00339 print_objfile_section_info (bfd *abfd, 
00340                             struct obj_section *asect, 
00341                             char *string)
00342 {
00343   flagword flags = bfd_get_section_flags (abfd, asect->the_bfd_section);
00344   const char *name = bfd_section_name (abfd, asect->the_bfd_section);
00345 
00346   if (string == NULL || *string == '\0'
00347       || match_substring (string, name)
00348       || match_bfd_flags (string, flags))
00349     {
00350       struct gdbarch *gdbarch = gdbarch_from_bfd (abfd);
00351       int addr_size = gdbarch_addr_bit (gdbarch) / 8;
00352 
00353       maint_print_section_info (name, flags,
00354                                 obj_section_addr (asect),
00355                                 obj_section_endaddr (asect),
00356                                 asect->the_bfd_section->filepos,
00357                                 addr_size);
00358     }
00359 }
00360 
00361 static void
00362 maintenance_info_sections (char *arg, int from_tty)
00363 {
00364   if (exec_bfd)
00365     {
00366       printf_filtered (_("Exec file:\n"));
00367       printf_filtered ("    `%s', ", bfd_get_filename (exec_bfd));
00368       wrap_here ("        ");
00369       printf_filtered (_("file type %s.\n"), bfd_get_target (exec_bfd));
00370       if (arg && *arg && match_substring (arg, "ALLOBJ"))
00371         {
00372           struct objfile *ofile;
00373           struct obj_section *osect;
00374 
00375           /* Only this function cares about the 'ALLOBJ' argument; 
00376              if 'ALLOBJ' is the only argument, discard it rather than
00377              passing it down to print_objfile_section_info (which 
00378              wouldn't know how to handle it).  */
00379           if (strcmp (arg, "ALLOBJ") == 0)
00380             arg = NULL;
00381 
00382           ALL_OBJFILES (ofile)
00383             {
00384               printf_filtered (_("  Object file: %s\n"), 
00385                                bfd_get_filename (ofile->obfd));
00386               ALL_OBJFILE_OSECTIONS (ofile, osect)
00387                 {
00388                   print_objfile_section_info (ofile->obfd, osect, arg);
00389                 }
00390             }
00391         }
00392       else 
00393         bfd_map_over_sections (exec_bfd, print_bfd_section_info, arg);
00394     }
00395 
00396   if (core_bfd)
00397     {
00398       printf_filtered (_("Core file:\n"));
00399       printf_filtered ("    `%s', ", bfd_get_filename (core_bfd));
00400       wrap_here ("        ");
00401       printf_filtered (_("file type %s.\n"), bfd_get_target (core_bfd));
00402       bfd_map_over_sections (core_bfd, print_bfd_section_info, arg);
00403     }
00404 }
00405 
00406 static void
00407 maintenance_print_statistics (char *args, int from_tty)
00408 {
00409   print_objfile_statistics ();
00410   print_symbol_bcache_statistics ();
00411 }
00412 
00413 static void
00414 maintenance_print_architecture (char *args, int from_tty)
00415 {
00416   struct gdbarch *gdbarch = get_current_arch ();
00417 
00418   if (args == NULL)
00419     gdbarch_dump (gdbarch, gdb_stdout);
00420   else
00421     {
00422       struct cleanup *cleanups;
00423       struct ui_file *file = gdb_fopen (args, "w");
00424 
00425       if (file == NULL)
00426         perror_with_name (_("maintenance print architecture"));
00427       cleanups = make_cleanup_ui_file_delete (file);
00428       gdbarch_dump (gdbarch, file);
00429       do_cleanups (cleanups);
00430     }
00431 }
00432 
00433 /* The "maintenance print" command is defined as a prefix, with
00434    allow_unknown 0.  Therefore, its own definition is called only for
00435    "maintenance print" with no args.  */
00436 
00437 static void
00438 maintenance_print_command (char *arg, int from_tty)
00439 {
00440   printf_unfiltered (_("\"maintenance print\" must be followed "
00441                        "by the name of a print command.\n"));
00442   help_list (maintenanceprintlist, "maintenance print ", -1, gdb_stdout);
00443 }
00444 
00445 /* The "maintenance translate-address" command converts a section and address
00446    to a symbol.  This can be called in two ways:
00447    maintenance translate-address <secname> <addr>
00448    or   maintenance translate-address <addr>.  */
00449 
00450 static void
00451 maintenance_translate_address (char *arg, int from_tty)
00452 {
00453   CORE_ADDR address;
00454   struct obj_section *sect;
00455   char *p;
00456   struct bound_minimal_symbol sym;
00457   struct objfile *objfile;
00458 
00459   if (arg == NULL || *arg == 0)
00460     error (_("requires argument (address or section + address)"));
00461 
00462   sect = NULL;
00463   p = arg;
00464 
00465   if (!isdigit (*p))
00466     {                           /* See if we have a valid section name.  */
00467       while (*p && !isspace (*p))       /* Find end of section name.  */
00468         p++;
00469       if (*p == '\000')         /* End of command?  */
00470         error (_("Need to specify <section-name> and <address>"));
00471       *p++ = '\000';
00472       p = skip_spaces (p);
00473 
00474       ALL_OBJSECTIONS (objfile, sect)
00475       {
00476         if (strcmp (sect->the_bfd_section->name, arg) == 0)
00477           break;
00478       }
00479 
00480       if (!objfile)
00481         error (_("Unknown section %s."), arg);
00482     }
00483 
00484   address = parse_and_eval_address (p);
00485 
00486   if (sect)
00487     sym = lookup_minimal_symbol_by_pc_section (address, sect);
00488   else
00489     sym = lookup_minimal_symbol_by_pc (address);
00490 
00491   if (sym.minsym)
00492     {
00493       const char *symbol_name = SYMBOL_PRINT_NAME (sym.minsym);
00494       const char *symbol_offset
00495         = pulongest (address - SYMBOL_VALUE_ADDRESS (sym.minsym));
00496 
00497       sect = SYMBOL_OBJ_SECTION(sym.objfile, sym.minsym);
00498       if (sect != NULL)
00499         {
00500           const char *section_name;
00501           const char *obj_name;
00502 
00503           gdb_assert (sect->the_bfd_section && sect->the_bfd_section->name);
00504           section_name = sect->the_bfd_section->name;
00505 
00506           gdb_assert (sect->objfile && objfile_name (sect->objfile));
00507           obj_name = objfile_name (sect->objfile);
00508 
00509           if (MULTI_OBJFILE_P ())
00510             printf_filtered (_("%s + %s in section %s of %s\n"),
00511                              symbol_name, symbol_offset,
00512                              section_name, obj_name);
00513           else
00514             printf_filtered (_("%s + %s in section %s\n"),
00515                              symbol_name, symbol_offset, section_name);
00516         }
00517       else
00518         printf_filtered (_("%s + %s\n"), symbol_name, symbol_offset);
00519     }
00520   else if (sect)
00521     printf_filtered (_("no symbol at %s:%s\n"),
00522                      sect->the_bfd_section->name, hex_string (address));
00523   else
00524     printf_filtered (_("no symbol at %s\n"), hex_string (address));
00525 
00526   return;
00527 }
00528 
00529 
00530 /* When a command is deprecated the user will be warned the first time
00531    the command is used.  If possible, a replacement will be
00532    offered.  */
00533 
00534 static void
00535 maintenance_deprecate (char *args, int from_tty)
00536 {
00537   if (args == NULL || *args == '\0')
00538     {
00539       printf_unfiltered (_("\"maintenance deprecate\" takes an argument,\n\
00540 the command you want to deprecate, and optionally the replacement command\n\
00541 enclosed in quotes.\n"));
00542     }
00543 
00544   maintenance_do_deprecate (args, 1);
00545 
00546 }
00547 
00548 
00549 static void
00550 maintenance_undeprecate (char *args, int from_tty)
00551 {
00552   if (args == NULL || *args == '\0')
00553     {
00554       printf_unfiltered (_("\"maintenance undeprecate\" takes an argument, \n\
00555 the command you want to undeprecate.\n"));
00556     }
00557 
00558   maintenance_do_deprecate (args, 0);
00559 
00560 }
00561 
00562 /* You really shouldn't be using this.  It is just for the testsuite.
00563    Rather, you should use deprecate_cmd() when the command is created
00564    in _initialize_blah().
00565 
00566    This function deprecates a command and optionally assigns it a
00567    replacement.  */
00568 
00569 static void
00570 maintenance_do_deprecate (char *text, int deprecate)
00571 {
00572   struct cmd_list_element *alias = NULL;
00573   struct cmd_list_element *prefix_cmd = NULL;
00574   struct cmd_list_element *cmd = NULL;
00575 
00576   char *start_ptr = NULL;
00577   char *end_ptr = NULL;
00578   int len;
00579   char *replacement = NULL;
00580 
00581   if (text == NULL)
00582     return;
00583 
00584   if (!lookup_cmd_composition (text, &alias, &prefix_cmd, &cmd))
00585     {
00586       printf_filtered (_("Can't find command '%s' to deprecate.\n"), text);
00587       return;
00588     }
00589 
00590   if (deprecate)
00591     {
00592       /* Look for a replacement command.  */
00593       start_ptr = strchr (text, '\"');
00594       if (start_ptr != NULL)
00595         {
00596           start_ptr++;
00597           end_ptr = strrchr (start_ptr, '\"');
00598           if (end_ptr != NULL)
00599             {
00600               len = end_ptr - start_ptr;
00601               start_ptr[len] = '\0';
00602               replacement = xstrdup (start_ptr);
00603             }
00604         }
00605     }
00606 
00607   if (!start_ptr || !end_ptr)
00608     replacement = NULL;
00609 
00610 
00611   /* If they used an alias, we only want to deprecate the alias.
00612 
00613      Note the MALLOCED_REPLACEMENT test.  If the command's replacement
00614      string was allocated at compile time we don't want to free the
00615      memory.  */
00616   if (alias)
00617     {
00618       if (alias->flags & MALLOCED_REPLACEMENT)
00619         xfree (alias->replacement);
00620 
00621       if (deprecate)
00622         alias->flags |= (DEPRECATED_WARN_USER | CMD_DEPRECATED);
00623       else
00624         alias->flags &= ~(DEPRECATED_WARN_USER | CMD_DEPRECATED);
00625       alias->replacement = replacement;
00626       alias->flags |= MALLOCED_REPLACEMENT;
00627       return;
00628     }
00629   else if (cmd)
00630     {
00631       if (cmd->flags & MALLOCED_REPLACEMENT)
00632         xfree (cmd->replacement);
00633 
00634       if (deprecate)
00635         cmd->flags |= (DEPRECATED_WARN_USER | CMD_DEPRECATED);
00636       else
00637         cmd->flags &= ~(DEPRECATED_WARN_USER | CMD_DEPRECATED);
00638       cmd->replacement = replacement;
00639       cmd->flags |= MALLOCED_REPLACEMENT;
00640       return;
00641     }
00642   xfree (replacement);
00643 }
00644 
00645 /* Maintenance set/show framework.  */
00646 
00647 struct cmd_list_element *maintenance_set_cmdlist;
00648 struct cmd_list_element *maintenance_show_cmdlist;
00649 
00650 static void
00651 maintenance_set_cmd (char *args, int from_tty)
00652 {
00653   printf_unfiltered (_("\"maintenance set\" must be followed "
00654                        "by the name of a set command.\n"));
00655   help_list (maintenance_set_cmdlist, "maintenance set ", -1, gdb_stdout);
00656 }
00657 
00658 static void
00659 maintenance_show_cmd (char *args, int from_tty)
00660 {
00661   cmd_show_list (maintenance_show_cmdlist, from_tty, "");
00662 }
00663 
00664 /* Profiling support.  */
00665 
00666 static int maintenance_profile_p;
00667 static void
00668 show_maintenance_profile_p (struct ui_file *file, int from_tty,
00669                             struct cmd_list_element *c, const char *value)
00670 {
00671   fprintf_filtered (file, _("Internal profiling is %s.\n"), value);
00672 }
00673 
00674 #ifdef HAVE__ETEXT
00675 extern char _etext;
00676 #define TEXTEND &_etext
00677 #elif defined (HAVE_ETEXT)
00678 extern char etext;
00679 #define TEXTEND &etext
00680 #endif
00681 
00682 #if defined (HAVE_MONSTARTUP) && defined (HAVE__MCLEANUP) && defined (TEXTEND)
00683 
00684 static int profiling_state;
00685 
00686 static void
00687 mcleanup_wrapper (void)
00688 {
00689   extern void _mcleanup (void);
00690 
00691   if (profiling_state)
00692     _mcleanup ();
00693 }
00694 
00695 static void
00696 maintenance_set_profile_cmd (char *args, int from_tty,
00697                              struct cmd_list_element *c)
00698 {
00699   if (maintenance_profile_p == profiling_state)
00700     return;
00701 
00702   profiling_state = maintenance_profile_p;
00703 
00704   if (maintenance_profile_p)
00705     {
00706       static int profiling_initialized;
00707 
00708       extern void monstartup (unsigned long, unsigned long);
00709       extern int main();
00710 
00711       if (!profiling_initialized)
00712         {
00713           atexit (mcleanup_wrapper);
00714           profiling_initialized = 1;
00715         }
00716 
00717       /* "main" is now always the first function in the text segment, so use
00718          its address for monstartup.  */
00719       monstartup ((unsigned long) &main, (unsigned long) TEXTEND);
00720     }
00721   else
00722     {
00723       extern void _mcleanup (void);
00724 
00725       _mcleanup ();
00726     }
00727 }
00728 #else
00729 static void
00730 maintenance_set_profile_cmd (char *args, int from_tty,
00731                              struct cmd_list_element *c)
00732 {
00733   error (_("Profiling support is not available on this system."));
00734 }
00735 #endif
00736 
00737 /* If nonzero, display time usage both at startup and for each command.  */
00738 
00739 static int per_command_time;
00740 
00741 /* If nonzero, display space usage both at startup and for each command.  */
00742 
00743 static int per_command_space;
00744 
00745 /* If nonzero, display basic symtab stats for each command.  */
00746 
00747 static int per_command_symtab;
00748 
00749 /* mt per-command commands.  */
00750 
00751 static struct cmd_list_element *per_command_setlist;
00752 static struct cmd_list_element *per_command_showlist;
00753 
00754 /* Records a run time and space usage to be used as a base for
00755    reporting elapsed time or change in space.  */
00756 
00757 struct cmd_stats 
00758 {
00759   /* Zero if the saved time is from the beginning of GDB execution.
00760      One if from the beginning of an individual command execution.  */
00761   int msg_type;
00762   /* Track whether the stat was enabled at the start of the command
00763      so that we can avoid printing anything if it gets turned on by
00764      the current command.  */
00765   int time_enabled : 1;
00766   int space_enabled : 1;
00767   int symtab_enabled : 1;
00768   long start_cpu_time;
00769   struct timeval start_wall_time;
00770   long start_space;
00771   /* Total number of symtabs (over all objfiles).  */
00772   int start_nr_symtabs;
00773   /* Of those, a count of just the primary ones.  */
00774   int start_nr_primary_symtabs;
00775   /* Total number of blocks.  */
00776   int start_nr_blocks;
00777 };
00778 
00779 /* Set whether to display time statistics to NEW_VALUE
00780    (non-zero means true).  */
00781 
00782 void
00783 set_per_command_time (int new_value)
00784 {
00785   per_command_time = new_value;
00786 }
00787 
00788 /* Set whether to display space statistics to NEW_VALUE
00789    (non-zero means true).  */
00790 
00791 void
00792 set_per_command_space (int new_value)
00793 {
00794   per_command_space = new_value;
00795 }
00796 
00797 /* Count the number of symtabs and blocks.  */
00798 
00799 static void
00800 count_symtabs_and_blocks (int *nr_symtabs_ptr, int *nr_primary_symtabs_ptr,
00801                           int *nr_blocks_ptr)
00802 {
00803   struct objfile *o;
00804   struct symtab *s;
00805   int nr_symtabs = 0;
00806   int nr_primary_symtabs = 0;
00807   int nr_blocks = 0;
00808 
00809   ALL_SYMTABS (o, s)
00810     {
00811       ++nr_symtabs;
00812       if (s->primary)
00813         {
00814           ++nr_primary_symtabs;
00815           nr_blocks += BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (s));
00816         }
00817     }
00818 
00819   *nr_symtabs_ptr = nr_symtabs;
00820   *nr_primary_symtabs_ptr = nr_primary_symtabs;
00821   *nr_blocks_ptr = nr_blocks;
00822 }
00823 
00824 /* As indicated by display_time and display_space, report GDB's elapsed time
00825    and space usage from the base time and space provided in ARG, which
00826    must be a pointer to a struct cmd_stat.  This function is intended
00827    to be called as a cleanup.  */
00828 
00829 static void
00830 report_command_stats (void *arg)
00831 {
00832   struct cmd_stats *start_stats = (struct cmd_stats *) arg;
00833   int msg_type = start_stats->msg_type;
00834 
00835   if (start_stats->time_enabled)
00836     {
00837       long cmd_time = get_run_time () - start_stats->start_cpu_time;
00838       struct timeval now_wall_time, delta_wall_time, wait_time;
00839 
00840       gettimeofday (&now_wall_time, NULL);
00841       timeval_sub (&delta_wall_time,
00842                    &now_wall_time, &start_stats->start_wall_time);
00843 
00844       /* Subtract time spend in prompt_for_continue from walltime.  */
00845       wait_time = get_prompt_for_continue_wait_time ();
00846       timeval_sub (&delta_wall_time, &delta_wall_time, &wait_time);
00847 
00848       printf_unfiltered (msg_type == 0
00849                          ? _("Startup time: %ld.%06ld (cpu), %ld.%06ld (wall)\n")
00850                          : _("Command execution time: %ld.%06ld (cpu), %ld.%06ld (wall)\n"),
00851                          cmd_time / 1000000, cmd_time % 1000000,
00852                          (long) delta_wall_time.tv_sec,
00853                          (long) delta_wall_time.tv_usec);
00854     }
00855 
00856   if (start_stats->space_enabled)
00857     {
00858 #ifdef HAVE_SBRK
00859       char *lim = (char *) sbrk (0);
00860 
00861       long space_now = lim - lim_at_start;
00862       long space_diff = space_now - start_stats->start_space;
00863 
00864       printf_unfiltered (msg_type == 0
00865                          ? _("Space used: %ld (%s%ld during startup)\n")
00866                          : _("Space used: %ld (%s%ld for this command)\n"),
00867                          space_now,
00868                          (space_diff >= 0 ? "+" : ""),
00869                          space_diff);
00870 #endif
00871     }
00872 
00873   if (start_stats->symtab_enabled)
00874     {
00875       int nr_symtabs, nr_primary_symtabs, nr_blocks;
00876 
00877       count_symtabs_and_blocks (&nr_symtabs, &nr_primary_symtabs, &nr_blocks);
00878       printf_unfiltered (_("#symtabs: %d (+%d),"
00879                            " #primary symtabs: %d (+%d),"
00880                            " #blocks: %d (+%d)\n"),
00881                          nr_symtabs,
00882                          nr_symtabs - start_stats->start_nr_symtabs,
00883                          nr_primary_symtabs,
00884                          nr_primary_symtabs - start_stats->start_nr_primary_symtabs,
00885                          nr_blocks,
00886                          nr_blocks - start_stats->start_nr_blocks);
00887     }
00888 }
00889 
00890 /* Create a cleanup that reports time and space used since its creation.
00891    MSG_TYPE is zero for gdb startup, otherwise it is one(1) to report
00892    data for individual commands.  */
00893 
00894 struct cleanup *
00895 make_command_stats_cleanup (int msg_type)
00896 {
00897   struct cmd_stats *new_stat;
00898 
00899   /* Early exit if we're not reporting any stats.  */
00900   if (!per_command_time
00901       && !per_command_space
00902       && !per_command_symtab)
00903     return make_cleanup (null_cleanup, 0);
00904 
00905   new_stat = XZALLOC (struct cmd_stats);
00906 
00907   new_stat->msg_type = msg_type;
00908 
00909   if (per_command_space)
00910     {
00911 #ifdef HAVE_SBRK
00912       char *lim = (char *) sbrk (0);
00913       new_stat->start_space = lim - lim_at_start;
00914       new_stat->space_enabled = 1;
00915 #endif
00916     }
00917 
00918   if (per_command_time)
00919     {
00920       new_stat->start_cpu_time = get_run_time ();
00921       gettimeofday (&new_stat->start_wall_time, NULL);
00922       new_stat->time_enabled = 1;
00923     }
00924 
00925   if (per_command_symtab)
00926     {
00927       int nr_symtabs, nr_primary_symtabs, nr_blocks;
00928 
00929       count_symtabs_and_blocks (&nr_symtabs, &nr_primary_symtabs, &nr_blocks);
00930       new_stat->start_nr_symtabs = nr_symtabs;
00931       new_stat->start_nr_primary_symtabs = nr_primary_symtabs;
00932       new_stat->start_nr_blocks = nr_blocks;
00933       new_stat->symtab_enabled = 1;
00934     }
00935 
00936   /* Initalize timer to keep track of how long we waited for the user.  */
00937   reset_prompt_for_continue_wait_time ();
00938 
00939   return make_cleanup_dtor (report_command_stats, new_stat, xfree);
00940 }
00941 
00942 /* Handle unknown "mt set per-command" arguments.
00943    In this case have "mt set per-command on|off" affect every setting.  */
00944 
00945 static void
00946 set_per_command_cmd (char *args, int from_tty)
00947 {
00948   struct cmd_list_element *list;
00949   size_t length;
00950   int val;
00951 
00952   val = parse_cli_boolean_value (args);
00953   if (val < 0)
00954     error (_("Bad value for 'mt set per-command no'."));
00955 
00956   for (list = per_command_setlist; list != NULL; list = list->next)
00957     if (list->var_type == var_boolean)
00958       {
00959         gdb_assert (list->type == set_cmd);
00960         do_set_command (args, from_tty, list);
00961       }
00962 }
00963 
00964 /* Command "show per-command" displays summary of all the current
00965    "show per-command " settings.  */
00966 
00967 static void
00968 show_per_command_cmd (char *args, int from_tty)
00969 {
00970   cmd_show_list (per_command_showlist, from_tty, "");
00971 }
00972 
00973 void
00974 _initialize_maint_cmds (void)
00975 {
00976   add_prefix_cmd ("maintenance", class_maintenance, maintenance_command, _("\
00977 Commands for use by GDB maintainers.\n\
00978 Includes commands to dump specific internal GDB structures in\n\
00979 a human readable form, to cause GDB to deliberately dump core,\n\
00980 to test internal functions such as the C++/ObjC demangler, etc."),
00981                   &maintenancelist, "maintenance ", 0,
00982                   &cmdlist);
00983 
00984   add_com_alias ("mt", "maintenance", class_maintenance, 1);
00985 
00986   add_prefix_cmd ("info", class_maintenance, maintenance_info_command, _("\
00987 Commands for showing internal info about the program being debugged."),
00988                   &maintenanceinfolist, "maintenance info ", 0,
00989                   &maintenancelist);
00990   add_alias_cmd ("i", "info", class_maintenance, 1, &maintenancelist);
00991 
00992   add_cmd ("sections", class_maintenance, maintenance_info_sections, _("\
00993 List the BFD sections of the exec and core files. \n\
00994 Arguments may be any combination of:\n\
00995         [one or more section names]\n\
00996         ALLOC LOAD RELOC READONLY CODE DATA ROM CONSTRUCTOR\n\
00997         HAS_CONTENTS NEVER_LOAD COFF_SHARED_LIBRARY IS_COMMON\n\
00998 Sections matching any argument will be listed (no argument\n\
00999 implies all sections).  In addition, the special argument\n\
01000         ALLOBJ\n\
01001 lists all sections from all object files, including shared libraries."),
01002            &maintenanceinfolist);
01003 
01004   add_prefix_cmd ("print", class_maintenance, maintenance_print_command,
01005                   _("Maintenance command for printing GDB internal state."),
01006                   &maintenanceprintlist, "maintenance print ", 0,
01007                   &maintenancelist);
01008 
01009   add_prefix_cmd ("set", class_maintenance, maintenance_set_cmd, _("\
01010 Set GDB internal variables used by the GDB maintainer.\n\
01011 Configure variables internal to GDB that aid in GDB's maintenance"),
01012                   &maintenance_set_cmdlist, "maintenance set ",
01013                   0/*allow-unknown*/,
01014                   &maintenancelist);
01015 
01016   add_prefix_cmd ("show", class_maintenance, maintenance_show_cmd, _("\
01017 Show GDB internal variables used by the GDB maintainer.\n\
01018 Configure variables internal to GDB that aid in GDB's maintenance"),
01019                   &maintenance_show_cmdlist, "maintenance show ",
01020                   0/*allow-unknown*/,
01021                   &maintenancelist);
01022 
01023 #ifndef _WIN32
01024   add_cmd ("dump-me", class_maintenance, maintenance_dump_me, _("\
01025 Get fatal error; make debugger dump its core.\n\
01026 GDB sets its handling of SIGQUIT back to SIG_DFL and then sends\n\
01027 itself a SIGQUIT signal."),
01028            &maintenancelist);
01029 #endif
01030 
01031   add_cmd ("internal-error", class_maintenance,
01032            maintenance_internal_error, _("\
01033 Give GDB an internal error.\n\
01034 Cause GDB to behave as if an internal error was detected."),
01035            &maintenancelist);
01036 
01037   add_cmd ("internal-warning", class_maintenance,
01038            maintenance_internal_warning, _("\
01039 Give GDB an internal warning.\n\
01040 Cause GDB to behave as if an internal warning was reported."),
01041            &maintenancelist);
01042 
01043   add_cmd ("demangle", class_maintenance, maintenance_demangle, _("\
01044 Demangle a C++/ObjC mangled name.\n\
01045 Call internal GDB demangler routine to demangle a C++ link name\n\
01046 and prints the result."),
01047            &maintenancelist);
01048 
01049   add_prefix_cmd ("per-command", class_maintenance, set_per_command_cmd, _("\
01050 Per-command statistics settings."),
01051                     &per_command_setlist, "set per-command ",
01052                     1/*allow-unknown*/, &maintenance_set_cmdlist);
01053 
01054   add_prefix_cmd ("per-command", class_maintenance, show_per_command_cmd, _("\
01055 Show per-command statistics settings."),
01056                     &per_command_showlist, "show per-command ",
01057                     0/*allow-unknown*/, &maintenance_show_cmdlist);
01058 
01059   add_setshow_boolean_cmd ("time", class_maintenance,
01060                            &per_command_time, _("\
01061 Set whether to display per-command execution time."), _("\
01062 Show whether to display per-command execution time."),
01063                            _("\
01064 If enabled, the execution time for each command will be\n\
01065 displayed following the command's output."),
01066                            NULL, NULL,
01067                            &per_command_setlist, &per_command_showlist);
01068 
01069   add_setshow_boolean_cmd ("space", class_maintenance,
01070                            &per_command_space, _("\
01071 Set whether to display per-command space usage."), _("\
01072 Show whether to display per-command space usage."),
01073                            _("\
01074 If enabled, the space usage for each command will be\n\
01075 displayed following the command's output."),
01076                            NULL, NULL,
01077                            &per_command_setlist, &per_command_showlist);
01078 
01079   add_setshow_boolean_cmd ("symtab", class_maintenance,
01080                            &per_command_symtab, _("\
01081 Set whether to display per-command symtab statistics."), _("\
01082 Show whether to display per-command symtab statistics."),
01083                            _("\
01084 If enabled, the basic symtab statistics for each command will be\n\
01085 displayed following the command's output."),
01086                            NULL, NULL,
01087                            &per_command_setlist, &per_command_showlist);
01088 
01089   /* This is equivalent to "mt set per-command time on".
01090      Kept because some people are used to typing "mt time 1".  */
01091   add_cmd ("time", class_maintenance, maintenance_time_display, _("\
01092 Set the display of time usage.\n\
01093 If nonzero, will cause the execution time for each command to be\n\
01094 displayed, following the command's output."),
01095            &maintenancelist);
01096 
01097   /* This is equivalent to "mt set per-command space on".
01098      Kept because some people are used to typing "mt space 1".  */
01099   add_cmd ("space", class_maintenance, maintenance_space_display, _("\
01100 Set the display of space usage.\n\
01101 If nonzero, will cause the execution space for each command to be\n\
01102 displayed, following the command's output."),
01103            &maintenancelist);
01104 
01105   add_cmd ("type", class_maintenance, maintenance_print_type, _("\
01106 Print a type chain for a given symbol.\n\
01107 For each node in a type chain, print the raw data for each member of\n\
01108 the type structure, and the interpretation of the data."),
01109            &maintenanceprintlist);
01110 
01111   add_cmd ("statistics", class_maintenance, maintenance_print_statistics,
01112            _("Print statistics about internal gdb state."),
01113            &maintenanceprintlist);
01114 
01115   add_cmd ("architecture", class_maintenance,
01116            maintenance_print_architecture, _("\
01117 Print the internal architecture configuration.\n\
01118 Takes an optional file parameter."),
01119            &maintenanceprintlist);
01120 
01121   add_cmd ("translate-address", class_maintenance,
01122            maintenance_translate_address,
01123            _("Translate a section name and address to a symbol."),
01124            &maintenancelist);
01125 
01126   add_cmd ("deprecate", class_maintenance, maintenance_deprecate, _("\
01127 Deprecate a command.  Note that this is just in here so the \n\
01128 testsuite can check the command deprecator. You probably shouldn't use this,\n\
01129 rather you should use the C function deprecate_cmd().  If you decide you \n\
01130 want to use it: maintenance deprecate 'commandname' \"replacement\". The \n\
01131 replacement is optional."), &maintenancelist);
01132 
01133   add_cmd ("undeprecate", class_maintenance, maintenance_undeprecate, _("\
01134 Undeprecate a command.  Note that this is just in here so the \n\
01135 testsuite can check the command deprecator. You probably shouldn't use this,\n\
01136 If you decide you want to use it: maintenance undeprecate 'commandname'"),
01137            &maintenancelist);
01138 
01139   add_setshow_zinteger_cmd ("watchdog", class_maintenance, &watchdog, _("\
01140 Set watchdog timer."), _("\
01141 Show watchdog timer."), _("\
01142 When non-zero, this timeout is used instead of waiting forever for a target\n\
01143 to finish a low-level step or continue operation.  If the specified amount\n\
01144 of time passes without a response from the target, an error occurs."),
01145                             NULL,
01146                             show_watchdog,
01147                             &setlist, &showlist);
01148 
01149   add_setshow_boolean_cmd ("profile", class_maintenance,
01150                            &maintenance_profile_p, _("\
01151 Set internal profiling."), _("\
01152 Show internal profiling."), _("\
01153 When enabled GDB is profiled."),
01154                            maintenance_set_profile_cmd,
01155                            show_maintenance_profile_p,
01156                            &maintenance_set_cmdlist,
01157                            &maintenance_show_cmdlist);
01158 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines