2010-11-11 Phil Muldoon <pmuldoon@redhat.com>

* 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  <pmuldoon@redhat.com>

	* gdb.texinfo (Breakpoints In Python): Document "internal"
	parameter, and visible attribute.


2010-11-11  Phil Muldoon  <pmuldoon@redhat.com>

	* gdb.python/py-breakpoint.exp: Add internal watchpoint and
	breakpoint tests.
This commit is contained in:
Phil Muldoon 2010-11-11 14:11:56 +00:00
parent 95a2c8d6f7
commit 84f4c1fe05
12 changed files with 326 additions and 126 deletions

View file

@ -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. */
};