@@ -206,7 +206,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:
@@ -226,6 +236,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:
@@ -390,7 +401,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);
@@ -418,6 +430,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;
@@ -470,7 +470,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)
@@ -490,6 +490,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;
}
@@ -637,6 +649,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);
}
@@ -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 *fmtp;
cleanup = make_cleanup_restore_integer (&interpreter_async);
@@ -207,6 +204,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
@@ -308,6 +324,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
@@ -328,6 +352,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. */
@@ -422,6 +467,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. */
@@ -727,6 +776,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."), _("\
@@ -744,6 +811,15 @@ 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 command GCC command-line arguments FIXME"),
+ _("Show compile command GCC command-line arguments FIXME"),
+ _("\
+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
@@ -762,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);
}
@@ -73,9 +73,16 @@ enum compile_i_scope_types
/* A printable expression scope. Wrap an expression into a scope
suitable for the "compile print" command. It uses the generic
- function name "_gdb_expr". */
+ function name "_gdb_expr". COMPILE_I_PRINT_ADDRESS_SCOPE variant
+ is the usual one, taking address of the object.
+ COMPILE_I_PRINT_VALUE_SCOPE is needed for arrays where the array
+ 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. */
@@ -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\\."
+}
---
gdb/compile/compile-c-support.c | 21 ++++++
gdb/compile/compile-object-load.c | 18 +++++
gdb/compile/compile.c | 91 +++++++++++++++++++++++++--
gdb/defs.h | 4 +
gdb/doc/gdb.texinfo | 14 ++++
gdb/testsuite/gdb.compile/compile-print.exp | 5 +
6 files changed, 144 insertions(+), 9 deletions(-)
@@ -206,7 +206,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:
@@ -226,6 +236,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:
@@ -390,7 +401,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);
@@ -418,6 +430,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;
@@ -470,7 +470,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)
@@ -490,6 +490,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;
}
@@ -637,6 +649,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);
}
@@ -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 *fmtp;
cleanup = make_cleanup_restore_integer (&interpreter_async);
@@ -207,6 +204,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
@@ -308,6 +324,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
@@ -328,6 +352,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. */
@@ -422,6 +467,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. */
@@ -727,6 +776,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."), _("\
@@ -744,6 +811,15 @@ 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 command GCC command-line arguments FIXME"),
+ _("Show compile command GCC command-line arguments FIXME"),
+ _("\
+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
@@ -762,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);
}
@@ -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. */
@@ -17242,6 +17242,20 @@ 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}).
+
+@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
+
@subsection Caveats when using the @code{compile} command
There are a few caveats to keep in mind when using the @code{compile}
@@ -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\\."
+}