GDB (API)
|
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 }