Allow breakpoint commands to be set from Python

This changes the Python API so that breakpoint commands can be set by
writing to the "commands" attribute.

ChangeLog
2018-05-04  Tom Tromey  <tom@tromey.com>

	PR python/22731:
	* NEWS: Mention that breakpoint commands are writable.
	* python/py-breakpoint.c (bppy_set_commands): New function.
	(breakpoint_object_getset) <"commands">: Use it.

doc/ChangeLog
2018-05-04  Tom Tromey  <tom@tromey.com>

	PR python/22731:
	* python.texi (Breakpoints In Python): Mention that "commands" is
	writable.

testsuite/ChangeLog
2018-05-04  Tom Tromey  <tom@tromey.com>

	PR python/22731:
	* gdb.python/py-breakpoint.exp: Test setting breakpoint commands.
This commit is contained in:
Tom Tromey 2018-04-18 17:37:56 -06:00
parent 60b3cef2e4
commit a913fffbde
7 changed files with 75 additions and 3 deletions

View file

@ -1,3 +1,10 @@
2018-05-04 Tom Tromey <tom@tromey.com>
PR python/22731:
* NEWS: Mention that breakpoint commands are writable.
* python/py-breakpoint.c (bppy_set_commands): New function.
(breakpoint_object_getset) <"commands">: Use it.
2018-05-04 Tom Tromey <tom@tromey.com> 2018-05-04 Tom Tromey <tom@tromey.com>
* tracepoint.c (actions_command): Update. * tracepoint.c (actions_command): Update.

View file

@ -31,6 +31,9 @@ set|show record btrace cpu
** Type alignment is now exposed via the "align" attribute of a gdb.Type. ** Type alignment is now exposed via the "align" attribute of a gdb.Type.
** The commands attached to a breakpoint can be set by assigning to
the breakpoint's "commands" field.
* New targets * New targets
RiscV ELF riscv*-*-elf RiscV ELF riscv*-*-elf

View file

@ -1,3 +1,9 @@
2018-05-04 Tom Tromey <tom@tromey.com>
PR python/22731:
* python.texi (Breakpoints In Python): Mention that "commands" is
writable.
2018-05-02 Tom Tromey <tom@tromey.com> 2018-05-02 Tom Tromey <tom@tromey.com>
PR python/20084: PR python/20084:

View file

@ -5136,7 +5136,7 @@ value is @code{None}. This attribute is writable.
This attribute holds the commands attached to the breakpoint. If This attribute holds the commands attached to the breakpoint. If
there are commands, this attribute's value is a string holding all the there are commands, this attribute's value is a string holding all the
commands, separated by newlines. If there are no commands, this commands, separated by newlines. If there are no commands, this
attribute is @code{None}. This attribute is not writable. attribute is @code{None}. This attribute is writable.
@end defvar @end defvar
@node Finish Breakpoints in Python @node Finish Breakpoints in Python

View file

@ -510,6 +510,49 @@ bppy_get_commands (PyObject *self, void *closure)
return host_string_to_python_string (stb.c_str ()); return host_string_to_python_string (stb.c_str ());
} }
/* Set the commands attached to a breakpoint. Returns 0 on success.
Returns -1 on error, with a python exception set. */
static int
bppy_set_commands (PyObject *self, PyObject *newvalue, void *closure)
{
gdbpy_breakpoint_object *self_bp = (gdbpy_breakpoint_object *) self;
struct breakpoint *bp = self_bp->bp;
struct gdb_exception except = exception_none;
BPPY_SET_REQUIRE_VALID (self_bp);
gdb::unique_xmalloc_ptr<char> commands
(python_string_to_host_string (newvalue));
if (commands == nullptr)
return -1;
TRY
{
bool first = true;
char *save_ptr = nullptr;
auto reader
= [&] ()
{
const char *result = strtok_r (first ? commands.get () : nullptr,
"\n", &save_ptr);
first = false;
return result;
};
counted_command_line lines = read_command_lines_1 (reader, 1, nullptr);
breakpoint_set_commands (self_bp->bp, std::move (lines));
}
CATCH (ex, RETURN_MASK_ALL)
{
except = ex;
}
END_CATCH
GDB_PY_SET_HANDLE_EXCEPTION (except);
return 0;
}
/* Python function to get the breakpoint type. */ /* Python function to get the breakpoint type. */
static PyObject * static PyObject *
bppy_get_type (PyObject *self, void *closure) bppy_get_type (PyObject *self, void *closure)
@ -1185,7 +1228,7 @@ when setting this property.", NULL },
{ "condition", bppy_get_condition, bppy_set_condition, { "condition", bppy_get_condition, bppy_set_condition,
"Condition of the breakpoint, as specified by the user,\ "Condition of the breakpoint, as specified by the user,\
or None if no condition set."}, or None if no condition set."},
{ "commands", bppy_get_commands, NULL, { "commands", bppy_get_commands, bppy_set_commands,
"Commands of the breakpoint, as specified by the user."}, "Commands of the breakpoint, as specified by the user."},
{ "type", bppy_get_type, NULL, { "type", bppy_get_type, NULL,
"Type of breakpoint."}, "Type of breakpoint."},

View file

@ -1,3 +1,8 @@
2018-05-04 Tom Tromey <tom@tromey.com>
PR python/22731:
* gdb.python/py-breakpoint.exp: Test setting breakpoint commands.
2018-05-04 Tom Tromey <tom@tromey.com> 2018-05-04 Tom Tromey <tom@tromey.com>
PR gdb/11750: PR gdb/11750:

View file

@ -197,8 +197,16 @@ proc_with_prefix test_bkpt_cond_and_cmds { } {
gdb_py_test_silent_cmd "python blist = gdb.breakpoints()" \ gdb_py_test_silent_cmd "python blist = gdb.breakpoints()" \
"Get Breakpoint List" 0 "Get Breakpoint List" 0
gdb_test "python print (blist\[len(blist)-1\].commands)" \ gdb_py_test_silent_cmd "python last_bp = blist\[len(blist)-1\]" \
"Find last breakpoint" 0
gdb_test "python print (last_bp.commands)" \
"print \"Command for breakpoint has been executed.\".*print result" "print \"Command for breakpoint has been executed.\".*print result"
gdb_test_no_output "python last_bp.commands = 'echo hi\\necho there'" \
"set commands"
# Note the length is 3 because the string ends in a \n.
gdb_test "python print (len(last_bp.commands.split('\\n')))" "3" \
"check number of lines in commands"
} }
proc_with_prefix test_bkpt_invisible { } { proc_with_prefix test_bkpt_invisible { } {