> From: Phil Muldoon <pmuldoon@redhat.com>
> Date: Fri, 17 Nov 2017 11:02:08 +0000
>
> I just realised this needs a doc review also.
Doc review coming up.
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 9246659bfb..592fe70156 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -24,6 +24,9 @@
> gdb.new_thread are emitted. See the manual for further
> description of these.
>
> + ** Python breakpoints can now accept explicit locations. See the
> + manual for a further description of this feature.
I think "a further" should lose the "a" part. Also, how about
mentioning the node name in the manual where this is described?
> +watchpoint. The contents can be any location recognized by the
^^
Two spaces here, please.
> +@code{break} command or, in the case of a watchpoint, by the
> +@code{watch} command. Alternatively, create a new a explicit location
^^^^^^^^^^^^^^^^^^^^^^^
The second "a" should be deleted.
> +@var{function}, @var{label} and @var{line}. The optional @var{type}
> +denotes the breakpoint to create from the types defined later in this
> +chapter. This argument can be either @code{gdb.BP_BREAKPOINT} or
I think "denotes the breakpoint to create from the types" is at least
confusing. What did you mean here?
> +@code{gdb.BP_WATCHPOINT}; it defaults to @code{gdb.BP_BREAKPOINT}.
> +The optional @var{internal} argument allows the breakpoint to become
> +invisible to the user. The breakpoint will neither be reported when
^
I think you want a colon here, not a period, because the next sentence
explains what does it mean for a breakpoint to be "invisible".
Alternatively, start the next sentence with "Invisible breakpoints
will neither be reported ...".
> +created, nor will it be listed in the output from @code{info
> +breakpoints} (but will be listed with the @code{maint info
^^^^
"by", I think, not "with".
> +breakpoints} command). The optional @var{temporary} argument makes
> +the breakpoint a temporary breakpoint. Temporary breakpoints are
> +deleted after they have been hit. Any further access to the Python
> +breakpoint after it has been hit will result in a runtime error (as
I think you want to say "to the temporary breakpoint" here. The fact
that it is a Python breakpoint is not really relevant.
> +that breakpoint has now been automatically deleted). The optional
> +@var{wp_class} argument defines the class of watchpoint to create, if
> +@var{type} is @code{gdb.BP_WATCHPOINT}. If a watchpoint class is not
> +provided, it is assumed to be a @code{gdb.WP_WRITE} class.
What are the other supported classes? Either state that here or point
to where that is described.
Thanks.
On 17/11/17 13:30, Eli Zaretskii wrote:
>> From: Phil Muldoon <pmuldoon@redhat.com>
>> Date: Fri, 17 Nov 2017 11:02:08 +0000
>>
>> I just realised this needs a doc review also.
>
> Doc review coming up.
>
>> diff --git a/gdb/NEWS b/gdb/NEWS
>> index 9246659bfb..592fe70156 100644
>> --- a/gdb/NEWS
>> +++ b/gdb/NEWS
>> @@ -24,6 +24,9 @@
>> gdb.new_thread are emitted. See the manual for further
>> description of these.
>>
>> + ** Python breakpoints can now accept explicit locations. See the
>> + manual for a further description of this feature.
>
> I think "a further" should lose the "a" part. Also, how about
> mentioning the node name in the manual where this is described?
OK.
>> +@code{break} command or, in the case of a watchpoint, by the
>> +@code{watch} command. Alternatively, create a new a explicit location
> ^^^^^^^^^^^^^^^^^^^^^^^
> The second "a" should be deleted.
OK. The other comments refer to existing documentation that I have not
actually changed. I formatted the paragraph with the additional
sentence I added and re-formatted (the wrapping affected the whole
paragraph). I have no problem making the changes you suggest, they are
good, but can I please make them in another patchset so the changes
made in this one stay related?
For the purposes of clarity, the related changes in this patch are:
+@defun Breakpoint.__init__ (spec @r{[}, type @r{[}, wp_class @r{[}, internal @r{[}, temporary @r{]}, source @r{]}, function @r{]}, label @r{]}, line @r{]]]]]]]]})
and
+Alternatively, create a new a explicit location
+breakpoint (@pxref{Explicit Locations}) according to the
+specifications contained in the key words @var{source},
+@var{function}, @var{label} and @var{line}.
Cheers
Phil
@@ -24,6 +24,9 @@
gdb.new_thread are emitted. See the manual for further
description of these.
+ ** Python breakpoints can now accept explicit locations. See the
+ manual for a further description of this feature.
+
* New features in the GDB remote stub, GDBserver
** New "--selftest" command line option runs some GDBserver self
@@ -4861,27 +4861,30 @@ represented as Python @code{Long} values.
Python code can manipulate breakpoints via the @code{gdb.Breakpoint}
class.
-@defun Breakpoint.__init__ (spec @r{[}, type @r{[}, wp_class @r{[},internal @r{[},temporary@r{]]]]})
+@defun Breakpoint.__init__ (spec @r{[}, type @r{[}, wp_class @r{[}, internal @r{[}, temporary @r{]}, source @r{]}, function @r{]}, label @r{]}, line @r{]]]]]]]]})
Create a new breakpoint according to @var{spec}, which is a string
naming the location of the breakpoint, or an expression that defines a
-watchpoint. The contents can be any location recognized by the
-@code{break} command, or in the case of a watchpoint, by the
-@code{watch} command. The optional @var{type} denotes the breakpoint
-to create from the types defined later in this chapter. This argument
-can be either @code{gdb.BP_BREAKPOINT} or @code{gdb.BP_WATCHPOINT}; it
-defaults to @code{gdb.BP_BREAKPOINT}. The optional @var{internal}
-argument allows the breakpoint to become invisible to the user. The
-breakpoint will neither be reported when created, nor will it be
-listed in the output from @code{info breakpoints} (but will be listed
-with the @code{maint info breakpoints} command). The optional
-@var{temporary} argument makes the breakpoint a temporary breakpoint.
-Temporary breakpoints are deleted after they have been hit. Any
-further access to the Python breakpoint after it has been hit will
-result in a runtime error (as that breakpoint has now been
-automatically deleted). The optional @var{wp_class} argument defines
-the class of watchpoint to create, if @var{type} is
-@code{gdb.BP_WATCHPOINT}. If a watchpoint class is not provided, it
-is assumed to be a @code{gdb.WP_WRITE} class.
+watchpoint. The contents can be any location recognized by the
+@code{break} command or, in the case of a watchpoint, by the
+@code{watch} command. Alternatively, create a new a explicit location
+breakpoint (@pxref{Explicit Locations}) according to the
+specifications contained in the key words @var{source},
+@var{function}, @var{label} and @var{line}. The optional @var{type}
+denotes the breakpoint to create from the types defined later in this
+chapter. This argument can be either @code{gdb.BP_BREAKPOINT} or
+@code{gdb.BP_WATCHPOINT}; it defaults to @code{gdb.BP_BREAKPOINT}.
+The optional @var{internal} argument allows the breakpoint to become
+invisible to the user. The breakpoint will neither be reported when
+created, nor will it be listed in the output from @code{info
+breakpoints} (but will be listed with the @code{maint info
+breakpoints} command). The optional @var{temporary} argument makes
+the breakpoint a temporary breakpoint. Temporary breakpoints are
+deleted after they have been hit. Any further access to the Python
+breakpoint after it has been hit will result in a runtime error (as
+that breakpoint has now been automatically deleted). The optional
+@var{wp_class} argument defines the class of watchpoint to create, if
+@var{type} is @code{gdb.BP_WATCHPOINT}. If a watchpoint class is not
+provided, it is assumed to be a @code{gdb.WP_WRITE} class.
@end defun
The available types are represented by constants defined in the @code{gdb}
@@ -32,6 +32,7 @@
#include "language.h"
#include "location.h"
#include "py-event.h"
+#include "linespec.h"
/* Number of live breakpoints. */
static int bppy_live;
@@ -638,20 +639,73 @@ static int
bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
{
static const char *keywords[] = { "spec", "type", "wp_class", "internal",
- "temporary", NULL };
- const char *spec;
+ "temporary","source", "function",
+ "label", "line", NULL };
+ const char *spec = NULL;
int type = bp_breakpoint;
int access_type = hw_write;
PyObject *internal = NULL;
PyObject *temporary = NULL;
int internal_bp = 0;
int temporary_bp = 0;
+ char *line = NULL;
+ char *label = NULL;
+ char *source = NULL;
+ char *function = NULL;
- if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "s|iiOO", keywords,
+ if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|siiOOssss", keywords,
&spec, &type, &access_type,
- &internal, &temporary))
+ &internal,
+ &temporary, &source,
+ &function, &label, &line))
return -1;
+ /* If spec is defined, ensure that none of the explicit location
+ keywords are also defined. */
+ if (spec != NULL)
+ {
+ if (source != NULL || function != NULL || label != NULL || line != NULL)
+ {
+ PyErr_SetString (PyExc_RuntimeError,
+ _("Breakpoints specified with spec cannot "
+ "have source, function, label or line defined."));
+ return -1;
+ }
+ }
+ else
+ {
+ /* If spec isn't defined, ensure that the user is not trying to
+ define a watchpoint with an explicit location. */
+ if (type == bp_watchpoint)
+ {
+ PyErr_SetString (PyExc_RuntimeError,
+ _("Watchpoints cannot be set by explicit "
+ "location parameters."));
+ return -1;
+ }
+ else
+ {
+ /* Otherwise, ensure some explicit locations are defined. */
+ if (source == NULL && function == NULL && label == NULL
+ && line == NULL)
+ {
+ PyErr_SetString (PyExc_RuntimeError,
+ _("Neither spec nor explicit location set."));
+ return -1;
+ }
+ /* Finally, if source is specified, ensure that line, label
+ or function are specified too. */
+ if (source != NULL && function == NULL && label == NULL
+ && line == NULL)
+ {
+ PyErr_SetString (PyExc_RuntimeError,
+ _("Specifying a source must also include a "
+ "line, label or function."));
+ return -1;
+ }
+ }
+ }
+
if (internal)
{
internal_bp = PyObject_IsTrue (internal);
@@ -672,16 +726,37 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
TRY
{
- gdb::unique_xmalloc_ptr<char>
- copy_holder (xstrdup (skip_spaces (spec)));
- char *copy = copy_holder.get ();
-
switch (type)
{
case bp_breakpoint:
{
- event_location_up location
- = string_to_event_location_basic (©, current_language);
+ event_location_up location;
+
+ if (spec != NULL)
+ {
+ gdb::unique_xmalloc_ptr<char>
+ copy_holder (xstrdup (skip_spaces (spec)));
+ char *copy = copy_holder.get ();
+
+ location = string_to_event_location (©,
+ current_language);
+ }
+ else
+ {
+ struct explicit_location explicit_loc;
+
+ initialize_explicit_location (&explicit_loc);
+ explicit_loc.source_filename = source;
+ explicit_loc.function_name = function;
+ explicit_loc.label_name = label;
+
+ if (line != NULL)
+ explicit_loc.line_offset =
+ linespec_parse_line_offset (line);
+
+ location = new_explicit_location (&explicit_loc);
+ }
+
create_breakpoint (python_gdbarch,
location.get (), NULL, -1, NULL,
0,
@@ -692,8 +767,12 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
0, 1, internal_bp, 0);
break;
}
- case bp_watchpoint:
+ case bp_watchpoint:
{
+ gdb::unique_xmalloc_ptr<char>
+ copy_holder (xstrdup (skip_spaces (spec)));
+ char *copy = copy_holder.get ();
+
if (access_type == hw_write)
watch_command_wrapper (copy, 0, internal_bp);
else if (access_type == hw_access)
@@ -24,7 +24,7 @@ int multiply (int i)
int add (int i)
{
- return i + i;
+ return i + i; /* Break at function add. */
}
@@ -547,6 +547,74 @@ proc test_bkpt_events {} {
check_last_event breakpoint_deleted
}
+proc test_bkpt_explicit_loc {} {
+ global srcfile testfile
+
+ with_test_prefix test_bkpt_invisible {
+ # Start with a fresh gdb.
+ clean_restart ${testfile}
+
+ if ![runto_main] then {
+ fail "cannot run to main."
+ return 0
+ }
+
+ delete_breakpoints
+
+ set bp_location1 [gdb_get_line_number "Break at multiply."]
+ set bp_location2 [gdb_get_line_number "Break at add."]
+
+ gdb_py_test_silent_cmd "python bp1 = gdb.Breakpoint (line=\"$bp_location1\")" \
+ "set explicit breakpoint by line" 0
+ gdb_continue_to_breakpoint "Break at multiply" \
+ ".*Break at multiply.*"
+
+ gdb_py_test_silent_cmd "python bp1 = gdb.Breakpoint (line=\"+1\")" \
+ "set explicit breakpoint by relative line" 0
+ gdb_continue_to_breakpoint "Break at add" \
+ ".*Break at add.*"
+
+ delete_breakpoints
+ gdb_py_test_silent_cmd "python bp1 = gdb.Breakpoint (line=\"-1\")" \
+ "set explicit breakpoint by relative negative line" 0
+ gdb_continue_to_breakpoint "Break at multiply" \
+ ".*Break at multiply.*"
+
+ delete_breakpoints
+ gdb_py_test_silent_cmd "python bp1 = gdb.Breakpoint (function=\"add\")" \
+ "set explicit breakpoint by function" 0
+ gdb_continue_to_breakpoint "Break at function add" \
+ ".*Break at function add.*"
+
+ delete_breakpoints
+ gdb_py_test_silent_cmd "python bp1 = gdb.Breakpoint (source=\"$srcfile\", function=\"add\")" \
+ "set explicit breakpoint by source file and function" 0
+ gdb_continue_to_breakpoint "Break at function add" \
+ ".*Break at function add.*"
+
+ delete_breakpoints
+ gdb_py_test_silent_cmd "python bp1 = gdb.Breakpoint (source=\"$srcfile\", line=\"$bp_location2\")" \
+ "set explicit breakpoint by source file and line number" 0
+ gdb_continue_to_breakpoint "Break at add" \
+ ".*Break at add.*"
+
+ delete_breakpoints
+ gdb_test "python bp1 = gdb.Breakpoint (source=\"$srcfile\")" \
+ "RuntimeError: Specifying a source must also include a line, label or function.*" \
+ "set invalid explicit breakpoint by source only"
+
+ gdb_test "python bp1 = gdb.Breakpoint (source=\"foo.c\", line=\"5\")" \
+ "No source file named foo.*" \
+ "set invalid explicit breakpoint by missing source and line"
+ gdb_test "python bp1 = gdb.Breakpoint (source=\"$srcfile\", line=\"900\")" \
+ "No line 900 in file \"$srcfile\".*" \
+ "set invalid explicit breakpoint by source and invalid line"
+ gdb_test "python bp1 = gdb.Breakpoint (function=\"blah\")" \
+ "Function \"blah\" not defined.*" \
+ "set invalid explicit breakpoint by missing function"
+ }
+}
+
test_bkpt_basic
test_bkpt_deletion
test_bkpt_cond_and_cmds
@@ -558,3 +626,4 @@ test_bkpt_temporary
test_bkpt_address
test_bkpt_pending
test_bkpt_events
+test_bkpt_explicit_loc