* configure.in: Check that -pg works if using --enable-profiling.
[deliverable/binutils-gdb.git] / gdb / maint.c
index f480d1cf6e8284d02f43c82efa3d1e403f227cd1..6240b49f2d3cc3aef20a4bf3851938726231036f 100644 (file)
@@ -1,5 +1,5 @@
 /* Support for GDB maintenance commands.
 /* Support for GDB maintenance commands.
-   Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001
+   Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003
    Free Software Foundation, Inc.
    Written by Fred Fish at Cygnus Support.
 
    Free Software Foundation, Inc.
    Written by Fred Fish at Cygnus Support.
 
@@ -36,6 +36,8 @@
 #include "objfiles.h"
 #include "value.h"
 
 #include "objfiles.h"
 #include "value.h"
 
+#include "cli/cli-decode.h"
+
 extern void _initialize_maint_cmds (void);
 
 static void maintenance_command (char *, int);
 extern void _initialize_maint_cmds (void);
 
 static void maintenance_command (char *, int);
@@ -52,7 +54,7 @@ static void maintenance_space_display (char *, int);
 
 static void maintenance_info_command (char *, int);
 
 
 static void maintenance_info_command (char *, int);
 
-static void print_section_table (bfd *, asection *, PTR);
+static void print_section_table (bfd *, asection *, void *);
 
 static void maintenance_info_sections (char *, int);
 
 
 static void maintenance_info_sections (char *, int);
 
@@ -116,8 +118,18 @@ maintenance_dump_me (char *args, int from_tty)
 static void
 maintenance_internal_error (char *args, int from_tty)
 {
 static void
 maintenance_internal_error (char *args, int from_tty)
 {
-  internal_error (__FILE__, __LINE__,
-                 "internal maintenance");
+  internal_error (__FILE__, __LINE__, "%s", (args == NULL ? "" : args));
+}
+
+/* Stimulate the internal error mechanism that GDB uses when an
+   internal problem is detected.  Allows testing of the mechanism.
+   Also useful when the user wants to drop a core file but not exit
+   GDB. */
+
+static void
+maintenance_internal_warning (char *args, int from_tty)
+{
+  internal_warning (__FILE__, __LINE__, "%s", (args == NULL ? "" : args));
 }
 
 /* Someday we should allow demangling for things other than just
 }
 
 /* Someday we should allow demangling for things other than just
@@ -139,7 +151,17 @@ maintenance_demangle (char *args, int from_tty)
     }
   else
     {
     }
   else
     {
-      demangled = cplus_demangle (args, DMGL_ANSI | DMGL_PARAMS);
+      switch (current_language->la_language)
+       {
+       case language_objc:
+         /* Commented out until ObjC handling is enabled. */
+         /* demangled = objc_demangle (args); */
+         /* break; */
+       case language_cplus:
+       default:
+         demangled = cplus_demangle (args, DMGL_ANSI | DMGL_PARAMS);
+         break;
+       }
       if (demangled != NULL)
        {
          printf_unfiltered ("%s\n", demangled);
       if (demangled != NULL)
        {
          printf_unfiltered ("%s\n", demangled);
@@ -186,27 +208,82 @@ maintenance_info_command (char *arg, int from_tty)
   help_list (maintenanceinfolist, "maintenance info ", -1, gdb_stdout);
 }
 
   help_list (maintenanceinfolist, "maintenance info ", -1, gdb_stdout);
 }
 
-static void
-print_section_table (bfd *abfd, asection *asect, PTR ignore)
+/* Mini tokenizing lexer for 'maint info sections' command.  */
+
+static int
+match_substring (const char *string, const char *substr)
 {
 {
-  flagword flags;
+  int substr_len = strlen(substr);
+  const char *tok;
 
 
-  flags = bfd_get_section_flags (abfd, asect);
+  while ((tok = strstr (string, substr)) != NULL)
+    {
+      /* Got a partial match.  Is it a whole word? */
+      if (tok == string
+         || tok[-1] == ' '
+         || tok[-1] == '\t')
+      {
+       /* Token is delimited at the front... */
+       if (tok[substr_len] == ' '
+           || tok[substr_len] == '\t'
+           || tok[substr_len] == '\0')
+       {
+         /* Token is delimited at the rear.  Got a whole-word match.  */
+         return 1;
+       }
+      }
+      /* Token didn't match as a whole word.  Advance and try again.  */
+      string = tok + 1;
+    }
+  return 0;
+}
 
 
-  /* FIXME-32x64: Need print_address_numeric with field width.  */
-  printf_filtered ("    %s",
-                  local_hex_string_custom
-                  ((unsigned long) bfd_section_vma (abfd, asect), "08l"));
-  printf_filtered ("->%s",
-                  local_hex_string_custom
-                  ((unsigned long) (bfd_section_vma (abfd, asect)
-                                    + bfd_section_size (abfd, asect)),
-                   "08l"));
-  printf_filtered (" at %s",
-                  local_hex_string_custom
-                  ((unsigned long) asect->filepos, "08l"));
-  printf_filtered (": %s", bfd_section_name (abfd, asect));
+static int 
+match_bfd_flags (char *string, flagword flags)
+{
+  if (flags & SEC_ALLOC)
+    if (match_substring (string, "ALLOC"))
+      return 1;
+  if (flags & SEC_LOAD)
+    if (match_substring (string, "LOAD"))
+      return 1;
+  if (flags & SEC_RELOC)
+    if (match_substring (string, "RELOC"))
+      return 1;
+  if (flags & SEC_READONLY)
+    if (match_substring (string, "READONLY"))
+      return 1;
+  if (flags & SEC_CODE)
+    if (match_substring (string, "CODE"))
+      return 1;
+  if (flags & SEC_DATA)
+    if (match_substring (string, "DATA"))
+      return 1;
+  if (flags & SEC_ROM)
+    if (match_substring (string, "ROM"))
+      return 1;
+  if (flags & SEC_CONSTRUCTOR)
+    if (match_substring (string, "CONSTRUCTOR"))
+      return 1;
+  if (flags & SEC_HAS_CONTENTS)
+    if (match_substring (string, "HAS_CONTENTS"))
+      return 1;
+  if (flags & SEC_NEVER_LOAD)
+    if (match_substring (string, "NEVER_LOAD"))
+      return 1;
+  if (flags & SEC_COFF_SHARED_LIBRARY)
+    if (match_substring (string, "COFF_SHARED_LIBRARY"))
+      return 1;
+  if (flags & SEC_IS_COMMON)
+    if (match_substring (string, "IS_COMMON"))
+      return 1;
 
 
+  return 0;
+}
+
+static void
+print_bfd_flags (flagword flags)
+{
   if (flags & SEC_ALLOC)
     printf_filtered (" ALLOC");
   if (flags & SEC_LOAD)
   if (flags & SEC_ALLOC)
     printf_filtered (" ALLOC");
   if (flags & SEC_LOAD)
@@ -231,10 +308,60 @@ print_section_table (bfd *abfd, asection *asect, PTR ignore)
     printf_filtered (" COFF_SHARED_LIBRARY");
   if (flags & SEC_IS_COMMON)
     printf_filtered (" IS_COMMON");
     printf_filtered (" COFF_SHARED_LIBRARY");
   if (flags & SEC_IS_COMMON)
     printf_filtered (" IS_COMMON");
+}
 
 
+static void
+maint_print_section_info (const char *name, flagword flags, 
+                         CORE_ADDR addr, CORE_ADDR endaddr, 
+                         unsigned long filepos)
+{
+  /* FIXME-32x64: Need print_address_numeric with field width.  */
+  printf_filtered ("    0x%s", paddr (addr));
+  printf_filtered ("->0x%s", paddr (endaddr));
+  printf_filtered (" at %s",
+                  local_hex_string_custom ((unsigned long) filepos, "08l"));
+  printf_filtered (": %s", name);
+  print_bfd_flags (flags);
   printf_filtered ("\n");
 }
 
   printf_filtered ("\n");
 }
 
+static void
+print_bfd_section_info (bfd *abfd, 
+                       asection *asect, 
+                       void *arg)
+{
+  flagword flags = bfd_get_section_flags (abfd, asect);
+  const char *name = bfd_section_name (abfd, asect);
+
+  if (arg == NULL || *((char *) arg) == '\0'
+      || match_substring ((char *) arg, name)
+      || match_bfd_flags ((char *) arg, flags))
+    {
+      CORE_ADDR addr, endaddr;
+
+      addr = bfd_section_vma (abfd, asect);
+      endaddr = addr + bfd_section_size (abfd, asect);
+      maint_print_section_info (name, flags, addr, endaddr, asect->filepos);
+    }
+}
+
+static void
+print_objfile_section_info (bfd *abfd, 
+                           struct obj_section *asect, 
+                           char *string)
+{
+  flagword flags = bfd_get_section_flags (abfd, asect->the_bfd_section);
+  const char *name = bfd_section_name (abfd, asect->the_bfd_section);
+
+  if (string == NULL || *string == '\0'
+      || match_substring (string, name)
+      || match_bfd_flags (string, flags))
+    {
+      maint_print_section_info (name, flags, asect->addr, asect->endaddr, 
+                         asect->the_bfd_section->filepos);
+    }
+}
+
 /* ARGSUSED */
 static void
 maintenance_info_sections (char *arg, int from_tty)
 /* ARGSUSED */
 static void
 maintenance_info_sections (char *arg, int from_tty)
@@ -245,7 +372,30 @@ maintenance_info_sections (char *arg, int from_tty)
       printf_filtered ("    `%s', ", bfd_get_filename (exec_bfd));
       wrap_here ("        ");
       printf_filtered ("file type %s.\n", bfd_get_target (exec_bfd));
       printf_filtered ("    `%s', ", bfd_get_filename (exec_bfd));
       wrap_here ("        ");
       printf_filtered ("file type %s.\n", bfd_get_target (exec_bfd));
-      bfd_map_over_sections (exec_bfd, print_section_table, 0);
+      if (arg && *arg && match_substring (arg, "ALLOBJ"))
+       {
+         struct objfile *ofile;
+         struct obj_section *osect;
+
+         /* Only this function cares about the 'ALLOBJ' argument; 
+            if 'ALLOBJ' is the only argument, discard it rather than
+            passing it down to print_objfile_section_info (which 
+            wouldn't know how to handle it).  */
+         if (strcmp (arg, "ALLOBJ") == 0)
+           arg = NULL;
+
+         ALL_OBJFILES (ofile)
+           {
+             printf_filtered ("  Object file: %s\n", 
+                              bfd_get_filename (ofile->obfd));
+             ALL_OBJFILE_OSECTIONS (ofile, osect)
+               {
+                 print_objfile_section_info (ofile->obfd, osect, arg);
+               }
+           }
+       }
+      else 
+       bfd_map_over_sections (exec_bfd, print_bfd_section_info, arg);
     }
 
   if (core_bfd)
     }
 
   if (core_bfd)
@@ -254,7 +404,7 @@ maintenance_info_sections (char *arg, int from_tty)
       printf_filtered ("    `%s', ", bfd_get_filename (core_bfd));
       wrap_here ("        ");
       printf_filtered ("file type %s.\n", bfd_get_target (core_bfd));
       printf_filtered ("    `%s', ", bfd_get_filename (core_bfd));
       wrap_here ("        ");
       printf_filtered ("file type %s.\n", bfd_get_target (core_bfd));
-      bfd_map_over_sections (core_bfd, print_section_table, 0);
+      bfd_map_over_sections (core_bfd, print_bfd_section_info, arg);
     }
 }
 
     }
 }
 
@@ -355,7 +505,7 @@ maintenance_translate_address (char *arg, int from_tty)
 }
 
 
 }
 
 
-/* When a comamnd is deprecated the user will be warned the first time
+/* When a command is deprecated the user will be warned the first time
    the command is used.  If possible, a replacement will be
    offered. */
 
    the command is used.  If possible, a replacement will be
    offered. */
 
@@ -471,15 +621,91 @@ maintenance_do_deprecate (char *text, int deprecate)
     }
 }
 
     }
 }
 
+/* Maintenance set/show framework.  */
+
+static struct cmd_list_element *maintenance_set_cmdlist;
+static struct cmd_list_element *maintenance_show_cmdlist;
+
+static void
+maintenance_set_cmd (char *args, int from_tty)
+{
+  printf_unfiltered ("\"maintenance set\" must be followed by the name of a set command.\n");
+  help_list (maintenance_set_cmdlist, "maintenance set ", -1, gdb_stdout);
+}
+
+static void
+maintenance_show_cmd (char *args, int from_tty)
+{
+  cmd_show_list (maintenance_show_cmdlist, from_tty, "");
+}
+
+/* Profiling support.  */
+
+static int maintenance_profile_p;
+
+#if defined (HAVE_MONSTARTUP) && defined (HAVE__MCLEANUP)
+
+static int profiling_state;
+
+static void
+mcleanup_wrapper (void)
+{
+  extern void _mcleanup (void);
+
+  if (profiling_state)
+    _mcleanup ();
+}
+
+static void
+maintenance_set_profile_cmd (char *args, int from_tty, struct cmd_list_element *c)
+{
+  if (maintenance_profile_p == profiling_state)
+    return;
+
+  profiling_state = maintenance_profile_p;
+
+  if (maintenance_profile_p)
+    {
+      static int profiling_initialized;
+
+      extern void monstartup (unsigned long, unsigned long);
+      extern char _etext;
+      extern int main();
+
+      if (!profiling_initialized)
+       {
+         atexit (mcleanup_wrapper);
+         profiling_initialized = 1;
+       }
+
+      /* "main" is now always the first function in the text segment, so use
+        its address for monstartup.  */
+      monstartup ((unsigned long) &main, (unsigned long) &_etext);
+    }
+  else
+    {
+      extern void _mcleanup (void);
+      _mcleanup ();
+    }
+}
+#else
+static void
+maintenance_set_profile_cmd (char *args, int from_tty, struct cmd_list_element *c)
+{
+  warning ("Profiling support is not available on this system.");
+}
+#endif
 
 void
 _initialize_maint_cmds (void)
 {
 
 void
 _initialize_maint_cmds (void)
 {
+  struct cmd_list_element *tmpcmd;
+
   add_prefix_cmd ("maintenance", class_maintenance, maintenance_command,
                  "Commands for use by GDB maintainers.\n\
 Includes commands to dump specific internal GDB structures in\n\
 a human readable form, to cause GDB to deliberately dump core,\n\
   add_prefix_cmd ("maintenance", class_maintenance, maintenance_command,
                  "Commands for use by GDB maintainers.\n\
 Includes commands to dump specific internal GDB structures in\n\
 a human readable form, to cause GDB to deliberately dump core,\n\
-to test internal functions such as the C++ demangler, etc.",
+to test internal functions such as the C++/ObjC demangler, etc.",
                  &maintenancelist, "maintenance ", 0,
                  &cmdlist);
 
                  &maintenancelist, "maintenance ", 0,
                  &cmdlist);
 
@@ -492,7 +718,15 @@ to test internal functions such as the C++ demangler, etc.",
   add_alias_cmd ("i", "info", class_maintenance, 1, &maintenancelist);
 
   add_cmd ("sections", class_maintenance, maintenance_info_sections,
   add_alias_cmd ("i", "info", class_maintenance, 1, &maintenancelist);
 
   add_cmd ("sections", class_maintenance, maintenance_info_sections,
-          "List the BFD sections of the exec and core files.",
+          "List the BFD sections of the exec and core files. \n\
+Arguments may be any combination of:\n\
+       [one or more section names]\n\
+       ALLOC LOAD RELOC READONLY CODE DATA ROM CONSTRUCTOR\n\
+       HAS_CONTENTS NEVER_LOAD COFF_SHARED_LIBRARY IS_COMMON\n\
+Sections matching any argument will be listed (no argument\n\
+implies all sections).  In addition, the special argument\n\
+       ALLOBJ\n\
+lists all sections from all object files, including shared libraries.",
           &maintenanceinfolist);
 
   add_prefix_cmd ("print", class_maintenance, maintenance_print_command,
           &maintenanceinfolist);
 
   add_prefix_cmd ("print", class_maintenance, maintenance_print_command,
@@ -500,10 +734,24 @@ to test internal functions such as the C++ demangler, etc.",
                  &maintenanceprintlist, "maintenance print ", 0,
                  &maintenancelist);
 
                  &maintenanceprintlist, "maintenance print ", 0,
                  &maintenancelist);
 
+  add_prefix_cmd ("set", class_maintenance, maintenance_set_cmd, "\
+Set GDB internal variables used by the GDB maintainer.\n\
+Configure variables internal to GDB that aid in GDB's maintenance",
+                 &maintenance_set_cmdlist, "maintenance set ",
+                 0/*allow-unknown*/,
+                 &maintenancelist);
+
+  add_prefix_cmd ("show", class_maintenance, maintenance_show_cmd, "\
+Show GDB internal variables used by the GDB maintainer.\n\
+Configure variables internal to GDB that aid in GDB's maintenance",
+                 &maintenance_show_cmdlist, "maintenance show ",
+                 0/*allow-unknown*/,
+                 &maintenancelist);
+
 #ifndef _WIN32
   add_cmd ("dump-me", class_maintenance, maintenance_dump_me,
           "Get fatal error; make debugger dump its core.\n\
 #ifndef _WIN32
   add_cmd ("dump-me", class_maintenance, maintenance_dump_me,
           "Get fatal error; make debugger dump its core.\n\
-GDB sets it's handling of SIGQUIT back to SIG_DFL and then sends\n\
+GDB sets its handling of SIGQUIT back to SIG_DFL and then sends\n\
 itself a SIGQUIT signal.",
           &maintenancelist);
 #endif
 itself a SIGQUIT signal.",
           &maintenancelist);
 #endif
@@ -513,8 +761,13 @@ itself a SIGQUIT signal.",
 Cause GDB to behave as if an internal error was detected.",
           &maintenancelist);
 
 Cause GDB to behave as if an internal error was detected.",
           &maintenancelist);
 
+  add_cmd ("internal-warning", class_maintenance, maintenance_internal_warning,
+          "Give GDB an internal warning.\n\
+Cause GDB to behave as if an internal warning was reported.",
+          &maintenancelist);
+
   add_cmd ("demangle", class_maintenance, maintenance_demangle,
   add_cmd ("demangle", class_maintenance, maintenance_demangle,
-          "Demangle a C++ mangled name.\n\
+          "Demangle a C++/ObjC mangled name.\n\
 Call internal GDB demangler routine to demangle a C++ link name\n\
 and prints the result.",
           &maintenancelist);
 Call internal GDB demangler routine to demangle a C++ link name\n\
 and prints the result.",
           &maintenancelist);
@@ -596,4 +849,14 @@ When non-zero, this timeout is used instead of waiting forever for a target to\n
 finish a low-level step or continue operation.  If the specified amount of time\n\
 passes without a response from the target, an error occurs.", &setlist),
                      &showlist);
 finish a low-level step or continue operation.  If the specified amount of time\n\
 passes without a response from the target, an error occurs.", &setlist),
                      &showlist);
+
+
+  add_setshow_boolean_cmd ("profile", class_maintenance,
+                          &maintenance_profile_p,
+                          "Set internal profiling.\n"
+                          "When enabled GDB is profiled.",
+                          "Show internal profiling.\n",
+                          maintenance_set_profile_cmd, NULL,
+                          &maintenance_set_cmdlist,
+                          &maintenance_show_cmdlist);
 }
 }
This page took 0.049618 seconds and 4 git commands to generate.