diff mbox

Improve maint print symbols,psymbols,msymbols

Message ID m3d1pkrxwa.fsf@sspiff.org
State New
Headers show

Commit Message

Doug Evans April 20, 2016, 5:30 p.m. UTC
Hi.

More old sandbox spring cleaning.

At the time I needed this, I used it a lot.
I've since also added msymbol improvements if only for consistency sake.
It's helpful to have more control over what to print,
and to have the output appear on the screen
without having to go looking for it. Bleah.

2016-04-20  Doug Evans  <xdje42@gmail.com>

	* NEWS: Document new syntax for "mt print symbols", "mt print psymbols"
	and "mt print msymbols" commands.
	* psymtab.c (DEV_TTY): Delete.
	(dump_psymtab_addrmap): Don't dump if psymtabs_addrmap is NULL.
	(maintenance_print_psymbols): Rewrite for new syntax:
	mt print psymbols [-objfile objfile] [-pc address] [outfile]
	mt print psymbols [-objfile objfile] [-source source] [outfile]
	(_initialize_psymtab): Update help text.
	* symmisc.c (maintenance_print_symbols): Rewrite for new syntax:
	mt print symbols [-pc address] [outfile]
	mt print symbols [-objfile objfile] [-source source] [outfile]
	(maintenance_print_msymbols): Rewrite for new syntax:
	mt print msymbols [-objfile objfile] [outfile]
	Only print symbols for the current progspace.
	(_initialize_symmisc): Update help text.

	doc/
	* gdb.texinfo (Symbols): Update docs for symbol printing maintenance
	commands.

	testsuite/
	* gdb.base/maint.exp: Update tests for maint print symbols, psymbols
	and msymbols.

Comments

Eli Zaretskii April 20, 2016, 5:44 p.m. UTC | #1
> From: Doug Evans <xdje42@gmail.com>
> Date: Wed, 20 Apr 2016 10:30:13 -0700
> 
> 2016-04-20  Doug Evans  <xdje42@gmail.com>
> 
> 	* NEWS: Document new syntax for "mt print symbols", "mt print psymbols"
> 	and "mt print msymbols" commands.
> 	* psymtab.c (DEV_TTY): Delete.
> 	(dump_psymtab_addrmap): Don't dump if psymtabs_addrmap is NULL.
> 	(maintenance_print_psymbols): Rewrite for new syntax:
> 	mt print psymbols [-objfile objfile] [-pc address] [outfile]
> 	mt print psymbols [-objfile objfile] [-source source] [outfile]
> 	(_initialize_psymtab): Update help text.
> 	* symmisc.c (maintenance_print_symbols): Rewrite for new syntax:
> 	mt print symbols [-pc address] [outfile]
> 	mt print symbols [-objfile objfile] [-source source] [outfile]
> 	(maintenance_print_msymbols): Rewrite for new syntax:
> 	mt print msymbols [-objfile objfile] [outfile]
> 	Only print symbols for the current progspace.
> 	(_initialize_symmisc): Update help text.
> 
> 	doc/
> 	* gdb.texinfo (Symbols): Update docs for symbol printing maintenance
> 	commands.
> 
> 	testsuite/
> 	* gdb.base/maint.exp: Update tests for maint print symbols, psymbols
> 	and msymbols.

OK for the documentation parts, except this nit:

> +If @code{-objfile @var{OBJFILE}} is specified, only dump symbols for
> +that objfile.
> +If @code{-pc @var{address}} is specified, only dump symbols for the file
> +with code at that address.  Note that @var{address} may be a symbol like
> +@code{main}.
> +If @code{-source @var{SOURCE}} is specified, only dump symbols for that
> +source file.

The arguments of @var shouldn't be in CAPS.

Thanks.
Pedro Alves April 22, 2016, 1:31 p.m. UTC | #2
On 04/20/2016 06:30 PM, Doug Evans wrote:
> Hi.
> 
> More old sandbox spring cleaning.
> 
> At the time I needed this, I used it a lot.

Thanks, I think this is quite useful and helpful.

> I've since also added msymbol improvements if only for consistency sake.
> It's helpful to have more control over what to print,
> and to have the output appear on the screen
> without having to go looking for it. Bleah.

Yeah...

No real comments on the patch itself.  Only a small
passer-by comment below.

> +      else if (strcmp (argv[i], "-source") == 0)
> +	{
> +	  if (argv[i + 1] == NULL)
> +	    error (_("Missing source file"));
> +	  source_arg = argv[++i];
> +	}
> +      else if (strcmp (argv[i], "-objfile") == 0)
> +	{
> +	  if (argv[i + 1] == NULL)
> +	    error (_("Missing objfile name"));
> +	  objfile_arg = argv[++i];
> +	}
> +      else if (argv[i][0] == '-')
> +	{
> +	  /* Future proofing: Don't allow OUTFILE to begin with "-".  */
> +	  error (_("Unknown option: %s"), argv[i]);
> +	}

We don't do this often, but it's usual for tools to
understand "--" as meaning end of "-" options.  I'd
instead do:

      else if (strcmp (argv[i], "--") == 0)
        {
          /* Explicit "--" marks end of options. */
          break;
        }
      else if (argv[i][0] == '-')
        error (_("Unknown option: %s"), argv[i]);
      else
        break;

So anyone wanting a filename that begins with "-" could still have it.

Thanks,
Pedro Alves
diff mbox

Patch

diff --git a/gdb/NEWS b/gdb/NEWS
index 39d99b7..f93c567 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,13 @@ 
 
 *** Changes since GDB 7.11
 
+* The symbol dumping maintenance commands have new syntax.
+maint print symbols [-pc address] [filename]
+maint print symbols [-objfile objfile] [-source source] [filename]
+maint print psymbols [-objfile objfile] [-pc address] [filename]
+maint print psymbols [-objfile objfile] [-source source] [filename]
+maint print msymbols [-objfile objfile] [filename]
+
 * GDB now supports multibit bitfields and enums in target register
   descriptions.
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 7abd55e..25644a7 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -17106,21 +17106,32 @@  entered from the keyboard causes symbol information to be loaded.
 @cindex partial symbol dump
 @kindex maint print msymbols
 @cindex minimal symbol dump
-@item maint print symbols @var{filename}
-@itemx maint print psymbols @var{filename}
-@itemx maint print msymbols @var{filename}
-Write a dump of debugging symbol data into the file @var{filename}.
-These commands are used to debug the @value{GDBN} symbol-reading code.  Only
-symbols with debugging data are included.  If you use @samp{maint print
-symbols}, @value{GDBN} includes all the symbols for which it has already
-collected full details: that is, @var{filename} reflects symbols for
-only those files whose symbols @value{GDBN} has read.  You can use the
-command @code{info sources} to find out which files these are.  If you
-use @samp{maint print psymbols} instead, the dump shows information about
-symbols that @value{GDBN} only knows partially---that is, symbols defined in
-files that @value{GDBN} has skimmed, but not yet read completely.  Finally,
-@samp{maint print msymbols} dumps just the minimal symbol information
-required for each object file from which @value{GDBN} has read some symbols.
+@item maint print symbols @r{[}-pc @var{address}@r{]} @r{[}@var{filename}@r{]}
+@itemx maint print symbols @r{[}-objfile @var{objfile}@r{]} @r{[}-source @var{source}@r{]} @r{[}@var{filename}@r{]}
+@itemx maint print psymbols @r{[}-objfile @var{objfile}@r{]} @r{[}-pc @var{address}@r{]} @r{[}@var{filename}@r{]}
+@itemx maint print psymbols @r{[}-objfile @var{objfile}@r{]} @r{[}-source @var{source}@r{]} @r{[}@var{filename}@r{]}
+@itemx maint print msymbols @r{[}-objfile @var{objfile}@r{]} @r{[}@var{filename}@r{]}
+Write a dump of debugging symbol data into the file @var{filename} or
+the terminal if @var{filename} is unspecified.
+If @code{-objfile @var{OBJFILE}} is specified, only dump symbols for
+that objfile.
+If @code{-pc @var{address}} is specified, only dump symbols for the file
+with code at that address.  Note that @var{address} may be a symbol like
+@code{main}.
+If @code{-source @var{SOURCE}} is specified, only dump symbols for that
+source file.
+
+These commands are used to debug the @value{GDBN} symbol-reading code.
+These commands do not modify internal @value{GDBN} state, therefore
+@samp{maint print symbols} will only print symbols for already expanded symbol
+tables.
+You can use the command @code{info sources} to find out which files these are.
+If you use @samp{maint print psymbols} instead, the dump shows information
+about symbols that @value{GDBN} only knows partially---that is, symbols
+defined in files that @value{GDBN} has skimmed, but not yet read completely.
+Finally, @samp{maint print msymbols} just dumps ``minimal symbols'', e.g.,
+``ELF symbols''.
+
 @xref{Files, ,Commands to Specify Files}, for a discussion of how
 @value{GDBN} reads symbols (in the description of @code{symbol-file}).
 
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index 94b5e7e..a509fed 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -36,10 +36,6 @@ 
 #include "cp-support.h"
 #include "gdbcmd.h"
 
-#ifndef DEV_TTY
-#define DEV_TTY "/dev/tty"
-#endif
-
 struct psymbol_bcache
 {
   struct bcache *bcache;
@@ -1943,8 +1939,9 @@  dump_psymtab_addrmap (struct objfile *objfile, struct partial_symtab *psymtab,
 {
   struct dump_psymtab_addrmap_data addrmap_dump_data;
 
-  if (psymtab == NULL
-      || psymtab->psymtabs_addrmap_supported)
+  if ((psymtab == NULL
+       || psymtab->psymtabs_addrmap_supported)
+      && objfile->psymtabs_addrmap != NULL)
     {
       addrmap_dump_data.objfile = objfile;
       addrmap_dump_data.psymtab = psymtab;
@@ -1961,64 +1958,156 @@  static void
 maintenance_print_psymbols (char *args, int from_tty)
 {
   char **argv;
-  struct ui_file *outfile;
+  struct ui_file *outfile = gdb_stdout;
   struct cleanup *cleanups;
-  char *symname = NULL;
-  char *filename = DEV_TTY;
+  char *address_arg = NULL, *source_arg = NULL, *objfile_arg = NULL;
   struct objfile *objfile;
   struct partial_symtab *ps;
+  int i, outfile_idx, found;
+  CORE_ADDR pc = 0;
+  struct obj_section *section = NULL;
 
   dont_repeat ();
 
-  if (args == NULL)
-    {
-      error (_("\
-print-psymbols takes an output file name and optional symbol file name"));
-    }
   argv = gdb_buildargv (args);
   cleanups = make_cleanup_freeargv (argv);
 
-  if (argv[0] != NULL)
+  for (i = 0; argv[i] != NULL; ++i)
     {
-      filename = argv[0];
-      /* If a second arg is supplied, it is a source file name to match on.  */
-      if (argv[1] != NULL)
+      if (strcmp (argv[i], "-pc") == 0)
 	{
-	  symname = argv[1];
+	  if (argv[i + 1] == NULL)
+	    error (_("Missing pc value"));
+	  address_arg = argv[++i];
 	}
+      else if (strcmp (argv[i], "-source") == 0)
+	{
+	  if (argv[i + 1] == NULL)
+	    error (_("Missing source file"));
+	  source_arg = argv[++i];
+	}
+      else if (strcmp (argv[i], "-objfile") == 0)
+	{
+	  if (argv[i + 1] == NULL)
+	    error (_("Missing objfile name"));
+	  objfile_arg = argv[++i];
+	}
+      else if (argv[i][0] == '-')
+	{
+	  /* Future proofing: Don't allow OUTFILE to begin with "-".  */
+	  error (_("Unknown option: %s"), argv[i]);
+	}
+      else
+	break;
     }
+  outfile_idx = i;
 
-  filename = tilde_expand (filename);
-  make_cleanup (xfree, filename);
+  if (address_arg != NULL && source_arg != NULL)
+    error (_("Must specify at most one of -pc and -source"));
 
-  outfile = gdb_fopen (filename, FOPEN_WT);
-  if (outfile == NULL)
-    perror_with_name (filename);
-  make_cleanup_ui_file_delete (outfile);
+  if (argv[outfile_idx] != NULL)
+    {
+      char *outfile_name;
+
+      if (argv[outfile_idx + 1] != NULL)
+	error (_("Junk at end of command"));
+      outfile_name = tilde_expand (argv[outfile_idx]);
+      make_cleanup (xfree, outfile_name);
+      outfile = gdb_fopen (outfile_name, FOPEN_WT);
+      if (outfile == NULL)
+	perror_with_name (outfile_name);
+      make_cleanup_ui_file_delete (outfile);
+    }
 
-  ALL_OBJFILES (objfile)
-  {
-    fprintf_filtered (outfile, "\nPartial symtabs for objfile %s\n",
-		      objfile_name (objfile));
+  if (address_arg != NULL)
+    {
+      pc = parse_and_eval_address (address_arg);
+      /* If we fail to find a section, that's ok, try the lookup anyway.  */
+      section = find_pc_section (pc);
+    }
 
-    ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
+  found = 0;
+  ALL_OBJFILES (objfile)
     {
+      int printed_objfile_header = 0;
+      int print_for_objfile = 1;
+
       QUIT;
-      if (symname == NULL || filename_cmp (symname, ps->filename) == 0)
+      if (objfile_arg != NULL)
+	print_for_objfile
+	  = compare_filenames_for_search (objfile_name (objfile),
+					  objfile_arg);
+      if (!print_for_objfile)
+	continue;
+
+      if (address_arg != NULL)
 	{
-	  dump_psymtab (objfile, ps, outfile);
-	  dump_psymtab_addrmap (objfile, ps, outfile);
+	  struct bound_minimal_symbol msymbol = { NULL, NULL };
+
+	  /* We don't assume each pc has a unique objfile (this is for
+	     debugging).  */
+	  ps = find_pc_sect_psymtab (objfile, pc, section, msymbol);
+	  if (ps != NULL)
+	    {
+	      if (!printed_objfile_header)
+		{
+		  fprintf_filtered (outfile,
+				    "\nPartial symtabs for objfile %s\n",
+				    objfile_name (objfile));
+		  printed_objfile_header = 1;
+		}
+	      dump_psymtab (objfile, ps, outfile);
+	      dump_psymtab_addrmap (objfile, ps, outfile);
+	      found = 1;
+	    }
+	}
+      else
+	{
+	  ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
+	    {
+	      int print_for_source = 0;
+
+	      QUIT;
+	      if (source_arg != NULL)
+		{
+		  print_for_source
+		    = compare_filenames_for_search (ps->filename, source_arg);
+		  found = 1;
+		}
+	      if (source_arg == NULL
+		  || print_for_source)
+		{
+		  if (!printed_objfile_header)
+		    {
+		      fprintf_filtered (outfile,
+					"\nPartial symtabs for objfile %s\n",
+					objfile_name (objfile));
+		      printed_objfile_header = 1;
+		    }
+		  dump_psymtab (objfile, ps, outfile);
+		  dump_psymtab_addrmap (objfile, ps, outfile);
+		}
+	    }
 	}
-    }
 
-    /* If we're printing all symbols dump the full addrmap.  */
+      /* If we're printing all the objfile's symbols dump the full addrmap.  */
 
-    if (symname == NULL)
-      {
-	fprintf_filtered (outfile, "\n");
-	dump_psymtab_addrmap (objfile, NULL, outfile);
-      }
-  }
+      if (address_arg == NULL
+	  && source_arg == NULL
+	  && objfile->psymtabs_addrmap != NULL)
+	{
+	  fprintf_filtered (outfile, "\n");
+	  dump_psymtab_addrmap (objfile, NULL, outfile);
+	}
+    }
+
+  if (!found)
+    {
+      if (address_arg != NULL)
+	error (_("No partial symtab for address: %s"), address_arg);
+      if (source_arg != NULL)
+	error (_("No partial symtab for source file: %s"), source_arg);
+    }
 
   do_cleanups (cleanups);
 }
@@ -2230,8 +2319,13 @@  _initialize_psymtab (void)
 {
   add_cmd ("psymbols", class_maintenance, maintenance_print_psymbols, _("\
 Print dump of current partial symbol definitions.\n\
-Entries in the partial symbol table are dumped to file OUTFILE.\n\
-If a SOURCE file is specified, dump only that file's partial symbols."),
+Usage: mt print psymbols [-objfile objfile] [-pc address] [outfile]\n\
+       mt print psymbols [-objfile objfile] [-source source] [outfile]\n\
+Entries in the partial symbol table are dumped to file OUTFILE,\n\
+or the terminal if OUTFILE is unspecified.\n\
+If ADDRESS is provided, dump only the file for that address.\n\
+If SOURCE is provided, dump only that file's symbols.\n\
+If OBJFILE is provided, dump only that file's minimal symbols."),
 	   &maintenanceprintlist);
 
   add_cmd ("psymtabs", class_maintenance, maintenance_info_psymtabs, _("\
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
index d5efcfd..b4c8f66 100644
--- a/gdb/symmisc.c
+++ b/gdb/symmisc.c
@@ -412,49 +412,112 @@  static void
 maintenance_print_symbols (char *args, int from_tty)
 {
   char **argv;
-  struct ui_file *outfile;
+  struct ui_file *outfile = gdb_stdout;
   struct cleanup *cleanups;
-  char *symname = NULL;
-  char *filename = DEV_TTY;
-  struct objfile *objfile;
-  struct compunit_symtab *cu;
-  struct symtab *s;
+  char *address_arg = NULL, *source_arg = NULL, *objfile_arg = NULL;
+  int i, outfile_idx;
 
   dont_repeat ();
 
-  if (args == NULL)
-    {
-      error (_("Arguments missing: an output file name "
-	       "and an optional symbol file name"));
-    }
   argv = gdb_buildargv (args);
   cleanups = make_cleanup_freeargv (argv);
 
-  if (argv[0] != NULL)
+  for (i = 0; argv[i] != NULL; ++i)
     {
-      filename = argv[0];
-      /* If a second arg is supplied, it is a source file name to match on.  */
-      if (argv[1] != NULL)
+      if (strcmp (argv[i], "-pc") == 0)
+	{
+	  if (argv[i + 1] == NULL)
+	    error (_("Missing pc value"));
+	  address_arg = argv[++i];
+	}
+      else if (strcmp (argv[i], "-source") == 0)
+	{
+	  if (argv[i + 1] == NULL)
+	    error (_("Missing source file"));
+	  source_arg = argv[++i];
+	}
+      else if (strcmp (argv[i], "-objfile") == 0)
 	{
-	  symname = argv[1];
+	  if (argv[i + 1] == NULL)
+	    error (_("Missing objfile name"));
+	  objfile_arg = argv[++i];
 	}
+      else if (argv[i][0] == '-')
+	{
+	  /* Future proofing: Don't allow OUTFILE to begin with "-".  */
+	  error (_("Unknown option: %s"), argv[i]);
+	}
+      else
+	break;
     }
+  outfile_idx = i;
 
-  filename = tilde_expand (filename);
-  make_cleanup (xfree, filename);
+  if (address_arg != NULL && source_arg != NULL)
+    error (_("Must specify at most one of -pc and -source"));
 
-  outfile = gdb_fopen (filename, FOPEN_WT);
-  if (outfile == 0)
-    perror_with_name (filename);
-  make_cleanup_ui_file_delete (outfile);
+  if (argv[outfile_idx] != NULL)
+    {
+      char *outfile_name;
+
+      if (argv[outfile_idx + 1] != NULL)
+	error (_("Junk at end of command"));
+      outfile_name = tilde_expand (argv[outfile_idx]);
+      make_cleanup (xfree, outfile_name);
+      outfile = gdb_fopen (outfile_name, FOPEN_WT);
+      if (outfile == NULL)
+	perror_with_name (outfile_name);
+      make_cleanup_ui_file_delete (outfile);
+    }
+
+  if (address_arg != NULL)
+    {
+      CORE_ADDR pc = parse_and_eval_address (address_arg);
+      struct symtab *s = find_pc_line_symtab (pc);
 
-  ALL_FILETABS (objfile, cu, s)
+      if (s == NULL)
+	error (_("No symtab for address: %s"), address_arg);
+      dump_symtab (s, outfile);
+    }
+  else
     {
-      QUIT;
-      if (symname == NULL
-	  || filename_cmp (symname, symtab_to_filename_for_display (s)) == 0)
-	dump_symtab (s, outfile);
+      struct objfile *objfile;
+      struct compunit_symtab *cu;
+      struct symtab *s;
+      int found = 0;
+
+      ALL_OBJFILES (objfile)
+	{
+	  int print_for_objfile = 1;
+
+	  if (objfile_arg != NULL)
+	    print_for_objfile
+	      = compare_filenames_for_search (objfile_name (objfile),
+					      objfile_arg);
+	  if (!print_for_objfile)
+	    continue;
+
+	  ALL_OBJFILE_FILETABS (objfile, cu, s)
+	    {
+	      int print_for_source = 0;
+
+	      QUIT;
+	      if (source_arg != NULL)
+		{
+		  print_for_source
+		    = compare_filenames_for_search
+		        (symtab_to_filename_for_display (s), source_arg);
+		  found = 1;
+		}
+	      if (source_arg == NULL
+		  || print_for_source)
+		dump_symtab (s, outfile);
+	    }
+	}
+
+      if (source_arg != NULL && !found)
+	error (_("No symtab for source file: %s"), source_arg);
     }
+
   do_cleanups (cleanups);
 }
 
@@ -644,56 +707,57 @@  static void
 maintenance_print_msymbols (char *args, int from_tty)
 {
   char **argv;
-  struct ui_file *outfile;
+  struct ui_file *outfile = gdb_stdout;
   struct cleanup *cleanups;
-  char *filename = DEV_TTY;
-  char *symname = NULL;
-  struct program_space *pspace;
+  char *objfile_arg = NULL;
   struct objfile *objfile;
-
-  struct stat sym_st, obj_st;
+  int i, outfile_idx;
 
   dont_repeat ();
 
-  if (args == NULL)
-    {
-      error (_("print-msymbols takes an output file "
-	       "name and optional symbol file name"));
-    }
   argv = gdb_buildargv (args);
   cleanups = make_cleanup_freeargv (argv);
 
-  if (argv[0] != NULL)
+  for (i = 0; argv[i] != NULL; ++i)
     {
-      filename = argv[0];
-      /* If a second arg is supplied, it is a source file name to match on.  */
-      if (argv[1] != NULL)
+      if (strcmp (argv[i], "-objfile") == 0)
+	{
+	  if (argv[i + 1] == NULL)
+	    error (_("Missing objfile name"));
+	  objfile_arg = argv[++i];
+	}
+      else if (argv[i][0] == '-')
 	{
-	  symname = gdb_realpath (argv[1]);
-	  make_cleanup (xfree, symname);
-	  if (symname && stat (symname, &sym_st))
-	    perror_with_name (symname);
+	  /* Future proofing: Don't allow OUTFILE to begin with "-".  */
+	  error (_("Unknown option: %s"), argv[i]);
 	}
+      else
+	break;
     }
+  outfile_idx = i;
 
-  filename = tilde_expand (filename);
-  make_cleanup (xfree, filename);
+  if (argv[outfile_idx] != NULL)
+    {
+      char *outfile_name;
+
+      if (argv[outfile_idx + 1] != NULL)
+	error (_("Junk at end of command"));
+      outfile_name = tilde_expand (argv[outfile_idx]);
+      make_cleanup (xfree, outfile_name);
+      outfile = gdb_fopen (outfile_name, FOPEN_WT);
+      if (outfile == NULL)
+	perror_with_name (outfile_name);
+      make_cleanup_ui_file_delete (outfile);
+    }
 
-  outfile = gdb_fopen (filename, FOPEN_WT);
-  if (outfile == 0)
-    perror_with_name (filename);
-  make_cleanup_ui_file_delete (outfile);
+  ALL_OBJFILES (objfile)
+  {
+    QUIT;
+    if (objfile_arg == NULL
+	|| compare_filenames_for_search (objfile_name (objfile), objfile_arg))
+      dump_msymbols (objfile, outfile);
+  }
 
-  ALL_PSPACES (pspace)
-    ALL_PSPACE_OBJFILES (pspace, objfile)
-      {
-	QUIT;
-	if (symname == NULL || (!stat (objfile_name (objfile), &obj_st)
-				&& sym_st.st_dev == obj_st.st_dev
-				&& sym_st.st_ino == obj_st.st_ino))
-	  dump_msymbols (objfile, outfile);
-      }
-  fprintf_filtered (outfile, "\n\n");
   do_cleanups (cleanups);
 }
 
@@ -1048,14 +1112,21 @@  _initialize_symmisc (void)
 
   add_cmd ("symbols", class_maintenance, maintenance_print_symbols, _("\
 Print dump of current symbol definitions.\n\
-Entries in the full symbol table are dumped to file OUTFILE.\n\
-If a SOURCE file is specified, dump only that file's symbols."),
+Usage: mt print symbols [-pc address] [outfile]\n\
+       mt print symbols [-objfile objfile] [-source source] [outfile]\n\
+Entries in the full symbol table are dumped to file OUTFILE,\n\
+or the terminal if OUTFILE is unspecified.\n\
+If ADDRESS is provided, dump only the file for that address.\n\
+If SOURCE is provided, dump only that file's symbols.\n\
+If OBJFILE is provided, dump only that file's minimal symbols."),
 	   &maintenanceprintlist);
 
   add_cmd ("msymbols", class_maintenance, maintenance_print_msymbols, _("\
 Print dump of current minimal symbol definitions.\n\
-Entries in the minimal symbol table are dumped to file OUTFILE.\n\
-If a SOURCE file is specified, dump only that file's minimal symbols."),
+Usage: mt print msymbols [-objfile objfile] [outfile]\n\
+Entries in the minimal symbol table are dumped to file OUTFILE,\n\
+or the terminal if OUTFILE is unspecified.\n\
+If OBJFILE is provided, dump only that file's minimal symbols."),
 	   &maintenanceprintlist);
 
   add_cmd ("objfiles", class_maintenance, maintenance_print_objfiles,
diff --git a/gdb/testsuite/gdb.base/maint.exp b/gdb/testsuite/gdb.base/maint.exp
index f926c8b..c13d5de 100644
--- a/gdb/testsuite/gdb.base/maint.exp
+++ b/gdb/testsuite/gdb.base/maint.exp
@@ -207,55 +207,53 @@  if { ! $have_gdb_index } {
 }
 maint_pass_if $symtabs  "maint print objfiles: symtabs"
 
-gdb_test "maint print psymbols" \
-    "print-psymbols takes an output file name and optional symbol file name" \
-    "maint print psymbols w/o args"
-
 if { ! $have_gdb_index } {
     set psymbols_output [standard_output_file psymbols_output]
-    send_gdb "maint print psymbols $psymbols_output ${srcdir}/${subdir}/${srcfile}\n"
-    gdb_expect  {
-	-re "^maint print psymbols $psymbols_output \[^\n\]*\r\n$gdb_prompt $" {
-	    send_gdb "shell ls $psymbols_output\n"
-	    gdb_expect {
-		-re "$psymbols_output\r\n$gdb_prompt $" {
-		    # We want this grep to be as specific as possible,
-		    # so it's less likely to match symbol file names in
-		    # psymbols_output.  Yes, this actually happened;
-		    # poor expect got tons of output, and timed out
-		    # trying to match it.   --- Jim Blandy <jimb@cygnus.com>
-		    send_gdb "shell grep 'main.*function' $psymbols_output\n"
+    set test_list [list \
+		       "maint print psymbols -source" \
+		       "maint print psymbols -source ${srcdir}/${subdir}/${srcfile} $psymbols_output" \
+		       "maint print psymbols -pc" \
+		       "maint print psymbols -pc main $psymbols_output"]
+    foreach { test_name command } $test_list {
+	send_gdb "$command\n"
+	    gdb_expect  {
+		-re "^maint print psymbols \[^\n\]*\r\n$gdb_prompt $" {
+		    send_gdb "shell ls $psymbols_output\n"
 		    gdb_expect {
-			-re ".main., function, $hex.*$gdb_prompt $" {
-			    pass "maint print psymbols 1"
-			}
-			-re ".*main.  .., function, $hex.*$gdb_prompt $" {
-			    pass "maint print psymbols 2"
+			-re "$psymbols_output\r\n$gdb_prompt $" {
+			    # We want this grep to be as specific as possible,
+			    # so it's less likely to match symbol file names in
+			    # psymbols_output.  Yes, this actually happened;
+			    # poor expect got tons of output, and timed out
+			    # trying to match it.   --- Jim Blandy <jimb@cygnus.com>
+			    send_gdb "shell grep 'main.*function' $psymbols_output\n"
+			    gdb_expect {
+				-re ".main., function, $hex.*$gdb_prompt $" {
+				    pass "$test_name 1"
+				}
+				-re ".*main.  .., function, $hex.*$gdb_prompt $" {
+				    pass "$test_name 2"
+				}
+				-re ".*$gdb_prompt $" { fail "$test_name" }
+				timeout { fail "$test_name (timeout)" }
+			    }
+			    gdb_test "shell rm -f $psymbols_output" ".*" \
+				"shell rm -f psymbols_output"
 			}
-			-re ".*$gdb_prompt $" { fail "maint print psymbols" }
-			timeout     { fail "(timeout) maint print psymbols" }
+			-re ".*$gdb_prompt $" { fail "$test_name" }
+			timeout { fail "$test_name (timeout)" }
 		    }
-		    gdb_test "shell rm -f $psymbols_output" ".*" \
-			"shell rm -f psymbols_output"
 		}
-		-re ".*$gdb_prompt $"       { fail "maint print psymbols" }
-		timeout           { fail "(timeout) maint print psymbols" }
+		-re ".*$gdb_prompt $" { fail "$test_name" }
+		timeout { fail "$test_name (timeout)" }
 	    }
 	}
-	-re ".*$gdb_prompt $"       { fail "maint print psymbols" }
-	timeout           { fail "(timeout) maint print psymbols" }
-    }
 }
 
-gdb_test "maint print msymbols" \
-    "print-msymbols takes an output file name and optional symbol file name" \
-    "maint print msymbols w/o args"
-
-
 set msymbols_output [standard_output_file msymbols_output]
-send_gdb "maint print msymbols $msymbols_output ${binfile}\n"
+send_gdb "maint print msymbols -objfile ${binfile} $msymbols_output\n"
 gdb_expect  {
-    -re "^maint print msymbols $msymbols_output \[^\n\]*\r\n$gdb_prompt $" {
+    -re "^maint print msymbols \[^\n\]*\r\n$gdb_prompt $" {
 	send_gdb "shell ls $msymbols_output\n"
 	gdb_expect {
 	    -re "$msymbols_output\r\n$gdb_prompt $" {
@@ -264,18 +262,18 @@  gdb_expect  {
 		    -re "\\\[ *$decimal\\\] \[tT\]\[ \t\]+$hex \\.?factorial.*$gdb_prompt $" {
 			pass "maint print msymbols"
 		    }
-		    -re ".*$gdb_prompt $"     { fail "maint print msymbols" }
-		    timeout         { fail "(timeout) maint print msymbols" }
+		    -re ".*$gdb_prompt $" { fail "maint print msymbols" }
+		    timeout { fail "maint print msymbols (timeout)" }
 		}
 		gdb_test "shell rm -f $msymbols_output" ".*" \
 		    "shell rm -f msymbols_output"
 	    }
-	    -re ".*$gdb_prompt $"     { fail "maint print msymbols" }
-	    timeout         { fail "(timeout) maint print msymbols" }
+	    -re ".*$gdb_prompt $" { fail "maint print msymbols" }
+	    timeout { fail "maint print msymbols (timeout)" }
 	}
     }
-    -re ".*$gdb_prompt $"     { fail "maint print msymbols" }
-    timeout         { fail "(timeout) maint print msymbols" }
+    -re ".*$gdb_prompt $" { fail "maint print msymbols" }
+    timeout { fail "maint print msymbols (timeout)" }
 }
 
 # Check that maint print msymbols allows relative pathnames
@@ -284,8 +282,8 @@  gdb_test "cd [standard_output_file {}]" \
     "Working directory .*\..*" \
     "cd to objdir"
 
-gdb_test_multiple "maint print msymbols msymbols_output2 ${testfile}" "maint print msymbols" {
-    -re "^maint print msymbols msymbols_output2 \[^\n\]*\r\n$gdb_prompt $" {
+gdb_test_multiple "maint print msymbols -objfile ${testfile} msymbols_output2" "maint print msymbols" {
+    -re "^maint print msymbols \[^\n\]*\r\n$gdb_prompt $" {
     	gdb_test_multiple "shell ls msymbols_output2" "maint print msymbols" {
 	    -re "msymbols_output2\r\n$gdb_prompt $" {
 	    	gdb_test_multiple "shell grep factorial msymbols_output2" "maint print msymbols" {
@@ -296,7 +294,7 @@  gdb_test_multiple "maint print msymbols msymbols_output2 ${testfile}" "maint pri
 		        fail "maint print msymbols"
 		    }
 		    timeout {
-		        fail "(timeout) maint print msymbols"
+		        fail "maint print msymbols (timeout)"
 		    }
 		}
 		gdb_test "shell rm -f msymbols_output2" ".*" \
@@ -306,7 +304,7 @@  gdb_test_multiple "maint print msymbols msymbols_output2 ${testfile}" "maint pri
 		fail "maint print msymbols"
 	    }
 	    timeout {
-	    	fail "(timeout) maint print msymbols"
+	    	fail "maint print msymbols (timeout)"
 	    }
 	}
     }
@@ -314,47 +312,50 @@  gdb_test_multiple "maint print msymbols msymbols_output2 ${testfile}" "maint pri
 	fail "maint print msymbols"
     }
     timeout {
-	fail "(timeout) maint print msymbols"
+	fail "maint print msymbols (timeout)"
     }
 }
 gdb_test "cd ${mydir}" \
     "Working directory [string_to_regexp ${mydir}]\..*" \
     "cd to mydir"
 
-gdb_test "maint print symbols" \
-    "Arguments missing: an output file name and an optional symbol file name" \
-    "maint print symbols w/o args"
-
 
 # Request symbols for one particular source file so that we don't try to
 # dump the symbol information for the entire C library - over 500MB nowadays
 # for GNU libc.
 
 set symbols_output [standard_output_file symbols_output]
-send_gdb "maint print symbols $symbols_output ${srcdir}/${subdir}/${srcfile}\n"
-gdb_expect  {
-    -re "^maint print symbols $symbols_output \[^\n\]*\r\n$gdb_prompt $" {
-	send_gdb "shell ls $symbols_output\n"
-	gdb_expect {
-	    -re "$symbols_output\r\n$gdb_prompt $" {
-		# See comments for `maint print psymbols'.
-		send_gdb "shell grep 'main(.*block' $symbols_output\n"
-		gdb_expect {
-		    -re "int main\\(int, char \\*\\*, char \\*\\*\\); block.*$gdb_prompt $" {
-			pass "maint print symbols"
+set test_list [list \
+		   "maint print symbols -source" \
+		   "maint print symbols -source ${srcdir}/${subdir}/${srcfile} $symbols_output" \
+		   "maint print symbols -pc" \
+		   "maint print symbols -pc main $symbols_output"]
+foreach { test_name command } $test_list {
+    send_gdb "$command\n"
+    gdb_expect {
+	-re "^maint print symbols \[^\n\]*\r\n$gdb_prompt $" {
+	    send_gdb "shell ls $symbols_output\n"
+	    gdb_expect {
+		-re "$symbols_output\r\n$gdb_prompt $" {
+		    # See comments for `maint print psymbols'.
+		    send_gdb "shell grep 'main(.*block' $symbols_output\n"
+		    gdb_expect {
+			-re "int main\\(int, char \\*\\*, char \\*\\*\\); block.*$gdb_prompt $" {
+			    pass "$test_name"
+			}
+			-re ".*$gdb_prompt $" { fail "$test_name" }
+			timeout { fail "$test_name (timeout)" }
 		    }
-		    -re ".*$gdb_prompt $"     { fail "maint print symbols" }
-		    timeout         { fail "(timeout) maint print symbols" }
+		    gdb_test "shell rm -f $symbols_output" ".*" \
+			"shell rm -f symbols_output"
 		}
-		gdb_test "shell rm -f $symbols_output" ".*" \
-		    "shell rm -f symbols_output"
+		-re ".*$gdb_prompt $" { fail "$test_name" }
+		timeout { fail "$test_name (timeout)" }
 	    }
-	    -re ".*$gdb_prompt $"     { fail "maint print symbols" }
-	    timeout         { fail "(timeout) maint print symbols" }
 	}
+	-re ".*$gdb_prompt $" { fail "$test_name" }
+	timeout { fail "$test_name (timeout)" }
     }
-    -re ".*$gdb_prompt $"     { fail "maint print symbols" }
-    timeout         { fail "(timeout) maint print symbols" }
 }
 
 set msg "maint print type"