diff options
author | Phil Muldoon <pmuldoon@redhat.com> | 2017-12-07 16:47:33 +0000 |
---|---|---|
committer | Phil Muldoon <pmuldoon@redhat.com> | 2017-12-07 16:47:33 +0000 |
commit | 824cc835aa9a4d585d955db4ab2a5dd4c17cc22c (patch) | |
tree | 8f0ee6f88956328aea665e4016ea7ae09274c6bd /gdb/python/py-breakpoint.c | |
parent | 9c226a8689db8bced43b94f551e118551219ce54 (diff) | |
download | binutils-gdb-824cc835aa9a4d585d955db4ab2a5dd4c17cc22c.tar.gz |
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/py-breakpoint.c')
-rw-r--r-- | gdb/python/py-breakpoint.c | 134 |
1 files changed, 121 insertions, 13 deletions
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c index 2574683ed47..f865317ab33 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 (©, 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) |