summaryrefslogtreecommitdiff
path: root/gdb/python
diff options
context:
space:
mode:
authorPhil Muldoon <pmuldoon@redhat.com>2017-12-07 16:47:33 +0000
committerPhil Muldoon <pmuldoon@redhat.com>2017-12-07 16:47:33 +0000
commit824cc835aa9a4d585d955db4ab2a5dd4c17cc22c (patch)
tree8f0ee6f88956328aea665e4016ea7ae09274c6bd /gdb/python
parent9c226a8689db8bced43b94f551e118551219ce54 (diff)
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.
Diffstat (limited to 'gdb/python')
-rw-r--r--gdb/python/py-breakpoint.c134
1 files changed, 121 insertions, 13 deletions
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 2574683ed4..f865317ab3 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -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 (&copy, 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 (&copy,
+ 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)