Mirror of the gdb-patches mailing list
 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 v3 9/9] compile: compile printf: gdbserver support
Date: Sat, 11 Apr 2015 19:44:00 -0000	[thread overview]
Message-ID: <20150411194437.29128.58569.stgit@host1.jankratochvil.net> (raw)
In-Reply-To: <20150411194322.29128.52477.stgit@host1.jankratochvil.net>

Hi,

former patch injects plain:
	printf (...);
This patch injects gdbserver-compatible:
	f = open_memstream (&s, ...);
	fprintf (f, ...);
	fclose (f);
	return s;

Jan


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

	* compile/compile-c-support.c (add_code_header, add_code_footer)
	(c_compute_program): Use open_memstream, fprintf and fclose.
	* compile/compile-object-load.c (compile_object_load): Set expected
	char * for COMPILE_I_PRINTF_SCOPE.
	* compile/compile-object-run.c: Include gdbcore.h.
	(free_inferior_memory): New function.
	(compile_object_run): Support COMPILE_I_PRINTF_SCOPE's return value.

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

	* gdb.texinfo (Compiling and Injecting Code): Mention for compile
	printf open_memstream and fprintf.

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"): Remove !is_remote conditional.

diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c
index 92c41b6..3b9bb52 100644
--- a/gdb/compile/compile-c-support.c
+++ b/gdb/compile/compile-c-support.c
@@ -208,13 +208,21 @@ add_code_header (enum compile_i_scope_types type, struct ui_file *buf)
       break;
     case COMPILE_I_PRINTF_SCOPE:
       fputs_unfiltered ("#include <stdio.h>\n"
-			"void "
+			"char *"
 			GCC_FE_WRAPPER_FUNCTION
 			" (struct "
 			COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG
 			" *"
 			COMPILE_I_SIMPLE_REGISTER_ARG_NAME
-			") {\n",
+			") {\n"
+			"\tchar *__gdb_retval;\n"
+			"\tsize_t __gdb_retval_size;\n"
+			"\tFILE *__gdb_outf;\n"
+			"\n"
+			"\t__gdb_outf = open_memstream (&__gdb_retval, "
+						       "&__gdb_retval_size);\n"
+			"\tif (__gdb_outf == NULL)\n"
+			"\t\treturn NULL;\n",
 			buf);
       break;
     case COMPILE_I_RAW_SCOPE:
@@ -233,10 +241,15 @@ add_code_footer (enum compile_i_scope_types type, struct ui_file *buf)
 {
   switch (type)
     {
+    case COMPILE_I_PRINTF_SCOPE:
+      fputs_unfiltered ("\tif (fclose (__gdb_outf) != 0)\n"
+			"\t\treturn NULL;\n"
+			"\treturn __gdb_retval;\n",
+			buf);
+      // FALLTHRU
     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:
@@ -432,7 +445,7 @@ c_compute_program (struct compile_instance *inst,
       break;
     case COMPILE_I_PRINTF_SCOPE:
       fprintf_unfiltered (buf,
-"printf (%s);\n"
+"fprintf (__gdb_outf, %s);\n"
 			  , input);
       break;
     default:
diff --git a/gdb/compile/compile-object-load.c b/gdb/compile/compile-object-load.c
index bc74590..d7c13c9 100644
--- a/gdb/compile/compile-object-load.c
+++ b/gdb/compile/compile-object-load.c
@@ -651,7 +651,8 @@ compile_object_load (const char *object_file, const char *source_file,
       break;
     case COMPILE_I_PRINTF_SCOPE:
       expect_parameters = 1;
-      expect_return_type = builtin_type (target_gdbarch ())->builtin_void;
+      expect_return_type = lookup_pointer_type
+			       (builtin_type (target_gdbarch ())->builtin_char);
       break;
     default:
       internal_error (__FILE__, __LINE__, _("invalid scope %d"), scope);
diff --git a/gdb/compile/compile-object-run.c b/gdb/compile/compile-object-run.c
index 216cbf9..ed56410 100644
--- a/gdb/compile/compile-object-run.c
+++ b/gdb/compile/compile-object-run.c
@@ -27,6 +27,7 @@
 #include "block.h"
 #include "valprint.h"
 #include "compile.h"
+#include "gdbcore.h"

 /* Helper for do_module_cleanup.  */

@@ -99,6 +100,18 @@ do_module_cleanup (void *arg)
   xfree (data);
 }

+static void
+free_inferior_memory (CORE_ADDR addr)
+{
+  struct objfile *objf;
+  struct value *func_val = find_function_in_inferior ("free", &objf);
+  struct gdbarch *gdbarch = get_objfile_arch (objf);
+  struct type *addr_type = builtin_type (gdbarch)->builtin_data_ptr;
+  struct value *addr_val = value_from_pointer (addr_type, addr);
+
+  call_function_by_hand (func_val, 1, &addr_val);
+}
+
 /* Perform inferior call of MODULE.  This function may throw an error.
    This function may leave files referenced by MODULE on disk until
    the inferior call dummy frame is discarded.  This function may throw errors.
@@ -117,6 +130,7 @@ compile_object_run (struct compile_module *module)
   struct symbol *func_sym = module->func_sym;
   CORE_ADDR regs_addr = module->regs_addr;
   struct objfile *objfile = module->objfile;
+  enum compile_i_scope_types scope = module->scope;

   data = xmalloc (sizeof (*data) + strlen (objfile_name_s));
   data->executedp = &executed;
@@ -136,7 +150,7 @@ compile_object_run (struct compile_module *module)
       struct type *func_type = SYMBOL_TYPE (func_sym);
       htab_t copied_types;
       int current_arg = 0;
-      struct value **vargs;
+      struct value **vargs, *func_return_value;

       /* OBJFILE may disappear while FUNC_TYPE still will be in use.  */
       copied_types = create_copied_types_hash (objfile);
@@ -163,8 +177,42 @@ compile_object_run (struct compile_module *module)
 	  ++current_arg;
 	}
       gdb_assert (current_arg == TYPE_NFIELDS (func_type));
-      call_function_by_hand_dummy (func_val, TYPE_NFIELDS (func_type), vargs,
-				   do_module_cleanup, data);
+      func_return_value = call_function_by_hand_dummy (func_val,
+						       TYPE_NFIELDS (func_type),
+						       vargs,
+						       do_module_cleanup, data);
+
+      // DATA can be already freed now.
+      data = NULL;
+
+      if (scope == COMPILE_I_PRINTF_SCOPE)
+	{
+	  struct value_print_options opts;
+	  gdb_byte *buffer = NULL;
+	  struct cleanup *old_chain;
+	  int errcode, bytes_read;
+	  struct type *retval_type = value_type (func_return_value);
+	  struct type *char_type;
+
+	  gdb_assert (TYPE_CODE (retval_type) == TYPE_CODE_PTR);
+	  char_type = TYPE_TARGET_TYPE (retval_type);
+	  gdb_assert (TYPE_CODE (char_type) == TYPE_CODE_INT);
+
+	  get_user_print_options (&opts);
+	  errcode = read_string (value_as_address (func_return_value), -1,
+				 TYPE_LENGTH (char_type), opts.print_max,
+				 gdbarch_byte_order (target_gdbarch ()),
+				 &buffer, &bytes_read);
+	  old_chain = make_cleanup (xfree, buffer);
+	  if (errcode != 0)
+	    memory_error (errcode, value_as_address (func_return_value));
+
+	  while (bytes_read-- > 0)
+	    putchar_filtered (*buffer++);
+	  do_cleanups (old_chain);
+
+	  free_inferior_memory (value_as_address (func_return_value));
+	}
     }
   CATCH (ex, RETURN_MASK_ERROR)
     {
diff --git a/gdb/testsuite/gdb.compile/compile-print.exp b/gdb/testsuite/gdb.compile/compile-print.exp
index 14fd489..43b9f24 100644
--- a/gdb/testsuite/gdb.compile/compile-print.exp
+++ b/gdb/testsuite/gdb.compile/compile-print.exp
@@ -57,7 +57,5 @@ 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\\."
-}
+gdb_test {compile printf "0x%x\n", varint} "\r\n0xa"
+gdb_test {compile printf "0x%x\n"} "\r\nCompilation failed\\."
---
 gdb/doc/gdb.texinfo |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c
index 92c41b6..3b9bb52 100644
--- a/gdb/compile/compile-c-support.c
+++ b/gdb/compile/compile-c-support.c
@@ -208,13 +208,21 @@ add_code_header (enum compile_i_scope_types type, struct ui_file *buf)
       break;
     case COMPILE_I_PRINTF_SCOPE:
       fputs_unfiltered ("#include <stdio.h>\n"
-			"void "
+			"char *"
 			GCC_FE_WRAPPER_FUNCTION
 			" (struct "
 			COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG
 			" *"
 			COMPILE_I_SIMPLE_REGISTER_ARG_NAME
-			") {\n",
+			") {\n"
+			"\tchar *__gdb_retval;\n"
+			"\tsize_t __gdb_retval_size;\n"
+			"\tFILE *__gdb_outf;\n"
+			"\n"
+			"\t__gdb_outf = open_memstream (&__gdb_retval, "
+						       "&__gdb_retval_size);\n"
+			"\tif (__gdb_outf == NULL)\n"
+			"\t\treturn NULL;\n",
 			buf);
       break;
     case COMPILE_I_RAW_SCOPE:
@@ -233,10 +241,15 @@ add_code_footer (enum compile_i_scope_types type, struct ui_file *buf)
 {
   switch (type)
     {
+    case COMPILE_I_PRINTF_SCOPE:
+      fputs_unfiltered ("\tif (fclose (__gdb_outf) != 0)\n"
+			"\t\treturn NULL;\n"
+			"\treturn __gdb_retval;\n",
+			buf);
+      // FALLTHRU
     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:
@@ -432,7 +445,7 @@ c_compute_program (struct compile_instance *inst,
       break;
     case COMPILE_I_PRINTF_SCOPE:
       fprintf_unfiltered (buf,
-"printf (%s);\n"
+"fprintf (__gdb_outf, %s);\n"
 			  , input);
       break;
     default:
diff --git a/gdb/compile/compile-object-load.c b/gdb/compile/compile-object-load.c
index bc74590..d7c13c9 100644
--- a/gdb/compile/compile-object-load.c
+++ b/gdb/compile/compile-object-load.c
@@ -651,7 +651,8 @@ compile_object_load (const char *object_file, const char *source_file,
       break;
     case COMPILE_I_PRINTF_SCOPE:
       expect_parameters = 1;
-      expect_return_type = builtin_type (target_gdbarch ())->builtin_void;
+      expect_return_type = lookup_pointer_type
+			       (builtin_type (target_gdbarch ())->builtin_char);
       break;
     default:
       internal_error (__FILE__, __LINE__, _("invalid scope %d"), scope);
diff --git a/gdb/compile/compile-object-run.c b/gdb/compile/compile-object-run.c
index 216cbf9..3606d42 100644
--- a/gdb/compile/compile-object-run.c
+++ b/gdb/compile/compile-object-run.c
@@ -27,6 +27,7 @@
 #include "block.h"
 #include "valprint.h"
 #include "compile.h"
+#include "gdbcore.h"
 
 /* Helper for do_module_cleanup.  */
 
@@ -99,6 +100,20 @@ do_module_cleanup (void *arg)
   xfree (data);
 }
 
+/* Call inferior function "free" for ADDR.  */
+
+static void
+free_inferior_memory (CORE_ADDR addr)
+{
+  struct objfile *objf;
+  struct value *func_val = find_function_in_inferior ("free", &objf);
+  struct gdbarch *gdbarch = get_objfile_arch (objf);
+  struct type *addr_type = builtin_type (gdbarch)->builtin_data_ptr;
+  struct value *addr_val = value_from_pointer (addr_type, addr);
+
+  call_function_by_hand (func_val, 1, &addr_val);
+}
+
 /* Perform inferior call of MODULE.  This function may throw an error.
    This function may leave files referenced by MODULE on disk until
    the inferior call dummy frame is discarded.  This function may throw errors.
@@ -117,6 +132,7 @@ compile_object_run (struct compile_module *module)
   struct symbol *func_sym = module->func_sym;
   CORE_ADDR regs_addr = module->regs_addr;
   struct objfile *objfile = module->objfile;
+  enum compile_i_scope_types scope = module->scope;
 
   data = xmalloc (sizeof (*data) + strlen (objfile_name_s));
   data->executedp = &executed;
@@ -136,7 +152,7 @@ compile_object_run (struct compile_module *module)
       struct type *func_type = SYMBOL_TYPE (func_sym);
       htab_t copied_types;
       int current_arg = 0;
-      struct value **vargs;
+      struct value **vargs, *func_return_value;
 
       /* OBJFILE may disappear while FUNC_TYPE still will be in use.  */
       copied_types = create_copied_types_hash (objfile);
@@ -163,8 +179,42 @@ compile_object_run (struct compile_module *module)
 	  ++current_arg;
 	}
       gdb_assert (current_arg == TYPE_NFIELDS (func_type));
-      call_function_by_hand_dummy (func_val, TYPE_NFIELDS (func_type), vargs,
-				   do_module_cleanup, data);
+      func_return_value = call_function_by_hand_dummy (func_val,
+						       TYPE_NFIELDS (func_type),
+						       vargs,
+						       do_module_cleanup, data);
+
+      // DATA can be already freed now.
+      data = NULL;
+
+      if (scope == COMPILE_I_PRINTF_SCOPE)
+	{
+	  struct value_print_options opts;
+	  gdb_byte *buffer = NULL;
+	  struct cleanup *old_chain;
+	  int errcode, bytes_read;
+	  struct type *retval_type = value_type (func_return_value);
+	  struct type *char_type;
+
+	  gdb_assert (TYPE_CODE (retval_type) == TYPE_CODE_PTR);
+	  char_type = TYPE_TARGET_TYPE (retval_type);
+	  gdb_assert (TYPE_CODE (char_type) == TYPE_CODE_INT);
+
+	  get_user_print_options (&opts);
+	  errcode = read_string (value_as_address (func_return_value), -1,
+				 TYPE_LENGTH (char_type), opts.print_max,
+				 gdbarch_byte_order (target_gdbarch ()),
+				 &buffer, &bytes_read);
+	  old_chain = make_cleanup (xfree, buffer);
+	  if (errcode != 0)
+	    memory_error (errcode, value_as_address (func_return_value));
+
+	  while (bytes_read-- > 0)
+	    putchar_filtered (*buffer++);
+	  do_cleanups (old_chain);
+
+	  free_inferior_memory (value_as_address (func_return_value));
+	}
     }
   CATCH (ex, RETURN_MASK_ERROR)
     {
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6688674..fd7ff05 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -17239,7 +17239,9 @@ multiple-line editor.
 @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}).
+(@pxref{Languages}).  The value is printed by @value{GDBN} and not the
+inferior, inferior does not execute specifically the function
+@code{printf}.
 
 @item compile printf
 @cindex reprint the last value
diff --git a/gdb/testsuite/gdb.compile/compile-print.exp b/gdb/testsuite/gdb.compile/compile-print.exp
index 14fd489..43b9f24 100644
--- a/gdb/testsuite/gdb.compile/compile-print.exp
+++ b/gdb/testsuite/gdb.compile/compile-print.exp
@@ -57,7 +57,5 @@ 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\\."
-}
+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-04-11 19:44 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-11 19:43 [PATCH v3 0/9] compile: compile print&printf Jan Kratochvil
2015-04-11 19:43 ` [PATCH v3 1/9] Code cleanup: Make parts of print_command_1 public Jan Kratochvil
2015-04-29 15:44   ` Pedro Alves
2015-04-30  0:24     ` Jan Kratochvil
2015-04-11 19:43 ` [PATCH v3 3/9] Code cleanup: compile: Constify some parameters Jan Kratochvil
2015-04-29 15:47   ` Pedro Alves
2015-05-06 18:58     ` [commit] " Jan Kratochvil
2015-04-11 19:43 ` [PATCH v3 2/9] compile: Distribute scope, add scope_data Jan Kratochvil
2015-04-29 15:44   ` Pedro Alves
2015-04-11 19:44 ` [PATCH v3 4/9] compile: Support relocation to GNU-IFUNCs Jan Kratochvil
2015-04-29 15:48   ` Pedro Alves
2015-05-06 19:00     ` [commit] " Jan Kratochvil
2015-04-11 19:44 ` [PATCH v3 6/9] Code cleanup: compile: func_addr -> func_sym Jan Kratochvil
2015-04-29 15:52   ` Pedro Alves
2015-04-11 19:44 ` [PATCH v3 7/9] compile: New 'compile print' Jan Kratochvil
2015-04-29 15:53   ` Pedro Alves
2015-05-03 14:06     ` Jan Kratochvil
2015-05-06 10:22       ` Pedro Alves
2015-05-06 12:23         ` Jan Kratochvil
2015-05-06 14:11           ` Pedro Alves
2015-05-06 19:18             ` Jan Kratochvil
2015-05-15 16:35               ` Pedro Alves
2015-04-11 19:44 ` Jan Kratochvil [this message]
2015-04-26  9:33   ` [PATCH v3 9/9] compile: compile printf: gdbserver support Jan Kratochvil
2015-04-29 18:19     ` Pedro Alves
2015-05-03 14:06       ` Jan Kratochvil
2015-05-06 10:22         ` Pedro Alves
2015-04-29 16:12   ` Pedro Alves
2015-04-11 19:44 ` [PATCH v3 5/9] compile: Use -Wall, not -w Jan Kratochvil
2015-04-29 15:49   ` Pedro Alves
2015-05-03 14:05     ` Jan Kratochvil
2015-05-06 10:21       ` Pedro Alves
2015-04-11 19:44 ` [PATCH v3 8/9] compile: New compile printf Jan Kratochvil
2015-04-29 15:54   ` Pedro Alves
2015-05-03 14:06     ` Jan Kratochvil
2015-05-06 10:22       ` Pedro Alves
2015-05-06 11:30         ` Jan Kratochvil
2015-05-06 11:47           ` Pedro Alves

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=20150411194437.29128.58569.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