python: Make gdb.execute("show commands") work (PR 23669)
Since commit
56bcdbea2b
("Let gdb.execute handle multi-line commands")
trying to use a command like gdb.execute("show commands") in Python
fails. GDB ends up trying to run the "commands" command.
The reason is that GDB gets confused with the special "commands"
command. In process_next_line, the lookup_cmd_1 function returns the
cmd_list_element representing the "commands" sub-command of "show".
Lower, we check the cmd_list_element to see if it matches various
control commands by name, including the "commands" command. This is
where we wrongfully conclude that the executed command must be
"commands", when in reality it was "show commands".
The fix proposed in this patch removes the comparisons by name, instead
comparing the cmd_list_element object by pointer with the objects
created at initialization time.
Tested on the buildbot, though on a single builder (Fedora-x86_64-m64).
gdb/ChangeLog:
PR python/23669
* breakpoint.c (commands_cmd_element): New.
(_initialize_breakpoint): Assign commands_cmd_element.
* breakpoint.h (commands_cmd_element): New.
* cli/cli-script.c (while_cmd_element, if_command,
define_cmd_element): New.
(command_name_equals): Remove.
(process_next_line): Compare commands by pointer, not by name.
(_initialize_cli_script): Assign the various cmd_list_element
variables.
* compile/compile.c (compile_cmd_element): New.
(_initialize_compile): Assign compile_cmd_element.
* compile/compile.h (compile_cmd_element): New.
* guile/guile.c (guile_cmd_element): New.
(install_gdb_commands): Assign guile_cmd_element.
* guile/guile.h (guile_cmd_element): New.
* python/python.c (python_cmd_element): New.
(_initialize_python): Assign python_cmd_element.
* python/python.h (python_cmd_element): New.
* tracepoint.c (while_stepping_cmd_element): New.
(_initialize_tracepoint): Assign while_stepping_cmd_element.
* tracepoint.h (while_stepping_cmd_element): New.
gdb/testsuite/ChangeLog:
PR python/23669
* gdb.python/python.exp: Test gdb.execute("show commands").
This commit is contained in:
parent
a0a8a9340d
commit
8588b35692
14 changed files with 98 additions and 36 deletions
|
@ -1,3 +1,28 @@
|
||||||
|
2018-09-17 Simon Marchi <simon.marchi@polymtl.ca>
|
||||||
|
|
||||||
|
PR python/23669
|
||||||
|
* breakpoint.c (commands_cmd_element): New.
|
||||||
|
(_initialize_breakpoint): Assign commands_cmd_element.
|
||||||
|
* breakpoint.h (commands_cmd_element): New.
|
||||||
|
* cli/cli-script.c (while_cmd_element, if_command,
|
||||||
|
define_cmd_element): New.
|
||||||
|
(command_name_equals): Remove.
|
||||||
|
(process_next_line): Compare commands by pointer, not by name.
|
||||||
|
(_initialize_cli_script): Assign the various cmd_list_element
|
||||||
|
variables.
|
||||||
|
* compile/compile.c (compile_cmd_element): New.
|
||||||
|
(_initialize_compile): Assign compile_cmd_element.
|
||||||
|
* compile/compile.h (compile_cmd_element): New.
|
||||||
|
* guile/guile.c (guile_cmd_element): New.
|
||||||
|
(install_gdb_commands): Assign guile_cmd_element.
|
||||||
|
* guile/guile.h (guile_cmd_element): New.
|
||||||
|
* python/python.c (python_cmd_element): New.
|
||||||
|
(_initialize_python): Assign python_cmd_element.
|
||||||
|
* python/python.h (python_cmd_element): New.
|
||||||
|
* tracepoint.c (while_stepping_cmd_element): New.
|
||||||
|
(_initialize_tracepoint): Assign while_stepping_cmd_element.
|
||||||
|
* tracepoint.h (while_stepping_cmd_element): New.
|
||||||
|
|
||||||
2018-09-17 Tom Tromey <tom@tromey.com>
|
2018-09-17 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
* infrun.c (save_infcall_suspend_state): Return
|
* infrun.c (save_infcall_suspend_state): Return
|
||||||
|
|
|
@ -15506,6 +15506,10 @@ initialize_breakpoint_ops (void)
|
||||||
|
|
||||||
static struct cmd_list_element *enablebreaklist = NULL;
|
static struct cmd_list_element *enablebreaklist = NULL;
|
||||||
|
|
||||||
|
/* See breakpoint.h. */
|
||||||
|
|
||||||
|
cmd_list_element *commands_cmd_element = nullptr;
|
||||||
|
|
||||||
void
|
void
|
||||||
_initialize_breakpoint (void)
|
_initialize_breakpoint (void)
|
||||||
{
|
{
|
||||||
|
@ -15531,7 +15535,8 @@ _initialize_breakpoint (void)
|
||||||
Set ignore-count of breakpoint number N to COUNT.\n\
|
Set ignore-count of breakpoint number N to COUNT.\n\
|
||||||
Usage is `ignore N COUNT'."));
|
Usage is `ignore N COUNT'."));
|
||||||
|
|
||||||
add_com ("commands", class_breakpoint, commands_command, _("\
|
commands_cmd_element = add_com ("commands", class_breakpoint,
|
||||||
|
commands_command, _("\
|
||||||
Set commands to be executed when the given breakpoints are hit.\n\
|
Set commands to be executed when the given breakpoints are hit.\n\
|
||||||
Give a space-separated breakpoint list as argument after \"commands\".\n\
|
Give a space-separated breakpoint list as argument after \"commands\".\n\
|
||||||
A list element can be a breakpoint number (e.g. `5') or a range of numbers\n\
|
A list element can be a breakpoint number (e.g. `5') or a range of numbers\n\
|
||||||
|
|
|
@ -1679,4 +1679,7 @@ extern void maybe_print_thread_hit_breakpoint (struct ui_out *uiout);
|
||||||
/* Print the specified breakpoint. */
|
/* Print the specified breakpoint. */
|
||||||
extern void print_breakpoint (breakpoint *bp);
|
extern void print_breakpoint (breakpoint *bp);
|
||||||
|
|
||||||
|
/* Command element for the 'commands' command. */
|
||||||
|
extern cmd_list_element *commands_cmd_element;
|
||||||
|
|
||||||
#endif /* !defined (BREAKPOINT_H) */
|
#endif /* !defined (BREAKPOINT_H) */
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "ui-out.h"
|
#include "ui-out.h"
|
||||||
#include "top.h"
|
#include "top.h"
|
||||||
#include "breakpoint.h"
|
#include "breakpoint.h"
|
||||||
|
#include "tracepoint.h"
|
||||||
#include "cli/cli-cmds.h"
|
#include "cli/cli-cmds.h"
|
||||||
#include "cli/cli-decode.h"
|
#include "cli/cli-decode.h"
|
||||||
#include "cli/cli-script.h"
|
#include "cli/cli-script.h"
|
||||||
|
@ -33,6 +34,8 @@
|
||||||
#include "interps.h"
|
#include "interps.h"
|
||||||
#include "compile/compile.h"
|
#include "compile/compile.h"
|
||||||
#include "common/gdb_string_view.h"
|
#include "common/gdb_string_view.h"
|
||||||
|
#include "python/python.h"
|
||||||
|
#include "guile/guile.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -58,6 +61,15 @@ static int command_nest_depth = 1;
|
||||||
/* This is to prevent certain commands being printed twice. */
|
/* This is to prevent certain commands being printed twice. */
|
||||||
static int suppress_next_print_command_trace = 0;
|
static int suppress_next_print_command_trace = 0;
|
||||||
|
|
||||||
|
/* Command element for the 'while' command. */
|
||||||
|
static cmd_list_element *while_cmd_element = nullptr;
|
||||||
|
|
||||||
|
/* Command element for the 'if' command. */
|
||||||
|
static cmd_list_element *if_cmd_element = nullptr;
|
||||||
|
|
||||||
|
/* Command element for the 'define' command. */
|
||||||
|
static cmd_list_element *define_cmd_element = nullptr;
|
||||||
|
|
||||||
/* Structure for arguments to user defined functions. */
|
/* Structure for arguments to user defined functions. */
|
||||||
|
|
||||||
class user_args
|
class user_args
|
||||||
|
@ -906,16 +918,6 @@ read_next_line (void)
|
||||||
return command_line_input (prompt_ptr, "commands");
|
return command_line_input (prompt_ptr, "commands");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true if CMD's name is NAME. */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
command_name_equals (struct cmd_list_element *cmd, const char *name)
|
|
||||||
{
|
|
||||||
return (cmd != NULL
|
|
||||||
&& cmd != CMD_LIST_AMBIGUOUS
|
|
||||||
&& strcmp (cmd->name, name) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Given an input line P, skip the command and return a pointer to the
|
/* Given an input line P, skip the command and return a pointer to the
|
||||||
first argument. */
|
first argument. */
|
||||||
|
|
||||||
|
@ -990,7 +992,7 @@ process_next_line (const char *p, struct command_line **command,
|
||||||
|
|
||||||
/* Check for while, if, break, continue, etc and build a new
|
/* Check for while, if, break, continue, etc and build a new
|
||||||
command line structure for them. */
|
command line structure for them. */
|
||||||
if (command_name_equals (cmd, "while-stepping"))
|
if (cmd == while_stepping_cmd_element)
|
||||||
{
|
{
|
||||||
/* Because validate_actionline and encode_action lookup
|
/* Because validate_actionline and encode_action lookup
|
||||||
command's line as command, we need the line to
|
command's line as command, we need the line to
|
||||||
|
@ -1005,34 +1007,28 @@ process_next_line (const char *p, struct command_line **command,
|
||||||
not. */
|
not. */
|
||||||
*command = build_command_line (while_stepping_control, p);
|
*command = build_command_line (while_stepping_control, p);
|
||||||
}
|
}
|
||||||
else if (command_name_equals (cmd, "while"))
|
else if (cmd == while_cmd_element)
|
||||||
{
|
*command = build_command_line (while_control, line_first_arg (p));
|
||||||
*command = build_command_line (while_control, line_first_arg (p));
|
else if (cmd == if_cmd_element)
|
||||||
}
|
*command = build_command_line (if_control, line_first_arg (p));
|
||||||
else if (command_name_equals (cmd, "if"))
|
else if (cmd == commands_cmd_element)
|
||||||
{
|
*command = build_command_line (commands_control, line_first_arg (p));
|
||||||
*command = build_command_line (if_control, line_first_arg (p));
|
else if (cmd == define_cmd_element)
|
||||||
}
|
|
||||||
else if (command_name_equals (cmd, "commands"))
|
|
||||||
{
|
|
||||||
*command = build_command_line (commands_control, line_first_arg (p));
|
|
||||||
}
|
|
||||||
else if (command_name_equals (cmd, "define"))
|
|
||||||
*command = build_command_line (define_control, line_first_arg (p));
|
*command = build_command_line (define_control, line_first_arg (p));
|
||||||
else if (command_name_equals (cmd, "python") && !inline_cmd)
|
else if (cmd == python_cmd_element && !inline_cmd)
|
||||||
{
|
{
|
||||||
/* Note that we ignore the inline "python command" form
|
/* Note that we ignore the inline "python command" form
|
||||||
here. */
|
here. */
|
||||||
*command = build_command_line (python_control, "");
|
*command = build_command_line (python_control, "");
|
||||||
}
|
}
|
||||||
else if (command_name_equals (cmd, "compile") && !inline_cmd)
|
else if (cmd == compile_cmd_element && !inline_cmd)
|
||||||
{
|
{
|
||||||
/* Note that we ignore the inline "compile command" form
|
/* Note that we ignore the inline "compile command" form
|
||||||
here. */
|
here. */
|
||||||
*command = build_command_line (compile_control, "");
|
*command = build_command_line (compile_control, "");
|
||||||
(*command)->control_u.compile.scope = COMPILE_I_INVALID_SCOPE;
|
(*command)->control_u.compile.scope = COMPILE_I_INVALID_SCOPE;
|
||||||
}
|
}
|
||||||
else if (command_name_equals (cmd, "guile") && !inline_cmd)
|
else if (cmd == guile_cmd_element && !inline_cmd)
|
||||||
{
|
{
|
||||||
/* Note that we ignore the inline "guile command" form here. */
|
/* Note that we ignore the inline "guile command" form here. */
|
||||||
*command = build_command_line (guile_control, "");
|
*command = build_command_line (guile_control, "");
|
||||||
|
@ -1597,7 +1593,7 @@ _initialize_cli_script (void)
|
||||||
Document a user-defined command.\n\
|
Document a user-defined command.\n\
|
||||||
Give command name as argument. Give documentation on following lines.\n\
|
Give command name as argument. Give documentation on following lines.\n\
|
||||||
End with a line of just \"end\"."));
|
End with a line of just \"end\"."));
|
||||||
add_com ("define", class_support, define_command, _("\
|
define_cmd_element = add_com ("define", class_support, define_command, _("\
|
||||||
Define a new command name. Command name is argument.\n\
|
Define a new command name. Command name is argument.\n\
|
||||||
Definition appears on following lines, one command per line.\n\
|
Definition appears on following lines, one command per line.\n\
|
||||||
End with a line of just \"end\".\n\
|
End with a line of just \"end\".\n\
|
||||||
|
@ -1606,13 +1602,13 @@ Commands defined in this way may accept an unlimited number of arguments\n\
|
||||||
accessed via $arg0 .. $argN. $argc tells how many arguments have\n\
|
accessed via $arg0 .. $argN. $argc tells how many arguments have\n\
|
||||||
been passed."));
|
been passed."));
|
||||||
|
|
||||||
add_com ("while", class_support, while_command, _("\
|
while_cmd_element = add_com ("while", class_support, while_command, _("\
|
||||||
Execute nested commands WHILE the conditional expression is non zero.\n\
|
Execute nested commands WHILE the conditional expression is non zero.\n\
|
||||||
The conditional expression must follow the word `while' and must in turn be\n\
|
The conditional expression must follow the word `while' and must in turn be\n\
|
||||||
followed by a new line. The nested commands must be entered one per line,\n\
|
followed by a new line. The nested commands must be entered one per line,\n\
|
||||||
and should be terminated by the word `end'."));
|
and should be terminated by the word `end'."));
|
||||||
|
|
||||||
add_com ("if", class_support, if_command, _("\
|
if_cmd_element = add_com ("if", class_support, if_command, _("\
|
||||||
Execute nested commands once IF the conditional expression is non zero.\n\
|
Execute nested commands once IF the conditional expression is non zero.\n\
|
||||||
The conditional expression must follow the word `if' and must in turn be\n\
|
The conditional expression must follow the word `if' and must in turn be\n\
|
||||||
followed by a new line. The nested commands must be entered one per line,\n\
|
followed by a new line. The nested commands must be entered one per line,\n\
|
||||||
|
|
|
@ -908,14 +908,16 @@ compile_instance::compile (const char *filename, int verbose_level)
|
||||||
|
|
||||||
#undef FORWARD
|
#undef FORWARD
|
||||||
|
|
||||||
|
/* See compile.h. */
|
||||||
|
cmd_list_element *compile_cmd_element = nullptr;
|
||||||
|
|
||||||
void
|
void
|
||||||
_initialize_compile (void)
|
_initialize_compile (void)
|
||||||
{
|
{
|
||||||
struct cmd_list_element *c = NULL;
|
struct cmd_list_element *c = NULL;
|
||||||
|
|
||||||
add_prefix_cmd ("compile", class_obscure, compile_command,
|
compile_cmd_element = add_prefix_cmd ("compile", class_obscure,
|
||||||
_("\
|
compile_command, _("\
|
||||||
Command to compile source code and inject it into the inferior."),
|
Command to compile source code and inject it into the inferior."),
|
||||||
&compile_command_list, "compile ", 1, &cmdlist);
|
&compile_command_list, "compile ", 1, &cmdlist);
|
||||||
add_com_alias ("expression", "compile", class_obscure, 0);
|
add_com_alias ("expression", "compile", class_obscure, 0);
|
||||||
|
|
|
@ -103,4 +103,7 @@ extern void compile_dwarf_bounds_to_c (string_file *stream,
|
||||||
|
|
||||||
extern void compile_print_value (struct value *val, void *data_voidp);
|
extern void compile_print_value (struct value *val, void *data_voidp);
|
||||||
|
|
||||||
|
/* Command element for the 'compile' command. */
|
||||||
|
extern cmd_list_element *compile_cmd_element;
|
||||||
|
|
||||||
#endif /* GDB_COMPILE_H */
|
#endif /* GDB_COMPILE_H */
|
||||||
|
|
|
@ -700,6 +700,9 @@ gdbscm_set_backtrace (int enable)
|
||||||
|
|
||||||
#endif /* HAVE_GUILE */
|
#endif /* HAVE_GUILE */
|
||||||
|
|
||||||
|
/* See guile.h. */
|
||||||
|
cmd_list_element *guile_cmd_element = nullptr;
|
||||||
|
|
||||||
/* Install the various gdb commands used by Guile. */
|
/* Install the various gdb commands used by Guile. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -725,7 +728,7 @@ This command is only a placeholder.")
|
||||||
|
|
||||||
/* Since "help guile" is easy to type, and intuitive, we add general help
|
/* Since "help guile" is easy to type, and intuitive, we add general help
|
||||||
in using GDB+Guile to this command. */
|
in using GDB+Guile to this command. */
|
||||||
add_com ("guile", class_obscure, guile_command,
|
guile_cmd_element = add_com ("guile", class_obscure, guile_command,
|
||||||
#ifdef HAVE_GUILE
|
#ifdef HAVE_GUILE
|
||||||
_("\
|
_("\
|
||||||
Evaluate one or more Guile expressions.\n\
|
Evaluate one or more Guile expressions.\n\
|
||||||
|
|
|
@ -25,4 +25,7 @@
|
||||||
/* This is all that guile exports to gdb. */
|
/* This is all that guile exports to gdb. */
|
||||||
extern const struct extension_language_defn extension_language_guile;
|
extern const struct extension_language_defn extension_language_guile;
|
||||||
|
|
||||||
|
/* Command element for the 'guile' command. */
|
||||||
|
extern cmd_list_element *guile_cmd_element;
|
||||||
|
|
||||||
#endif /* GDB_GUILE_H */
|
#endif /* GDB_GUILE_H */
|
||||||
|
|
|
@ -1745,6 +1745,9 @@ do_start_initialization ()
|
||||||
|
|
||||||
#endif /* HAVE_PYTHON */
|
#endif /* HAVE_PYTHON */
|
||||||
|
|
||||||
|
/* See python.h. */
|
||||||
|
cmd_list_element *python_cmd_element = nullptr;
|
||||||
|
|
||||||
void
|
void
|
||||||
_initialize_python (void)
|
_initialize_python (void)
|
||||||
{
|
{
|
||||||
|
@ -1774,7 +1777,7 @@ This command is only a placeholder.")
|
||||||
);
|
);
|
||||||
add_com_alias ("pi", "python-interactive", class_obscure, 1);
|
add_com_alias ("pi", "python-interactive", class_obscure, 1);
|
||||||
|
|
||||||
add_com ("python", class_obscure, python_command,
|
python_cmd_element = add_com ("python", class_obscure, python_command,
|
||||||
#ifdef HAVE_PYTHON
|
#ifdef HAVE_PYTHON
|
||||||
_("\
|
_("\
|
||||||
Evaluate a Python command.\n\
|
Evaluate a Python command.\n\
|
||||||
|
|
|
@ -25,4 +25,7 @@
|
||||||
/* This is all that python exports to gdb. */
|
/* This is all that python exports to gdb. */
|
||||||
extern const struct extension_language_defn extension_language_python;
|
extern const struct extension_language_defn extension_language_python;
|
||||||
|
|
||||||
|
/* Command element for the 'python' command. */
|
||||||
|
extern cmd_list_element *python_cmd_element;
|
||||||
|
|
||||||
#endif /* GDB_PYTHON_H */
|
#endif /* GDB_PYTHON_H */
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2018-09-17 Simon Marchi <simon.marchi@polymtl.ca>
|
||||||
|
|
||||||
|
PR python/23669
|
||||||
|
* gdb.python/python.exp: Test gdb.execute("show commands").
|
||||||
|
|
||||||
2018-09-16 Tom Tromey <tom@tromey.com>
|
2018-09-16 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
* gdb.base/new-ui.exp (do_execution_tests): Update.
|
* gdb.base/new-ui.exp (do_execution_tests): Update.
|
||||||
|
|
|
@ -497,3 +497,7 @@ gdb_test "python print(gdb.convenience_variable('cvar3'))" "None" \
|
||||||
"print reset convenience variable from python"
|
"print reset convenience variable from python"
|
||||||
gdb_test "print \$cvar3" "= void" \
|
gdb_test "print \$cvar3" "= void" \
|
||||||
"print reset convenience variable from CLI"
|
"print reset convenience variable from CLI"
|
||||||
|
|
||||||
|
# Test PR 23669, the following would invoke the "commands" command instead of
|
||||||
|
# "show commands".
|
||||||
|
gdb_test "python gdb.execute(\"show commands\")" "$decimal print \\\$cvar3.*"
|
||||||
|
|
|
@ -3977,6 +3977,9 @@ static const struct internalvar_funcs sdata_funcs =
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* See tracepoint.h. */
|
||||||
|
cmd_list_element *while_stepping_cmd_element = nullptr;
|
||||||
|
|
||||||
/* module initialization */
|
/* module initialization */
|
||||||
void
|
void
|
||||||
_initialize_tracepoint (void)
|
_initialize_tracepoint (void)
|
||||||
|
@ -4088,7 +4091,8 @@ Entering \"end\" on a line by itself is the normal way to terminate\n\
|
||||||
such a list.\n\n\
|
such a list.\n\n\
|
||||||
Note: the \"end\" command cannot be used at the gdb prompt."));
|
Note: the \"end\" command cannot be used at the gdb prompt."));
|
||||||
|
|
||||||
add_com ("while-stepping", class_trace, while_stepping_pseudocommand, _("\
|
while_stepping_cmd_element = add_com ("while-stepping", class_trace,
|
||||||
|
while_stepping_pseudocommand, _("\
|
||||||
Specify single-stepping behavior at a tracepoint.\n\
|
Specify single-stepping behavior at a tracepoint.\n\
|
||||||
Argument is number of instructions to trace in single-step mode\n\
|
Argument is number of instructions to trace in single-step mode\n\
|
||||||
following the tracepoint. This command is normally followed by\n\
|
following the tracepoint. This command is normally followed by\n\
|
||||||
|
|
|
@ -436,4 +436,7 @@ extern struct traceframe_info *get_traceframe_info (void);
|
||||||
|
|
||||||
extern struct bp_location *get_traceframe_location (int *stepping_frame_p);
|
extern struct bp_location *get_traceframe_location (int *stepping_frame_p);
|
||||||
|
|
||||||
|
/* Command element for the 'while-stepping' command. */
|
||||||
|
extern cmd_list_element *while_stepping_cmd_element;
|
||||||
|
|
||||||
#endif /* TRACEPOINT_H */
|
#endif /* TRACEPOINT_H */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue