public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Jan Kratochvil <jan.kratochvil@redhat.com>
To: gdb-patches@sourceware.org
Cc: Phil Muldoon <pmuldoon@redhat.com>
Subject: [PATCH v4 09/11] compile: New compile printf
Date: Sun, 03 May 2015 14:08:00 -0000	[thread overview]
Message-ID: <20150503140759.18583.70510.stgit@host1.jankratochvil.net> (raw)
In-Reply-To: <20150503140647.18583.2012.stgit@host1.jankratochvil.net>

Hi,

command naming needs to follow what gets decided for 'compile print'.

This part sends the output to inferior stdout, only the next patch will
redirect it to GDB (so that for example it works for remote gdbserver).

It cannot work for core files as one cannot execute inferior code there.
There were some ideas such as compiling the entered sources into GCC
intermediate form (GIMPLE?) and interpret it by GDB on top of the core file.
That would be much more complicated, this implementation is made according to
Phil's specification.

Besides existing
	(gdb) set compile-args
there will be now also:
	(gdb) set compile-printf-args
Maybe it would be worth to start some set sub-category 'compile' such as:
	(gdb) set compile args
	(gdb) set compile printf-args
That would mean the whole process of deprecating 'set compile-args' etc.


Jan


gdb/ChangeLog
2015-04-06  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* compile/compile-c-support.c (add_code_header, add_code_footer)
	(c_compute_program): Add COMPILE_I_PRINTF_SCOPE.
	* compile/compile-object-load.c (get_regs_type): Verify 2nd parameter
	type.
	(compile_object_load): Add COMPILE_I_PRINTF_SCOPE.
	* compile/compile.c (compile_print_command): Rename to ...
	(compile_print): ... here.
	(compile_print_command, compile_printf_command, compile_printf_args)
	(compile_printf_args_argv, set_compile_printf_args)
	(show_compile_printf_args): New.
	(get_args): Add COMPILE_I_PRINTF_SCOPE support.
	(_initialize_compile): Install compile_printf_command,
	set_compile_printf_args and show_compile_printf_args.  Set default
	COMPILE_PRINTF_ARGS.
	* defs.h (enum compile_i_scope_types): Add COMPILE_I_PRINTF_SCOPE.

gdb/doc/ChangeLog
2015-04-06  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.texinfo (Compiling and Injecting Code): Add compile printf.

gdb/testsuite/ChangeLog
2015-04-06  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.compile/compile-print.exp (compile printf "0x%x\n", varint)
	(compile printf "0x%x\n"): New.
---
 gdb/compile/compile-c-support.c             |   21 ++++++
 gdb/compile/compile-object-load.c           |   18 +++++
 gdb/compile/compile.c                       |   93 +++++++++++++++++++++++++--
 gdb/defs.h                                  |    4 +
 gdb/doc/gdb.texinfo                         |   16 +++++
 gdb/testsuite/gdb.compile/compile-print.exp |    5 +
 6 files changed, 148 insertions(+), 9 deletions(-)

diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c
index 39f06c6..684d328 100644
--- a/gdb/compile/compile-c-support.c
+++ b/gdb/compile/compile-c-support.c
@@ -207,7 +207,17 @@ add_code_header (enum compile_i_scope_types type, struct ui_file *buf)
 			") {\n",
 			buf);
       break;
-
+    case COMPILE_I_PRINTF_SCOPE:
+      fputs_unfiltered ("#include <stdio.h>\n"
+			"void "
+			GCC_FE_WRAPPER_FUNCTION
+			" (struct "
+			COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG
+			" *"
+			COMPILE_I_SIMPLE_REGISTER_ARG_NAME
+			") {\n",
+			buf);
+      break;
     case COMPILE_I_RAW_SCOPE:
       break;
     default:
@@ -227,6 +237,7 @@ add_code_footer (enum compile_i_scope_types type, struct ui_file *buf)
     case COMPILE_I_SIMPLE_SCOPE:
     case COMPILE_I_PRINT_ADDRESS_SCOPE:
     case COMPILE_I_PRINT_VALUE_SCOPE:
+    case COMPILE_I_PRINTF_SCOPE:
       fputs_unfiltered ("}\n", buf);
       break;
     case COMPILE_I_RAW_SCOPE:
@@ -391,7 +402,8 @@ c_compute_program (struct compile_instance *inst,
 
   if (inst->scope == COMPILE_I_SIMPLE_SCOPE
       || inst->scope == COMPILE_I_PRINT_ADDRESS_SCOPE
-      || inst->scope == COMPILE_I_PRINT_VALUE_SCOPE)
+      || inst->scope == COMPILE_I_PRINT_VALUE_SCOPE
+      || inst->scope == COMPILE_I_PRINTF_SCOPE)
     {
       ui_file_put (var_stream, ui_file_write_for_put, buf);
       fputs_unfiltered ("#pragma GCC user_expression\n", buf);
@@ -419,6 +431,11 @@ c_compute_program (struct compile_instance *inst,
 			  (inst->scope == COMPILE_I_PRINT_ADDRESS_SCOPE
 			   ? "&" : ""));
       break;
+    case COMPILE_I_PRINTF_SCOPE:
+      fprintf_unfiltered (buf,
+"printf (%s);\n"
+			  , input);
+      break;
     default:
       fputs_unfiltered (input, buf);
       break;
diff --git a/gdb/compile/compile-object-load.c b/gdb/compile/compile-object-load.c
index ea7082c..852f875 100644
--- a/gdb/compile/compile-object-load.c
+++ b/gdb/compile/compile-object-load.c
@@ -471,7 +471,7 @@ static struct type *
 get_regs_type (struct symbol *func_sym, struct objfile *objfile)
 {
   struct type *func_type = SYMBOL_TYPE (func_sym);
-  struct type *regsp_type, *regs_type;
+  struct type *regsp_type, *regs_type, *void_type, *voidp_type;
 
   /* No register parameter present.  */
   if (TYPE_NFIELDS (func_type) == 0)
@@ -491,6 +491,18 @@ get_regs_type (struct symbol *func_sym, struct objfile *objfile)
 	   TYPE_CODE (regs_type), GCC_FE_WRAPPER_FUNCTION,
 	   objfile_name (objfile));
 
+  /* No register parameter present.  */
+  if (TYPE_NFIELDS (func_type) == 1)
+    return regs_type;
+
+  void_type = builtin_type (target_gdbarch ())->builtin_void;
+  voidp_type = lookup_pointer_type (void_type);
+  if (!types_deeply_equal (voidp_type, TYPE_FIELD_TYPE (func_type, 1)))
+    error (_("Invalid type of function \"%s\" parameter \"%s\" in compiled "
+	    "module \"%s\"."),
+	  GCC_FE_WRAPPER_FUNCTION, COMPILE_I_PRINT_OUT_ARG,
+	  objfile_name (objfile));
+
   return regs_type;
 }
 
@@ -638,6 +650,10 @@ compile_object_load (const char *object_file, const char *source_file,
       expect_parameters = 2;
       expect_return_type = builtin_type (target_gdbarch ())->builtin_void;
       break;
+    case COMPILE_I_PRINTF_SCOPE:
+      expect_parameters = 1;
+      expect_return_type = builtin_type (target_gdbarch ())->builtin_void;
+      break;
     default:
       internal_error (__FILE__, __LINE__, _("invalid scope %d"), scope);
     }
diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
index fbecf8c..344674d 100644
--- a/gdb/compile/compile.c
+++ b/gdb/compile/compile.c
@@ -174,17 +174,14 @@ compile_print_value (struct value *val, void *data_voidp)
   print_value (val, fmtp);
 }
 
-/* Handle the input from the 'compile print' command.  The "compile
-   print" command is used to evaluate and print an expression that may
-   contain calls to the GCC compiler.  The language expected in this
-   compile command is the language currently set in GDB.  */
+/* Implement 'compile print' and 'compile printf' command according
+   to SCOPE.  */
 
 static void
-compile_print_command (char *arg_param, int from_tty)
+compile_print (char *arg_param, enum compile_i_scope_types scope)
 {
   const char *arg = arg_param;
   struct cleanup *cleanup;
-  enum compile_i_scope_types scope = COMPILE_I_PRINT_ADDRESS_SCOPE;
   struct format_data fmt;
 
   cleanup = make_cleanup_restore_integer (&interpreter_async);
@@ -209,6 +206,25 @@ compile_print_command (char *arg_param, int from_tty)
   do_cleanups (cleanup);
 }
 
+/* Handle the input from the 'compile print' command.  The "compile
+   print" command is used to evaluate and print an expression that may
+   contain calls to the GCC compiler.  The language expected in this
+   compile command is the language currently set in GDB.  */
+
+static void
+compile_print_command (char *arg, int from_tty)
+{
+  compile_print (arg, COMPILE_I_PRINT_ADDRESS_SCOPE);
+}
+
+/* Handle the input from the 'compile printf' command.  */
+
+static void
+compile_printf_command (char *arg, int from_tty)
+{
+  compile_print (arg, COMPILE_I_PRINTF_SCOPE);
+}
+
 /* A cleanup function to remove a directory and all its contents.  */
 
 static void
@@ -310,6 +326,14 @@ static char *compile_args;
 static int compile_args_argc;
 static char **compile_args_argv;
 
+/* String for 'set compile-printf-args' and 'show compile-printf-args'.  */
+static char *compile_printf_args;
+
+/* Parsed form of COMPILE_PRINTF_ARGS.
+   COMPILE_PRINTF_ARGS_ARGV is NULL terminated.  */
+static int compile_printf_args_argc;
+static char **compile_printf_args_argv;
+
 /* Implement 'set compile-args'.  */
 
 static void
@@ -330,6 +354,27 @@ show_compile_args (struct ui_file *file, int from_tty,
 		    value);
 }
 
+/* Implement 'set compile-printf-args'.  */
+
+static void
+set_compile_printf_args (char *args, int from_tty, struct cmd_list_element *c)
+{
+  freeargv (compile_printf_args_argv);
+  build_argc_argv (compile_printf_args,
+		   &compile_printf_args_argc, &compile_printf_args_argv);
+}
+
+/* Implement 'show compile-printf-args'.  */
+
+static void
+show_compile_printf_args (struct ui_file *file, int from_tty,
+		   struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Compile printf command command-line arguments "
+			    "are \"%s\".\n"),
+		    value);
+}
+
 /* Append ARGC and ARGV (as parsed by build_argc_argv) to *ARGCP and *ARGVP.
    ARGCP+ARGVP can be zero+NULL and also ARGC+ARGV can be zero+NULL.  */
 
@@ -424,6 +469,10 @@ get_args (const struct compile_instance *compiler, struct gdbarch *gdbarch,
   freeargv (argv_compiler);
 
   append_args (argcp, argvp, compile_args_argc, compile_args_argv);
+
+  if (compiler->scope == COMPILE_I_PRINTF_SCOPE)
+    append_args (argcp, argvp,
+		 compile_printf_args_argc, compile_printf_args_argv);
 }
 
 /* A cleanup function to destroy a gdb_gcc_instance.  */
@@ -725,6 +774,24 @@ EXPR may be preceded with /FMT, where FMT is a format letter\n\
 but no count or size letter (see \"x\" command)."),
 	   &compile_command_list);
 
+  add_cmd ("printf", class_obscure, compile_printf_command,
+	   _("\
+Print formatted output with the compiler.\n\
+\n\
+Usage: compile printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\
+\n\
+The arguments may be specified on the same line as the command, e.g.:\n\
+\n\
+    compile printf \"%d\\n\", i\n\
+\n\
+Alternatively, you can type the arguments interactively.\n\
+You can invoke this mode when no argument is given to the command\n\
+(i.e., \"compile printf\" is typed with nothing after it).  An\n\
+interactive prompt will be shown allowing you to enter multiple\n\
+lines of source code.  Type a line containing \"end\" to indicate\n\
+the end of the source code."),
+	   &compile_command_list);
+
   add_setshow_boolean_cmd ("compile", class_maintenance, &compile_debug, _("\
 Set compile command debugging."), _("\
 Show compile command debugging."), _("\
@@ -742,6 +809,17 @@ String quoting is parsed like in shell, for example:\n\
   -mno-align-double \"-I/dir with a space/include\""),
 			  set_compile_args, show_compile_args, &setlist, &showlist);
 
+  add_setshow_string_cmd ("compile-printf-args", class_support,
+			  &compile_printf_args,
+			  _("Set compile printf command "
+			    "GCC command-line arguments"),
+			  _("Show compile printf command "
+			    "GCC command-line arguments"),
+			  _("\
+Use options like -Werror which get added for 'compile printf' command."),
+			  set_compile_printf_args, show_compile_printf_args,
+			  &setlist, &showlist);
+
   /* Override flags possibly coming from DW_AT_producer.  */
   compile_args = xstrdup ("-O0 -gdwarf-4"
   /* We use -fPIE Otherwise GDB would need to reserve space large enough for
@@ -760,4 +838,7 @@ String quoting is parsed like in shell, for example:\n\
 			 " -fno-stack-protector"
   );
   set_compile_args (compile_args, 0, NULL);
+
+  compile_printf_args = xstrdup ("-Werror=format");
+  set_compile_printf_args (compile_printf_args, 0, NULL);
 }
diff --git a/gdb/defs.h b/gdb/defs.h
index 1c6f118..a62740a 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -79,6 +79,10 @@ enum compile_i_scope_types
        name already specifies its address.  */
     COMPILE_I_PRINT_ADDRESS_SCOPE,
     COMPILE_I_PRINT_VALUE_SCOPE,
+
+    /* Implement the "compile printf" command.  SCOPE_DATA contains
+       string containing the format string together with its arguments.  */
+    COMPILE_I_PRINTF_SCOPE,
   };
 
 /* Just in case they're not defined in stdio.h.  */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 0b6d6b0..8277fb5 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -17237,6 +17237,22 @@ command without any text following the command.  This will start the
 multiple-line editor.
 @end table
 
+@table @code
+@item compile printf @var{template}, @var{expressions}@dots{}
+Compile and execute @code{printf} function call with the compiler
+language found as the current language in @value{GDBN}
+(@pxref{Languages}).  This command is not asynchronous signal safe for
+the inferior, calling it in an inappropriate moment may crash the
+inferior or cause other undefined inferior behavior.
+
+@item compile printf
+@cindex reprint the last value
+Alternatively you can enter the template and expression (source code
+producing them) as multiple lines of text.  To enter this mode, invoke
+the @samp{compile printf} command without any text following the
+command.  This will start the multiple-line editor.
+@end table
+
 @noindent
 The process of compiling and injecting the code can be inspected using:
 
diff --git a/gdb/testsuite/gdb.compile/compile-print.exp b/gdb/testsuite/gdb.compile/compile-print.exp
index 92c6240..14fd489 100644
--- a/gdb/testsuite/gdb.compile/compile-print.exp
+++ b/gdb/testsuite/gdb.compile/compile-print.exp
@@ -56,3 +56,8 @@ gdb_test "compile print/x 256" " = 0x100"
 gdb_test {print $} " = 256"
 
 gdb_test "compile print varobject" { = {field = 1}}
+
+if ![is_remote target] {
+    gdb_test {compile printf "0x%x\n", varint} "\r\n0xa"
+    gdb_test {compile printf "0x%x\n"} "\r\nCompilation failed\\."
+}

  parent reply	other threads:[~2015-05-03 14:08 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-03 14:06 [PATCH v4 00/11] compile: compile print&printf Jan Kratochvil
2015-05-03 14:07 ` [PATCH v4 01/11] compile: Add one debug message Jan Kratochvil
2015-05-03 14:07 ` [PATCH v4 07/11] Code cleanup: compile: func_addr -> func_sym Jan Kratochvil
2015-05-03 14:07 ` [PATCH v4 03/11] compile: Distribute scope, add scope_data Jan Kratochvil
2015-05-03 14:07 ` [PATCH v4 05/11] compile: Support relocation to GNU-IFUNCs Jan Kratochvil
2015-05-03 14:07 ` [PATCH v4 02/11] Code cleanup: Make parts of print_command_1 public Jan Kratochvil
2015-05-03 14:07 ` [PATCH v4 08/11] compile: New 'compile print' Jan Kratochvil
2015-05-03 14:07 ` [PATCH v4 04/11] Code cleanup: compile: Constify some parameters Jan Kratochvil
2015-05-03 14:07 ` [PATCH v4 06/11] compile: Use -Wall, not -w Jan Kratochvil
2015-05-03 14:08 ` [PATCH v4 11/11] RFC only: compile: Use also inferior munmap Jan Kratochvil
2015-05-06 15:21   ` Pedro Alves
2015-05-06 19:32     ` Jan Kratochvil
2015-05-08 20:23       ` Jan Kratochvil
2015-05-03 14:08 ` Jan Kratochvil [this message]
2015-05-03 14:08 ` [PATCH v4 10/11] compile: compile printf: gdbserver support Jan Kratochvil

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=20150503140759.18583.70510.stgit@host1.jankratochvil.net \
    --to=jan.kratochvil@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=pmuldoon@redhat.com \
    /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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).