Implement explicit locations for Python breakpoints.
This introduces several new keywords to the bppy_init constructor. The spec parameter is now optional but mutually exclusive to the explicit keywords source, label, function and line. gdb/ChangeLog 2017-12-07 Phil Muldoon <pmuldoon@redhat.com> * python/py-breakpoint.c (bppy_init): Use string_to_event_location over basic location code. Implement explicit location keywords. (bppy_init_validate_args): New function. * NEWS: Document Python explicit breakpoint locations. doc/ChangeLog 2017-12-07 Phil Muldoon <pmuldoon@redhat.com> * python.texi (Breakpoints In Python): Add text relating to allowed explicit locations and keywords in gdb.Breakpoints. testsuite/ChangeLog 2017-12-07 Phil Muldoon <pmuldoon@redhat.com> * gdb.python/py-breakpoint.exp (test_bkpt_explicit_loc): Add new tests for explicit locations.
This commit is contained in:
parent
9c226a8689
commit
824cc835aa
8 changed files with 245 additions and 33 deletions
|
@ -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;
|
||||
|
@ -631,25 +632,104 @@ bppy_get_ignore_count (PyObject *self, void *closure)
|
|||
return PyInt_FromLong (self_bp->bp->ignore_count);
|
||||
}
|
||||
|
||||
/* Internal function to validate the Python parameters/keywords
|
||||
provided to bppy_init. */
|
||||
|
||||
static int
|
||||
bppy_init_validate_args (const char *spec, char *source,
|
||||
char *function, char *label,
|
||||
char *line, enum bptype type)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Python function to create a new breakpoint. */
|
||||
static int
|
||||
bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static const char *keywords[] = { "spec", "type", "wp_class", "internal",
|
||||
"temporary", NULL };
|
||||
const char *spec;
|
||||
int type = bp_breakpoint;
|
||||
"temporary","source", "function",
|
||||
"label", "line", NULL };
|
||||
const char *spec = NULL;
|
||||
enum bptype type = bp_breakpoint;
|
||||
int access_type = hw_write;
|
||||
PyObject *internal = NULL;
|
||||
PyObject *temporary = NULL;
|
||||
PyObject *lineobj = NULL;;
|
||||
int internal_bp = 0;
|
||||
int temporary_bp = 0;
|
||||
gdb::unique_xmalloc_ptr<char> line;
|
||||
char *label = NULL;
|
||||
char *source = NULL;
|
||||
char *function = NULL;
|
||||
|
||||
if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "s|iiOO", keywords,
|
||||
if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|siiOOsssO", keywords,
|
||||
&spec, &type, &access_type,
|
||||
&internal, &temporary))
|
||||
&internal,
|
||||
&temporary, &source,
|
||||
&function, &label, &lineobj))
|
||||
return -1;
|
||||
|
||||
|
||||
if (lineobj != NULL)
|
||||
{
|
||||
if (PyInt_Check (lineobj))
|
||||
line.reset (xstrprintf ("%ld", PyInt_AsLong (lineobj)));
|
||||
else if (PyString_Check (lineobj))
|
||||
line = python_string_to_host_string (lineobj);
|
||||
else
|
||||
{
|
||||
PyErr_SetString (PyExc_RuntimeError,
|
||||
_("Line keyword should be an integer or a string. "));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (internal)
|
||||
{
|
||||
internal_bp = PyObject_IsTrue (internal);
|
||||
|
@ -664,23 +744,47 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (bppy_init_validate_args (spec, source, function, label, line.get (),
|
||||
type) == -1)
|
||||
return -1;
|
||||
|
||||
bppy_pending_object = (gdbpy_breakpoint_object *) self;
|
||||
bppy_pending_object->number = -1;
|
||||
bppy_pending_object->bp = NULL;
|
||||
|
||||
TRY
|
||||
{
|
||||
gdb::unique_xmalloc_ptr<char>
|
||||
copy_holder (xstrdup (skip_spaces (spec)));
|
||||
const char *copy = copy_holder.get ();
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case bp_breakpoint:
|
||||
{
|
||||
event_location_up location
|
||||
= string_to_event_location_basic (©, current_language,
|
||||
symbol_name_match_type::WILD);
|
||||
event_location_up location;
|
||||
|
||||
if (spec != NULL)
|
||||
{
|
||||
gdb::unique_xmalloc_ptr<char>
|
||||
copy_holder (xstrdup (skip_spaces (spec)));
|
||||
const 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.get ());
|
||||
|
||||
location = new_explicit_location (&explicit_loc);
|
||||
}
|
||||
|
||||
create_breakpoint (python_gdbarch,
|
||||
location.get (), NULL, -1, NULL,
|
||||
0,
|
||||
|
@ -691,8 +795,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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue