From patchwork Sun May 3 14:08:07 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kratochvil X-Patchwork-Id: 6544 Received: (qmail 93062 invoked by alias); 3 May 2015 14:08:14 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 93001 invoked by uid 89); 3 May 2015 14:08:13 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.1 required=5.0 tests=AWL, BAYES_00, KAM_STOCKGEN, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Sun, 03 May 2015 14:08:11 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (Postfix) with ESMTPS id 66F268E7A3 for ; Sun, 3 May 2015 14:08:10 +0000 (UTC) Received: from host1.jankratochvil.net (ovpn-116-27.ams2.redhat.com [10.36.116.27]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t43E887Y024508; Sun, 3 May 2015 10:08:09 -0400 Subject: [PATCH v4 10/11] compile: compile printf: gdbserver support From: Jan Kratochvil To: gdb-patches@sourceware.org Cc: Phil Muldoon Date: Sun, 03 May 2015 16:08:07 +0200 Message-ID: <20150503140807.18583.31477.stgit@host1.jankratochvil.net> In-Reply-To: <20150503140647.18583.2012.stgit@host1.jankratochvil.net> References: <20150503140647.18583.2012.stgit@host1.jankratochvil.net> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-IsSubscribed: yes 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 * 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 * gdb.texinfo (Compiling and Injecting Code): Mention for compile printf open_memstream and fprintf. gdb/testsuite/ChangeLog 2015-04-06 Jan Kratochvil * gdb.compile/compile-print.exp (compile printf "0x%x\n", varint) (compile printf "0x%x\n"): Remove !is_remote conditional. --- gdb/compile/compile-c-support.c | 21 ++++++++-- gdb/compile/compile-object-load.c | 3 + gdb/compile/compile-object-run.c | 56 ++++++++++++++++++++++++++- gdb/doc/gdb.texinfo | 4 +- gdb/testsuite/gdb.compile/compile-print.exp | 6 +-- 5 files changed, 77 insertions(+), 13 deletions(-) diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c index 684d328..14805bc 100644 --- a/gdb/compile/compile-c-support.c +++ b/gdb/compile/compile-c-support.c @@ -209,13 +209,21 @@ add_code_header (enum compile_i_scope_types type, struct ui_file *buf) break; case COMPILE_I_PRINTF_SCOPE: fputs_unfiltered ("#include \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: @@ -234,10 +242,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: @@ -433,7 +446,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 852f875..0be47ca 100644 --- a/gdb/compile/compile-object-load.c +++ b/gdb/compile/compile-object-load.c @@ -652,7 +652,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 87145db..067f549 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. */ @@ -101,6 +102,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. @@ -119,6 +134,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; @@ -138,7 +154,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); @@ -165,8 +181,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 8277fb5..ba819a4 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -17243,7 +17243,9 @@ 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. +inferior or cause other undefined inferior behavior. 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\\."