Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Kevin Buettner <kevinb@redhat.com>
To: gdb-patches@sourceware.org
Cc: Kevin Buettner <kevinb@redhat.com>
Subject: [PATCH 2/3] Add -P command line switch for executing Python scripts
Date: Sun, 21 Jul 2019 23:54:00 -0000	[thread overview]
Message-ID: <20190721235427.21893-3-kevinb@redhat.com> (raw)
In-Reply-To: <20190721235427.21893-1-kevinb@redhat.com>

This commit introduces a new command line switch to GDB, a -P /
--python switch which is used for executing a python script.
Encountering -P curtails normal argument processing by GDB; any
remaining arguments (after the script name) are passed to the
script.

This is work that was originally written as part of the Archer
project.  The original/primary author is Tom Tromey, but it has
been maintained for the Fedora project by Jan Kratochvil, Sergio
Durigan Junior, and perhaps others too.

In its original form, and even in the form found within the Fedora
sources, the code implementing the -P switch had several properties
which I found to be surprising:

1) After script execution, exit() was called which (obviously)
   caused GDB to exit.
2) The printing of GDB's banner (copyright info, bug reporting
   instructions, and help instructions) was suppressed.
3) Due to the exit() noted above, GDB's CLI was not (automatically)
   invoked.  If the CLI was desired, it could be run from the Python
   script via use of the gdb.cli method, which was added as part of
   that work.

I've changed things so that exit() is no longer called.  GDB's CLI
will be invoked after script execution.  Also, GDB's banner will be
printed (or not) as normal.  I.e, the banner will be printed unless
the -q switch is specified.

If the script doesn't want the CLI for some reason, it can explicitly
call exit().  It may be the case that the script would be better off
calling a (yet to be written) gdb.exit() method for doing this
instead.  Such a method could make sure that GDB shuts down properly.

gdb/ChangeLog:

	* main.c (python/python.h): Include.
	(captured_main_1): Add option processing and other support for -P
	switch.
	(captured_main): Add help messages for -P.
	* python/python.h (run_python_script): Declare.
	* python/python.c (run_python_script): New function.
---
 gdb/main.c          | 48 ++++++++++++++++++++++++++++++++++++++------
 gdb/python/python.c | 49 +++++++++++++++++++++++++++++++++++++++++++++
 gdb/python/python.h |  2 ++
 3 files changed, 93 insertions(+), 6 deletions(-)

diff --git a/gdb/main.c b/gdb/main.c
index 678c413021..bc8238e3ce 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -33,6 +33,7 @@
 
 #include "interps.h"
 #include "main.h"
+#include "python/python.h"
 #include "source.h"
 #include "cli/cli-cmds.h"
 #include "objfiles.h"
@@ -440,7 +441,7 @@ struct cmdarg
 };
 
 static void
-captured_main_1 (struct captured_main_args *context)
+captured_main_1 (struct captured_main_args *context, bool &python_script)
 {
   int argc = context->argc;
   char **argv = context->argv;
@@ -658,10 +659,14 @@ captured_main_1 (struct captured_main_args *context)
       {"args", no_argument, &set_args, 1},
       {"l", required_argument, 0, 'l'},
       {"return-child-result", no_argument, &return_child_result, 1},
+#if HAVE_PYTHON
+      {"python", no_argument, 0, 'P'},
+      {"P", no_argument, 0, 'P'},
+#endif
       {0, no_argument, 0, 0}
     };
 
-    while (1)
+    while (!python_script)
       {
 	int option_index;
 
@@ -679,6 +684,9 @@ captured_main_1 (struct captured_main_args *context)
 	  case 0:
 	    /* Long option that just sets a flag.  */
 	    break;
+	  case 'P':
+	    python_script = true;
+	    break;
 	  case OPT_SE:
 	    symarg = optarg;
 	    execarg = optarg;
@@ -858,7 +866,20 @@ captured_main_1 (struct captured_main_args *context)
 
   /* Now that gdb_init has created the initial inferior, we're in
      position to set args for that inferior.  */
-  if (set_args)
+  if (python_script)
+    {
+      /* The first argument is a python script to evaluate, and
+	 subsequent arguments are passed to the script for
+	 processing there.  */
+      if (optind >= argc)
+	{
+	  fprintf_unfiltered (gdb_stderr,
+			      _("%s: Python script file name required\n"),
+			      argv[0]);
+	  exit (1);
+	}
+    }
+  else if (set_args)
     {
       /* The remaining options are the command-line options for the
 	 inferior.  The first one is the sym/exec file, and the rest
@@ -1157,9 +1178,14 @@ static void
 captured_main (void *data)
 {
   struct captured_main_args *context = (struct captured_main_args *) data;
+  bool python_script = false;
 
-  captured_main_1 (context);
+  captured_main_1 (context, python_script);
 
+#if HAVE_PYTHON
+  if (python_script)
+    run_python_script (context->argc - optind, &context->argv[optind]);
+#endif
   /* NOTE: cagney/1999-11-07: There is probably no reason for not
      moving this loop and the code found in captured_command_loop()
      into the command_loop() proper.  The main thing holding back that
@@ -1215,9 +1241,12 @@ print_gdb_help (struct ui_file *stream)
   fputs_unfiltered (_("\
 This is the GNU debugger.  Usage:\n\n\
     gdb [options] [executable-file [core-file or process-id]]\n\
-    gdb [options] --args executable-file [inferior-arguments ...]\n\n\
-"), stream);
+    gdb [options] --args executable-file [inferior-arguments ...]\n"), stream);
+#if HAVE_PYTHON
   fputs_unfiltered (_("\
+    gdb [options] [--python|-P] script-file [script-arguments ...]\n"), stream);
+#endif
+  fputs_unfiltered (_("\n\
 Selection of debuggee and its files:\n\n\
   --args             Arguments after executable-file are passed to inferior\n\
   --core=COREFILE    Analyze the core dump COREFILE.\n\
@@ -1260,6 +1289,13 @@ Output and user interface control:\n\n\
 #endif
   fputs_unfiltered (_("\
   --dbx              DBX compatibility mode.\n\
+"), stream);
+#if HAVE_PYTHON
+  fputs_unfiltered (_("\
+  --python, -P       Following argument is Python script file; remaining\n\
+                     arguments are passed to script.\n"), stream);
+#endif
+  fputs_unfiltered (_("\
   -q, --quiet, --silent\n\
                      Do not print version number on startup.\n\n\
 "), stream);
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 96bee7c3b0..7bd4d1684f 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -1276,6 +1276,55 @@ gdbpy_print_stack_or_quit ()
 
 \f
 
+/* Set up the Python argument vector and evaluate a script.  This is
+   used to implement 'gdb -P'.  */
+
+void
+run_python_script (int argc, char **argv)
+{
+  if (!gdb_python_initialized)
+    return;
+
+  gdbpy_enter enter_py (get_current_arch (), current_language);
+
+#if PYTHON_ABI_VERSION < 3
+  PySys_SetArgv (argc - 1, argv + 1);
+#else
+  {
+    wchar_t **wargv = (wchar_t **) alloca (sizeof (*wargv) * (argc + 1));
+    int i;
+
+    for (i = 1; i < argc; i++)
+      {
+	size_t len = mbstowcs (NULL, argv[i], 0);
+
+	if (len == (size_t) -1)
+	  {
+	    fprintf (stderr, "Invalid multibyte argument #%d \"%s\"\n",
+		     i, argv[i]);
+	    exit (1);
+	  }
+	wargv[i] = (wchar_t *) alloca (sizeof (**wargv) * (len + 1));
+	size_t len2 = mbstowcs (wargv[i], argv[i], len + 1);
+	assert (len2 == len);
+      }
+    wargv[argc] = NULL;
+    PySys_SetArgv (argc - 1, wargv + 1);
+  }
+#endif
+
+  FILE *input = fopen (argv[0], "r");
+  if (! input)
+    {
+      fprintf (stderr, "could not open %s: %s\n", argv[0], strerror (errno));
+      exit (1);
+    }
+  PyRun_SimpleFile (input, argv[0]);
+  fclose (input);
+}
+
+\f
+
 /* Return a sequence holding all the Progspaces.  */
 
 static PyObject *
diff --git a/gdb/python/python.h b/gdb/python/python.h
index 10cd90d00e..2af0b2934d 100644
--- a/gdb/python/python.h
+++ b/gdb/python/python.h
@@ -28,4 +28,6 @@ extern const struct extension_language_defn extension_language_python;
 /* Command element for the 'python' command.  */
 extern cmd_list_element *python_cmd_element;
 
+extern void run_python_script (int argc, char **argv);
+
 #endif /* PYTHON_PYTHON_H */
-- 
2.21.0


  reply	other threads:[~2019-07-21 23:54 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-21 23:54 [PATCH 0/3] " Kevin Buettner
2019-07-21 23:54 ` Kevin Buettner [this message]
2019-07-23  2:47   ` [PATCH 2/3] " Simon Marchi
2019-07-23 20:25   ` Tom Tromey
2019-07-27 20:47     ` Kevin Buettner
2019-08-21 16:39     ` Pedro Alves
2019-07-21 23:54 ` [PATCH 3/3] Tests for Python -P commandline support Kevin Buettner
2019-07-21 23:54 ` [PATCH 1/3] Documentation " Kevin Buettner
2019-07-22 14:42   ` Eli Zaretskii
2019-07-22 16:04   ` Simon Marchi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190721235427.21893-3-kevinb@redhat.com \
    --to=kevinb@redhat.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox