From 84f4c1fe0525fb92c79216087fd8c1744aafb203 Mon Sep 17 00:00:00 2001 From: Phil Muldoon Date: Thu, 11 Nov 2010 14:11:56 +0000 Subject: 2010-11-11 Phil Muldoon * python/py-breakpoint.c (BPPY_REQUIRE_VALID): Check if bp is NULL. (BPPY_SET_REQUIRE_VALID): Ditto. (bpnum_is_valid): Delete function. (bppy_get_visibility): New function. (bppy_new): Parse for, and validate internal keyword. Pass internal keyword to breakpoint or watchpoint functions. (build_bp_list): New function. (gdbpy_breakpoints): Rewrite. Use build_bp_list and iterate_over_breakpoints. (gdbpy_breakpoint_created): Rewrite. Do not store breakpoints in a look-aside vector. (gdbpy_breakpoint_deleted): Rewrite, defer breakpoint management to internal breakpoint chain. * breakpoint.c (set_breakpoint_number): New function. (breakpoint_1): Check if breakpoint number is more than zero. (set_raw_breakpoint_without_location): Set py_bp_object to NULL. (create_breakpoint_sal): Take a new parameter called internal. Call set_breakpoint_number with internal parameter. Do not mention internal breakpoints. All callers updated. (create_breakpoint): Ditto. (create_breakpoints_sal): Ditto. (watch_command_1): Ditto. (watch_command_wrapper): Take a new parameter called internal. All callers updated. (rwatch_command_wrapper): Ditto. (awatch_command_wrapper): Ditto. (save_breakpoints): Update breakpoint save condition check. (iterate_over_breakpoints): New function. * breakpoint.h: Add conditional python includes. Add py_bp_object and comment to struct breakpoint. Update all callers. * defs.h: Add PyObject definition for GDB builds without Python. 2010-11-11 Phil Muldoon * gdb.texinfo (Breakpoints In Python): Document "internal" parameter, and visible attribute. 2010-11-11 Phil Muldoon * gdb.python/py-breakpoint.exp: Add internal watchpoint and breakpoint tests. --- gdb/python/py-breakpoint.c | 161 +++++++++++++++++++++++++-------------------- 1 file changed, 89 insertions(+), 72 deletions(-) (limited to 'gdb/python') diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c index b18f7f3..8afa414 100644 --- a/gdb/python/py-breakpoint.c +++ b/gdb/python/py-breakpoint.c @@ -34,17 +34,6 @@ typedef struct breakpoint_object breakpoint_object; static PyTypeObject breakpoint_object_type; -/* A dynamically allocated vector of breakpoint objects. Each - breakpoint has a number. A breakpoint is valid if its slot in this - vector is non-null. When a breakpoint is deleted, we drop our - reference to it and zero its slot; this is how we let the Python - object have a lifetime which is independent from that of the gdb - breakpoint. */ -static breakpoint_object **bppy_breakpoints; - -/* Number of slots in bppy_breakpoints. */ -static int bppy_slots; - /* Number of live breakpoints. */ static int bppy_live; @@ -68,7 +57,7 @@ struct breakpoint_object exception if it is invalid. */ #define BPPY_REQUIRE_VALID(Breakpoint) \ do { \ - if (! bpnum_is_valid ((Breakpoint)->number)) \ + if ((Breakpoint)->bp == NULL) \ return PyErr_Format (PyExc_RuntimeError, _("Breakpoint %d is invalid."), \ (Breakpoint)->number); \ } while (0) @@ -77,7 +66,7 @@ struct breakpoint_object exception if it is invalid. This macro is for use in setter functions. */ #define BPPY_SET_REQUIRE_VALID(Breakpoint) \ do { \ - if (! bpnum_is_valid ((Breakpoint)->number)) \ + if ((Breakpoint)->bp == NULL) \ { \ PyErr_Format (PyExc_RuntimeError, _("Breakpoint %d is invalid."), \ (Breakpoint)->number); \ @@ -115,18 +104,6 @@ static struct pybp_code pybp_watch_types[] = {NULL} /* Sentinel. */ }; -/* Evaluate to true if the breakpoint NUM is valid, false otherwise. */ -static int -bpnum_is_valid (int num) -{ - if (num >=0 - && num < bppy_slots - && bppy_breakpoints[num] != NULL) - return 1; - - return 0; -} - /* Python function which checks the validity of a breakpoint object. */ static PyObject * bppy_is_valid (PyObject *self, PyObject *args) @@ -503,6 +480,21 @@ bppy_get_type (PyObject *self, void *closure) return PyInt_FromLong (self_bp->bp->type); } +/* Python function to get the visibility of the breakpoint. */ + +static PyObject * +bppy_get_visibility (PyObject *self, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (self_bp); + + if (self_bp->bp->number < 0) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + /* Python function to get the breakpoint's number. */ static PyObject * bppy_get_number (PyObject *self, void *closure) @@ -569,16 +561,25 @@ static PyObject * bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs) { PyObject *result; - static char *keywords[] = { "spec", "type", "wp_class", NULL }; + static char *keywords[] = { "spec", "type", "wp_class", "internal", NULL }; char *spec; int type = bp_breakpoint; int access_type = hw_write; + PyObject *internal = NULL; + int internal_bp = 0; volatile struct gdb_exception except; - if (! PyArg_ParseTupleAndKeywords (args, kwargs, "s|ii", keywords, - &spec, &type, &access_type)) + if (! PyArg_ParseTupleAndKeywords (args, kwargs, "s|iiO", keywords, + &spec, &type, &access_type, &internal)) return NULL; + if (internal) + { + internal_bp = PyObject_IsTrue (internal); + if (internal_bp == -1) + return NULL; + } + result = subtype->tp_alloc (subtype, 0); if (! result) return NULL; @@ -598,17 +599,17 @@ bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs) 0, bp_breakpoint, 0, AUTO_BOOLEAN_TRUE, - NULL, 0, 1); + NULL, 0, 1, internal_bp); break; } case bp_watchpoint: { if (access_type == hw_write) - watch_command_wrapper (spec, 0); + watch_command_wrapper (spec, 0, internal_bp); else if (access_type == hw_access) - awatch_command_wrapper (spec, 0); + awatch_command_wrapper (spec, 0, internal_bp); else if (access_type == hw_read) - rwatch_command_wrapper (spec, 0); + rwatch_command_wrapper (spec, 0, internal_bp); else error(_("Cannot understand watchpoint access type.")); break; @@ -631,31 +632,50 @@ bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs) +static int +build_bp_list (struct breakpoint *b, void *arg) +{ + PyObject *list = arg; + PyObject *bp = b->py_bp_object; + int iserr = 0; + + /* Not all breakpoints will have a companion Python object. + Only breakpoints that were created via bppy_new, or + breakpoints that were created externally and are tracked by + the Python Scripting API. */ + if (bp) + iserr = PyList_Append (list, bp); + + if (iserr == -1) + return 1; + + return 0; +} + /* Static function to return a tuple holding all breakpoints. */ PyObject * gdbpy_breakpoints (PyObject *self, PyObject *args) { - PyObject *result; + PyObject *list; if (bppy_live == 0) Py_RETURN_NONE; - result = PyTuple_New (bppy_live); - if (result) - { - int i, out = 0; + list = PyList_New (0); + if (!list) + return NULL; - for (i = 0; out < bppy_live; ++i) - { - if (! bppy_breakpoints[i]) - continue; - Py_INCREF (bppy_breakpoints[i]); - PyTuple_SetItem (result, out, (PyObject *) bppy_breakpoints[i]); - ++out; - } + /* If iteratre_over_breakpoints returns non NULL it signals an error + condition. In that case abandon building the list and return + NULL. */ + if (iterate_over_breakpoints (build_bp_list, list) != NULL) + { + Py_DECREF (list); + return NULL; } - return result; + + return PyList_AsTuple (list); } @@ -671,13 +691,13 @@ gdbpy_breakpoint_created (int num) struct breakpoint *bp = NULL; PyGILState_STATE state; - if (num < 0) - return; - bp = get_breakpoint (num); if (! bp) return; + if (num < 0 && bppy_pending_object == NULL) + return; + if (bp->type != bp_breakpoint && bp->type != bp_watchpoint && bp->type != bp_hardware_watchpoint @@ -685,21 +705,6 @@ gdbpy_breakpoint_created (int num) && bp->type != bp_access_watchpoint) return; - if (num >= bppy_slots) - { - int old = bppy_slots; - - bppy_slots = bppy_slots * 2 + 10; - bppy_breakpoints - = (breakpoint_object **) xrealloc (bppy_breakpoints, - (bppy_slots - * sizeof (breakpoint_object *))); - memset (&bppy_breakpoints[old], 0, - (bppy_slots - old) * sizeof (PyObject *)); - } - - ++bppy_live; - state = PyGILState_Ensure (); if (bppy_pending_object) @@ -713,12 +718,16 @@ gdbpy_breakpoint_created (int num) { newbp->number = num; newbp->bp = bp; - bppy_breakpoints[num] = newbp; + newbp->bp->py_bp_object = (PyObject *) newbp; Py_INCREF (newbp); + ++bppy_live; + } + else + { + PyErr_SetString (PyExc_RuntimeError, + _("Error while creating breakpoint from GDB.")); + gdbpy_print_stack (); } - - /* Just ignore errors here. */ - PyErr_Clear (); PyGILState_Release (state); } @@ -729,14 +738,20 @@ static void gdbpy_breakpoint_deleted (int num) { PyGILState_STATE state; + struct breakpoint *bp = NULL; + breakpoint_object *bp_obj; state = PyGILState_Ensure (); - if (bpnum_is_valid (num)) + bp = get_breakpoint (num); + if (! bp) + return; + + bp_obj = ((breakpoint_object *) bp->py_bp_object); + if (bp_obj) { - bppy_breakpoints[num]->bp = NULL; - Py_DECREF (bppy_breakpoints[num]); - bppy_breakpoints[num] = NULL; + bp_obj->bp = NULL; --bppy_live; + Py_DECREF (bp_obj); } PyGILState_Release (state); } @@ -819,6 +834,8 @@ or None if no condition set."}, "Commands of the breakpoint, as specified by the user."}, { "type", bppy_get_type, NULL, "Type of breakpoint."}, + { "visible", bppy_get_visibility, NULL, + "Whether the breakpoint is visible to the user."}, { NULL } /* Sentinel. */ }; -- cgit v1.1