2010-04-09 Phil Muldoon <pmuldoon@redhat.com>

Thiago Jung Bauermann  <bauerman@br.ibm.com>
   	    Tom Tromey  <tromey@redhat.com>

	* breakpoint.c (condition_command): Simplify.  Move condition
	setting code to ...
	(set_breakpoint_condition): ... here.  New function.
	* breakpoint.h  (set_breakpoint_condition): Declare.
	* Makefile.in (SUBDIR_PYTHON_OBS): Add py-breakpoint.
	(SUBDIR_PYTHON_SRCS): Likewise.
	(py-breakpoint.o): New rule.
	* python/py-breakpoint.c: New file.
	* python/python-internal.h (gdbpy_breakpoints)
	(gdbpy_initialize_breakpoints): Declare.
	(GDB_PY_SET_HANDLE_EXCEPTION) Define.


2010-04-09  Phil Muldoon  <pmuldoon@redhat.com>

	* gdb.python/py-breakpoint.exp: New File.
	* gdb.python/py-breakpoint.C: Ditto.

2010-04-09  Phil Muldoon  <pmuldoon@redhat.com>
	    Thiago Jung Bauermann  <bauerman@br.ibm.com>
   	    Tom Tromey  <tromey@redhat.com>

	* gdb.texinfo (Breakpoints In Python): New Node.
This commit is contained in:
Phil Muldoon 2010-04-09 09:41:43 +00:00
parent e760a81b79
commit adc368187c
14 changed files with 1329 additions and 50 deletions

View File

@ -1,3 +1,19 @@
2010-04-09 Phil Muldoon <pmuldoon@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Tom Tromey <tromey@redhat.com>
* breakpoint.c (condition_command): Simplify. Move condition
setting code to ...
(set_breakpoint_condition): ... here. New function.
* breakpoint.h (set_breakpoint_condition): Declare.
* Makefile.in (SUBDIR_PYTHON_OBS): Add py-breakpoint.
(SUBDIR_PYTHON_SRCS): Likewise.
(py-breakpoint.o): New rule.
* python/py-breakpoint.c: New file.
* python/python-internal.h (gdbpy_breakpoints)
(gdbpy_initialize_breakpoints): Declare.
(GDB_PY_SET_HANDLE_EXCEPTION) Define.
2010-04-09 Pedro Alves <pedro@codesourcery.com> 2010-04-09 Pedro Alves <pedro@codesourcery.com>
* regformats/regdat.sh: Include server.h. Don't include * regformats/regdat.sh: Include server.h. Don't include

View File

@ -268,6 +268,7 @@ SUBDIR_TUI_CFLAGS= \
SUBDIR_PYTHON_OBS = \ SUBDIR_PYTHON_OBS = \
python.o \ python.o \
py-block.o \ py-block.o \
py-breakpoint.o \
py-cmd.o \ py-cmd.o \
py-frame.o \ py-frame.o \
py-function.o \ py-function.o \
@ -282,6 +283,7 @@ SUBDIR_PYTHON_OBS = \
SUBDIR_PYTHON_SRCS = \ SUBDIR_PYTHON_SRCS = \
python/python.c \ python/python.c \
python/py-block.c \ python/py-block.c \
python/py-breakpoint.c \
python/py-cmd.c \ python/py-cmd.c \
python/py-frame.c \ python/py-frame.c \
python/py-function.c \ python/py-function.c \
@ -1986,6 +1988,10 @@ py-block.o: $(srcdir)/python/py-block.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-block.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-block.c
$(POSTCOMPILE) $(POSTCOMPILE)
py-breakpoint.o: $(srcdir)/python/py-breakpoint.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-breakpoint.c
$(POSTCOMPILE)
py-cmd.o: $(srcdir)/python/py-cmd.c py-cmd.o: $(srcdir)/python/py-cmd.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-cmd.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-cmd.c
$(POSTCOMPILE) $(POSTCOMPILE)

View File

@ -25,8 +25,8 @@
* Python scripting * Python scripting
** The GDB Python API now has access to symbols, symbol tables, and ** The GDB Python API now has access to breakpoints, symbols, symbol
frame's code blocks. tables, and frame's code blocks.
** New methods gdb.target_charset and gdb.target_wide_charset. ** New methods gdb.target_charset and gdb.target_wide_charset.

View File

@ -709,6 +709,61 @@ get_breakpoint (int num)
} }
void
set_breakpoint_condition (struct breakpoint *b, char *exp,
int from_tty)
{
struct bp_location *loc = b->loc;
for (; loc; loc = loc->next)
{
xfree (loc->cond);
loc->cond = NULL;
}
xfree (b->cond_string);
b->cond_string = NULL;
xfree (b->cond_exp);
b->cond_exp = NULL;
if (*exp == 0)
{
if (from_tty)
printf_filtered (_("Breakpoint %d now unconditional.\n"), b->number);
}
else
{
char *arg = exp;
/* I don't know if it matters whether this is the string the user
typed in or the decompiled expression. */
b->cond_string = xstrdup (arg);
b->condition_not_parsed = 0;
if (is_watchpoint (b))
{
innermost_block = NULL;
arg = exp;
b->cond_exp = parse_exp_1 (&arg, 0, 0);
if (*arg)
error (_("Junk at end of expression"));
b->cond_exp_valid_block = innermost_block;
}
else
{
for (loc = b->loc; loc; loc = loc->next)
{
arg = exp;
loc->cond =
parse_exp_1 (&arg, block_for_pc (loc->address), 0);
if (*arg)
error (_("Junk at end of expression"));
}
}
}
breakpoints_changed ();
observer_notify_breakpoint_modified (b->number);
}
/* condition N EXP -- set break condition of breakpoint N to EXP. */ /* condition N EXP -- set break condition of breakpoint N to EXP. */
static void static void
@ -729,53 +784,7 @@ condition_command (char *arg, int from_tty)
ALL_BREAKPOINTS (b) ALL_BREAKPOINTS (b)
if (b->number == bnum) if (b->number == bnum)
{ {
struct bp_location *loc = b->loc; set_breakpoint_condition (b, arg, from_tty);
for (; loc; loc = loc->next)
{
xfree (loc->cond);
loc->cond = NULL;
}
xfree (b->cond_string);
b->cond_string = NULL;
xfree (b->cond_exp);
b->cond_exp = NULL;
if (*p == 0)
{
if (from_tty)
printf_filtered (_("Breakpoint %d now unconditional.\n"), bnum);
}
else
{
arg = p;
/* I don't know if it matters whether this is the string the user
typed in or the decompiled expression. */
b->cond_string = xstrdup (arg);
b->condition_not_parsed = 0;
if (is_watchpoint (b))
{
innermost_block = NULL;
arg = p;
b->cond_exp = parse_exp_1 (&arg, 0, 0);
if (*arg)
error (_("Junk at end of expression"));
b->cond_exp_valid_block = innermost_block;
}
else
{
for (loc = b->loc; loc; loc = loc->next)
{
arg = p;
loc->cond =
parse_exp_1 (&arg, block_for_pc (loc->address), 0);
if (*arg)
error (_("Junk at end of expression"));
}
}
}
breakpoints_changed ();
observer_notify_breakpoint_modified (b->number);
return; return;
} }

View File

@ -1005,6 +1005,10 @@ extern int breakpoints_always_inserted_mode (void);
in our opinion won't ever trigger. */ in our opinion won't ever trigger. */
extern void breakpoint_retire_moribund (void); extern void breakpoint_retire_moribund (void);
/* Set break condition of breakpoint B to EXP. */
extern void set_breakpoint_condition (struct breakpoint *b, char *exp,
int from_tty);
/* Checks if we are catching syscalls or not. /* Checks if we are catching syscalls or not.
Returns 0 if not, greater than 0 if we are. */ Returns 0 if not, greater than 0 if we are. */
extern int catch_syscall_enabled (void); extern int catch_syscall_enabled (void);

View File

@ -1,3 +1,9 @@
2010-04-09 Phil Muldoon <pmuldoon@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Breakpoints In Python): New Node.
2010-04-08 Stan Shebs <stan@codesourcery.com> 2010-04-08 Stan Shebs <stan@codesourcery.com>
* gdb.texinfo (Tracepoint Packets): Describe disconn and circular * gdb.texinfo (Tracepoint Packets): Describe disconn and circular

View File

@ -19714,6 +19714,7 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
* Symbols In Python:: Python representation of symbols. * Symbols In Python:: Python representation of symbols.
* Symbol Tables In Python:: Python representation of symbol tables. * Symbol Tables In Python:: Python representation of symbol tables.
* Lazy Strings In Python:: Python representation of lazy strings. * Lazy Strings In Python:: Python representation of lazy strings.
* Breakpoints In Python:: Manipulating breakpoints using Python.
@end menu @end menu
@node Basic Python @node Basic Python
@ -19739,6 +19740,12 @@ command as having originated from the user invoking it interactively.
It must be a boolean value. If omitted, it defaults to @code{False}. It must be a boolean value. If omitted, it defaults to @code{False}.
@end defun @end defun
@findex gdb.breakpoints
@defun breakpoints
Return a sequence holding all of @value{GDBN}'s breakpoints.
@xref{Breakpoints In Python}, for more information.
@end defun
@findex gdb.parameter @findex gdb.parameter
@defun parameter parameter @defun parameter parameter
Return the value of a @value{GDBN} parameter. @var{parameter} is a Return the value of a @value{GDBN} parameter. @var{parameter} is a
@ -21279,6 +21286,163 @@ Return the symbol table's source absolute file name.
@end defmethod @end defmethod
@end table @end table
@node Breakpoints In Python
@subsubsection Manipulating breakpoints using Python
@cindex breakpoints in python
@tindex gdb.Breakpoint
Python code can manipulate breakpoints via the @code{gdb.Breakpoint}
class.
@defmethod Breakpoint __init__ spec @r{[}type@r{]} @r{[}wp_class@r{]}
Create a new breakpoint. @var{spec} is a string naming the
location of the breakpoint, or an expression that defines a
watchpoint. The contents can be any location recognized by the
@code{break} command, or in the case of a watchpoint, by the @code{watch}
command. The optional @var{type} denotes the breakpoint to create
from the types defined later in this chapter. This argument can be
either: @code{BP_BREAKPOINT} or @code{BP_WATCHPOINT}. @var{type}
defaults to @code{BP_BREAKPOINT}. The optional @var{wp_class}
argument defines the class of watchpoint to create, if @var{type} is
defined as @code{BP_WATCHPOINT}. If a watchpoint class is not
provided, it is assumed to be a @var{WP_WRITE} class.
@end defmethod
The available watchpoint types represented by constants are defined in the
@code{gdb} module:
@table @code
@findex WP_READ
@findex gdb.WP_READ
@item WP_READ
Read only watchpoint.
@findex WP_WRITE
@findex gdb.WP_WRITE
@item WP_WRITE
Write only watchpoint.
@findex WP_ACCESS
@findex gdb.WP_ACCESS
@item WP_ACCESS
Read/Write watchpoint.
@end table
@defmethod Breakpoint is_valid
Return @code{True} if this @code{Breakpoint} object is valid,
@code{False} otherwise. A @code{Breakpoint} object can become invalid
if the user deletes the breakpoint. In this case, the object still
exists, but the underlying breakpoint does not. In the cases of
watchpoint scope, the watchpoint remains valid even if execution of the
inferior leaves the scope of that watchpoint.
@end defmethod
@defivar Breakpoint enabled
This attribute is @code{True} if the breakpoint is enabled, and
@code{False} otherwise. This attribute is writable.
@end defivar
@defivar Breakpoint silent
This attribute is @code{True} if the breakpoint is silent, and
@code{False} otherwise. This attribute is writable.
Note that a breakpoint can also be silent if it has commands and the
first command is @code{silent}. This is not reported by the
@code{silent} attribute.
@end defivar
@defivar Breakpoint thread
If the breakpoint is thread-specific, this attribute holds the thread
id. If the breakpoint is not thread-specific, this attribute is
@code{None}. This attribute is writable.
@end defivar
@defivar Breakpoint task
If the breakpoint is Ada task-specific, this attribute holds the Ada task
id. If the breakpoint is not task-specific (or the underlying
language is not Ada), this attribute is @code{None}. This attribute
is writable.
@end defivar
@defivar Breakpoint ignore_count
This attribute holds the ignore count for the breakpoint, an integer.
This attribute is writable.
@end defivar
@defivar Breakpoint number
This attribute holds the breakpoint's number --- the identifier used by
the user to manipulate the breakpoint. This attribute is not writable.
@end defivar
@defivar Breakpoint type
This attribute holds the breakpoint's type --- the identifier used to
determine the actual breakpoint type or use-case. This attribute is not
writable.
@end defivar
The available types are represented by constants defined in the @code{gdb}
module:
@table @code
@findex BP_BREAKPOINT
@findex gdb.BP_BREAKPOINT
@item BP_BREAKPOINT
Normal code breakpoint.
@findex BP_WATCHPOINT
@findex gdb.BP_WATCHPOINT
@item BP_WATCHPOINT
Watchpoint breakpoint.
@findex BP_HARDWARE_WATCHPOINT
@findex gdb.BP_HARDWARE_WATCHPOINT
@item BP_HARDWARE_WATCHPOINT
Hardware assisted watchpoint.
@findex BP_READ_WATCHPOINT
@findex gdb.BP_READ_WATCHPOINT
@item BP_READ_WATCHPOINT
Hardware assisted read watchpoint.
@findex BP_ACCESS_WATCHPOINT
@findex gdb.BP_ACCESS_WATCHPOINT
@item BP_ACCESS_WATCHPOINT
Hardware assisted access watchpoint.
@end table
@defivar Breakpoint hit_count
This attribute holds the hit count for the breakpoint, an integer.
This attribute is writable, but currently it can only be set to zero.
@end defivar
@defivar Breakpoint location
This attribute holds the location of the breakpoint, as specified by
the user. It is a string. If the breakpoint does not have a location
(that is, it is a watchpoint) the attribute's value is @code{None}. This
attribute is not writable.
@end defivar
@defivar Breakpoint expression
This attribute holds a breakpoint expression, as specified by
the user. It is a string. If the breakpoint does not have an
expression (the breakpoint is not a watchpoint) the attribute's value
is @code{None}. This attribute is not writable.
@end defivar
@defivar Breakpoint condition
This attribute holds the condition of the breakpoint, as specified by
the user. It is a string. If there is no condition, this attribute's
value is @code{None}. This attribute is writable.
@end defivar
@defivar Breakpoint commands
This attribute holds the commands attached to the breakpoint. If
there are commands, this attribute's value is a string holding all the
commands, separated by newlines. If there are no commands, this
attribute is @code{None}. This attribute is not writable.
@end defivar
@node Lazy Strings In Python @node Lazy Strings In Python
@subsubsection Python representation of lazy strings. @subsubsection Python representation of lazy strings.

862
gdb/python/py-breakpoint.c Normal file
View File

@ -0,0 +1,862 @@
/* Python interface to breakpoints
Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "value.h"
#include "exceptions.h"
#include "python-internal.h"
#include "charset.h"
#include "breakpoint.h"
#include "gdbcmd.h"
#include "gdbthread.h"
#include "observer.h"
#include "cli/cli-script.h"
#include "ada-lang.h"
/* From breakpoint.c. */
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;
/* Variables used to pass information between the Breakpoint
constructor and the breakpoint-created hook function. */
static breakpoint_object *bppy_pending_object;
struct breakpoint_object
{
PyObject_HEAD
/* The breakpoint number according to gdb. */
int number;
/* The gdb breakpoint object, or NULL if the breakpoint has been
deleted. */
struct breakpoint *bp;
};
/* Require that BREAKPOINT be a valid breakpoint ID; throw a Python
exception if it is invalid. */
#define BPPY_REQUIRE_VALID(Breakpoint) \
do { \
if (! bpnum_is_valid ((Breakpoint)->number)) \
return PyErr_Format (PyExc_RuntimeError, _("Breakpoint %d is invalid."), \
(Breakpoint)->number); \
} while (0)
/* Require that BREAKPOINT be a valid breakpoint ID; throw a Python
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)) \
{ \
PyErr_Format (PyExc_RuntimeError, _("Breakpoint %d is invalid."), \
(Breakpoint)->number); \
return -1; \
} \
} while (0)
/* This is used to initialize various gdb.bp_* constants. */
struct pybp_code
{
/* The name. */
const char *name;
/* The code. */
enum type_code code;
};
/* Entries related to the type of user set breakpoints. */
static struct pybp_code pybp_codes[] =
{
{ "BP_NONE", bp_none},
{ "BP_BREAKPOINT", bp_breakpoint},
{ "BP_WATCHPOINT", bp_watchpoint},
{ "BP_HARDWARE_WATCHPOINT", bp_hardware_watchpoint},
{ "BP_READ_WATCHPOINT", bp_read_watchpoint},
{ "BP_ACCESS_WATCHPOINT", bp_access_watchpoint},
{NULL} /* Sentinel. */
};
/* Entries related to the type of watchpoint. */
static struct pybp_code pybp_watch_types[] =
{
{ "WP_READ", hw_read},
{ "WP_WRITE", hw_write},
{ "WP_ACCESS", hw_access},
{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)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
if (self_bp->bp)
Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
/* Python function to test whether or not the breakpoint is enabled. */
static PyObject *
bppy_get_enabled (PyObject *self, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
BPPY_REQUIRE_VALID (self_bp);
if (! self_bp->bp)
Py_RETURN_FALSE;
if (self_bp->bp->enable_state == bp_enabled)
Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
/* Python function to test whether or not the breakpoint is silent. */
static PyObject *
bppy_get_silent (PyObject *self, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
BPPY_REQUIRE_VALID (self_bp);
if (self_bp->bp->silent)
Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
/* Python function to set the enabled state of a breakpoint. */
static int
bppy_set_enabled (PyObject *self, PyObject *newvalue, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
int cmp;
BPPY_SET_REQUIRE_VALID (self_bp);
if (newvalue == NULL)
{
PyErr_SetString (PyExc_TypeError,
_("Cannot delete `enabled' attribute."));
return -1;
}
else if (! PyBool_Check (newvalue))
{
PyErr_SetString (PyExc_TypeError,
_("The value of `enabled' must be a boolean."));
return -1;
}
cmp = PyObject_IsTrue (newvalue);
if (cmp < 0)
return -1;
else if (cmp == 1)
enable_breakpoint (self_bp->bp);
else
disable_breakpoint (self_bp->bp);
return 0;
}
/* Python function to set the 'silent' state of a breakpoint. */
static int
bppy_set_silent (PyObject *self, PyObject *newvalue, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
int cmp;
BPPY_SET_REQUIRE_VALID (self_bp);
if (newvalue == NULL)
{
PyErr_SetString (PyExc_TypeError,
_("Cannot delete `silent' attribute."));
return -1;
}
else if (! PyBool_Check (newvalue))
{
PyErr_SetString (PyExc_TypeError,
_("The value of `silent' must be a boolean."));
return -1;
}
cmp = PyObject_IsTrue (newvalue);
if (cmp < 0)
return -1;
else
self_bp->bp->silent = cmp;
return 0;
}
/* Python function to set the thread of a breakpoint. */
static int
bppy_set_thread (PyObject *self, PyObject *newvalue, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
int id;
BPPY_SET_REQUIRE_VALID (self_bp);
if (newvalue == NULL)
{
PyErr_SetString (PyExc_TypeError,
_("Cannot delete `thread' attribute."));
return -1;
}
else if (PyInt_Check (newvalue))
{
id = (int) PyInt_AsLong (newvalue);
if (! valid_thread_id (id))
{
PyErr_SetString (PyExc_RuntimeError,
_("Invalid thread ID."));
return -1;
}
}
else if (newvalue == Py_None)
id = -1;
else
{
PyErr_SetString (PyExc_TypeError,
_("The value of `thread' must be an integer or None."));
return -1;
}
self_bp->bp->thread = id;
return 0;
}
/* Python function to set the (Ada) task of a breakpoint. */
static int
bppy_set_task (PyObject *self, PyObject *newvalue, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
int id;
BPPY_SET_REQUIRE_VALID (self_bp);
if (newvalue == NULL)
{
PyErr_SetString (PyExc_TypeError,
_("Cannot delete `task' attribute."));
return -1;
}
else if (PyInt_Check (newvalue))
{
id = (int) PyInt_AsLong (newvalue);
if (! valid_task_id (id))
{
PyErr_SetString (PyExc_RuntimeError,
_("Invalid task ID."));
return -1;
}
}
else if (newvalue == Py_None)
id = 0;
else
{
PyErr_SetString (PyExc_TypeError,
_("The value of `task' must be an integer or None."));
return -1;
}
self_bp->bp->task = id;
return 0;
}
/* Python function to set the ignore count of a breakpoint. */
static int
bppy_set_ignore_count (PyObject *self, PyObject *newvalue, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
long value;
BPPY_SET_REQUIRE_VALID (self_bp);
if (newvalue == NULL)
{
PyErr_SetString (PyExc_TypeError,
_("Cannot delete `ignore_count' attribute."));
return -1;
}
else if (! PyInt_Check (newvalue))
{
PyErr_SetString (PyExc_TypeError,
_("The value of `ignore_count' must be an integer."));
return -1;
}
value = PyInt_AsLong (newvalue);
if (value < 0)
value = 0;
set_ignore_count (self_bp->number, (int) value, 0);
return 0;
}
/* Python function to set the hit count of a breakpoint. */
static int
bppy_set_hit_count (PyObject *self, PyObject *newvalue, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
BPPY_SET_REQUIRE_VALID (self_bp);
if (newvalue == NULL)
{
PyErr_SetString (PyExc_TypeError,
_("Cannot delete `hit_count' attribute."));
return -1;
}
else if (! PyInt_Check (newvalue) || PyInt_AsLong (newvalue) != 0)
{
PyErr_SetString (PyExc_AttributeError,
_("The value of `hit_count' must be zero."));
return -1;
}
self_bp->bp->hit_count = 0;
return 0;
}
/* Python function to get the location of a breakpoint. */
static PyObject *
bppy_get_location (PyObject *self, void *closure)
{
char *str;
breakpoint_object *obj = (breakpoint_object *) self;
BPPY_REQUIRE_VALID (obj);
if (obj->bp->type != bp_breakpoint)
Py_RETURN_NONE;
str = obj->bp->addr_string;
if (! str)
str = "";
return PyString_Decode (str, strlen (str), host_charset (), NULL);
}
/* Python function to get the breakpoint expression. */
static PyObject *
bppy_get_expression (PyObject *self, void *closure)
{
char *str;
breakpoint_object *obj = (breakpoint_object *) self;
BPPY_REQUIRE_VALID (obj);
if (obj->bp->type != bp_watchpoint
&& obj->bp->type != bp_hardware_watchpoint
&& obj->bp->type != bp_read_watchpoint
&& obj->bp->type != bp_access_watchpoint)
Py_RETURN_NONE;
str = obj->bp->exp_string;
if (! str)
str = "";
return PyString_Decode (str, strlen (str), host_charset (), NULL);
}
/* Python function to get the condition expression of a breakpoint. */
static PyObject *
bppy_get_condition (PyObject *self, void *closure)
{
char *str;
breakpoint_object *obj = (breakpoint_object *) self;
BPPY_REQUIRE_VALID (obj);
str = obj->bp->cond_string;
if (! str)
Py_RETURN_NONE;
return PyString_Decode (str, strlen (str), host_charset (), NULL);
}
static int
bppy_set_condition (PyObject *self, PyObject *newvalue, void *closure)
{
char *exp;
breakpoint_object *self_bp = (breakpoint_object *) self;
volatile struct gdb_exception except;
BPPY_SET_REQUIRE_VALID (self_bp);
if (newvalue == NULL)
{
PyErr_SetString (PyExc_TypeError,
_("Cannot delete `condition' attribute."));
return -1;
}
else if (newvalue == Py_None)
exp = "";
else
{
exp = python_string_to_host_string (newvalue);
if (exp == NULL)
return -1;
}
TRY_CATCH (except, RETURN_MASK_ALL)
{
set_breakpoint_condition (self_bp->bp, exp, 0);
}
GDB_PY_SET_HANDLE_EXCEPTION (except);
return 0;
}
/* Python function to get the commands attached to a breakpoint. */
static PyObject *
bppy_get_commands (PyObject *self, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
struct breakpoint *bp = self_bp->bp;
long length;
volatile struct gdb_exception except;
struct ui_file *string_file;
struct cleanup *chain;
PyObject *result;
char *cmdstr;
BPPY_REQUIRE_VALID (self_bp);
if (! self_bp->bp->commands)
Py_RETURN_NONE;
string_file = mem_fileopen ();
chain = make_cleanup_ui_file_delete (string_file);
TRY_CATCH (except, RETURN_MASK_ALL)
{
ui_out_redirect (uiout, string_file);
print_command_lines (uiout, breakpoint_commands (bp), 0);
ui_out_redirect (uiout, NULL);
}
cmdstr = ui_file_xstrdup (string_file, &length);
GDB_PY_HANDLE_EXCEPTION (except);
result = PyString_Decode (cmdstr, strlen (cmdstr), host_charset (), NULL);
do_cleanups (chain);
xfree (cmdstr);
return result;
}
/* Python function to get the breakpoint type. */
static PyObject *
bppy_get_type (PyObject *self, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
BPPY_REQUIRE_VALID (self_bp);
return PyInt_FromLong (self_bp->bp->type);
}
/* Python function to get the breakpoint's number. */
static PyObject *
bppy_get_number (PyObject *self, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
BPPY_REQUIRE_VALID (self_bp);
return PyInt_FromLong (self_bp->number);
}
/* Python function to get the breakpoint's thread ID. */
static PyObject *
bppy_get_thread (PyObject *self, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
BPPY_REQUIRE_VALID (self_bp);
if (self_bp->bp->thread == -1)
Py_RETURN_NONE;
return PyInt_FromLong (self_bp->bp->thread);
}
/* Python function to get the breakpoint's task ID (in Ada). */
static PyObject *
bppy_get_task (PyObject *self, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
BPPY_REQUIRE_VALID (self_bp);
if (self_bp->bp->task == 0)
Py_RETURN_NONE;
return PyInt_FromLong (self_bp->bp->task);
}
/* Python function to get the breakpoint's hit count. */
static PyObject *
bppy_get_hit_count (PyObject *self, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
BPPY_REQUIRE_VALID (self_bp);
return PyInt_FromLong (self_bp->bp->hit_count);
}
/* Python function to get the breakpoint's ignore count. */
static PyObject *
bppy_get_ignore_count (PyObject *self, void *closure)
{
breakpoint_object *self_bp = (breakpoint_object *) self;
BPPY_REQUIRE_VALID (self_bp);
return PyInt_FromLong (self_bp->bp->ignore_count);
}
/* Python function to create a new breakpoint. */
static PyObject *
bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
{
PyObject *result;
static char *keywords[] = { "spec", "type", "wp_class", NULL };
char *spec;
int type = bp_breakpoint;
int access_type = hw_write;
volatile struct gdb_exception except;
if (! PyArg_ParseTupleAndKeywords (args, kwargs, "s|ii", keywords,
&spec, &type, &access_type))
return NULL;
result = subtype->tp_alloc (subtype, 0);
if (! result)
return NULL;
bppy_pending_object = (breakpoint_object *) result;
bppy_pending_object->number = -1;
bppy_pending_object->bp = NULL;
TRY_CATCH (except, RETURN_MASK_ALL)
{
switch (type)
{
case bp_breakpoint:
{
create_breakpoint (python_gdbarch,
spec, NULL, -1,
0,
0, 0, 0,
0,
AUTO_BOOLEAN_TRUE,
NULL, 0, 1);
break;
}
case bp_watchpoint:
{
if (access_type == hw_write)
watch_command_wrapper (spec, 0);
else if (access_type == hw_access)
awatch_command_wrapper (spec, 0);
else if (access_type == hw_read)
rwatch_command_wrapper (spec, 0);
else
error(_("Cannot understand watchpoint access type."));
break;
}
default:
error(_("Do not understand breakpoint type to set."));
}
}
if (except.reason < 0)
{
subtype->tp_free (result);
return PyErr_Format (except.reason == RETURN_QUIT
? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
"%s", except.message);
}
BPPY_REQUIRE_VALID ((breakpoint_object *) result);
return result;
}
/* Static function to return a tuple holding all breakpoints. */
PyObject *
gdbpy_breakpoints (PyObject *self, PyObject *args)
{
PyObject *result;
if (bppy_live == 0)
Py_RETURN_NONE;
result = PyTuple_New (bppy_live);
if (result)
{
int i, out = 0;
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;
}
}
return result;
}
/* Event callback functions. */
/* Callback that is used when a breakpoint is created. This function
will create a new Python breakpoint object. */
static void
gdbpy_breakpoint_created (int num)
{
breakpoint_object *newbp;
struct breakpoint *bp = NULL;
PyGILState_STATE state;
if (num < 0)
return;
bp = get_breakpoint (num);
if (! bp)
return;
if (bp->type != bp_breakpoint
&& bp->type != bp_watchpoint
&& bp->type != bp_hardware_watchpoint
&& bp->type != bp_read_watchpoint
&& 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)
{
newbp = bppy_pending_object;
bppy_pending_object = NULL;
}
else
newbp = PyObject_New (breakpoint_object, &breakpoint_object_type);
if (newbp)
{
PyObject *hookfn;
newbp->number = num;
newbp->bp = bp;
bppy_breakpoints[num] = newbp;
Py_INCREF (newbp);
}
/* Just ignore errors here. */
PyErr_Clear ();
PyGILState_Release (state);
}
/* Callback that is used when a breakpoint is deleted. This will
invalidate the corresponding Python object. */
static void
gdbpy_breakpoint_deleted (int num)
{
PyGILState_STATE state;
state = PyGILState_Ensure ();
if (bpnum_is_valid (num))
{
bppy_breakpoints[num]->bp = NULL;
Py_DECREF (bppy_breakpoints[num]);
bppy_breakpoints[num] = NULL;
--bppy_live;
}
PyGILState_Release (state);
}
/* Initialize the Python breakpoint code. */
void
gdbpy_initialize_breakpoints (void)
{
int i;
breakpoint_object_type.tp_new = bppy_new;
if (PyType_Ready (&breakpoint_object_type) < 0)
return;
Py_INCREF (&breakpoint_object_type);
PyModule_AddObject (gdb_module, "Breakpoint",
(PyObject *) &breakpoint_object_type);
observer_attach_breakpoint_created (gdbpy_breakpoint_created);
observer_attach_breakpoint_deleted (gdbpy_breakpoint_deleted);
/* Add breakpoint types constants. */
for (i = 0; pybp_codes[i].name; ++i)
{
if (PyModule_AddIntConstant (gdb_module,
/* Cast needed for Python 2.4. */
(char *) pybp_codes[i].name,
pybp_codes[i].code) < 0)
return;
}
/* Add watchpoint types constants. */
for (i = 0; pybp_watch_types[i].name; ++i)
{
if (PyModule_AddIntConstant (gdb_module,
/* Cast needed for Python 2.4. */
(char *) pybp_watch_types[i].name,
pybp_watch_types[i].code) < 0)
return;
}
}
static PyGetSetDef breakpoint_object_getset[] = {
{ "enabled", bppy_get_enabled, bppy_set_enabled,
"Boolean telling whether the breakpoint is enabled.", NULL },
{ "silent", bppy_get_silent, bppy_set_silent,
"Boolean telling whether the breakpoint is silent.", NULL },
{ "thread", bppy_get_thread, bppy_set_thread,
"Thread ID for the breakpoint.\n\
If the value is a thread ID (integer), then this is a thread-specific breakpoint.\n\
If the value is None, then this breakpoint is not thread-specific.\n\
No other type of value can be used.", NULL },
{ "task", bppy_get_task, bppy_set_task,
"Thread ID for the breakpoint.\n\
If the value is a task ID (integer), then this is an Ada task-specific breakpoint.\n\
If the value is None, then this breakpoint is not task-specific.\n\
No other type of value can be used.", NULL },
{ "ignore_count", bppy_get_ignore_count, bppy_set_ignore_count,
"Number of times this breakpoint should be automatically continued.",
NULL },
{ "number", bppy_get_number, NULL,
"Breakpoint's number assigned by GDB.", NULL },
{ "hit_count", bppy_get_hit_count, bppy_set_hit_count,
"Number of times the breakpoint has been hit.\n\
Can be set to zero to clear the count. No other value is valid\n\
when setting this property.", NULL },
{ "location", bppy_get_location, NULL,
"Location of the breakpoint, as specified by the user.", NULL},
{ "expression", bppy_get_expression, NULL,
"Expression of the breakpoint, as specified by the user.", NULL},
{ "condition", bppy_get_condition, bppy_set_condition,
"Condition of the breakpoint, as specified by the user,\
or None if no condition set."},
{ "commands", bppy_get_commands, NULL,
"Commands of the breakpoint, as specified by the user."},
{ "type", bppy_get_type, NULL,
"Type of breakpoint."},
{ NULL } /* Sentinel. */
};
static PyMethodDef breakpoint_object_methods[] =
{
{ "is_valid", bppy_is_valid, METH_NOARGS,
"Return true if this breakpoint is valid, false if not." },
{ NULL } /* Sentinel. */
};
static PyTypeObject breakpoint_object_type =
{
PyObject_HEAD_INIT (NULL)
0, /*ob_size*/
"gdb.Breakpoint", /*tp_name*/
sizeof (breakpoint_object), /*tp_basicsize*/
0, /*tp_itemsize*/
0, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"GDB breakpoint object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
breakpoint_object_methods, /* tp_methods */
0, /* tp_members */
breakpoint_object_getset /* tp_getset */
};

View File

@ -75,6 +75,7 @@ extern PyTypeObject block_object_type;
extern PyTypeObject symbol_object_type; extern PyTypeObject symbol_object_type;
PyObject *gdbpy_history (PyObject *self, PyObject *args); PyObject *gdbpy_history (PyObject *self, PyObject *args);
PyObject *gdbpy_breakpoints (PyObject *, PyObject *);
PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *); PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw); PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw);
PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args); PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args);
@ -82,6 +83,7 @@ PyObject *gdbpy_block_for_pc (PyObject *self, PyObject *args);
PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw); PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw);
PyObject *gdbpy_create_lazy_string_object (CORE_ADDR address, long length, PyObject *gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
const char *encoding, struct type *type); const char *encoding, struct type *type);
PyObject *gdbpy_get_hook_function (const char *);
PyObject *symtab_and_line_to_sal_object (struct symtab_and_line sal); PyObject *symtab_and_line_to_sal_object (struct symtab_and_line sal);
PyObject *symtab_to_symtab_object (struct symtab *symtab); PyObject *symtab_to_symtab_object (struct symtab *symtab);
@ -111,6 +113,7 @@ void gdbpy_initialize_blocks (void);
void gdbpy_initialize_types (void); void gdbpy_initialize_types (void);
void gdbpy_initialize_functions (void); void gdbpy_initialize_functions (void);
void gdbpy_initialize_objfile (void); void gdbpy_initialize_objfile (void);
void gdbpy_initialize_breakpoints (void);
void gdbpy_initialize_lazy_string (void); void gdbpy_initialize_lazy_string (void);
struct cleanup *make_cleanup_py_decref (PyObject *py); struct cleanup *make_cleanup_py_decref (PyObject *py);
@ -131,6 +134,18 @@ extern const struct language_defn *python_language;
"%s", Exception.message); \ "%s", Exception.message); \
} while (0) } while (0)
/* Use this after a TRY_EXCEPT to throw the appropriate Python
exception. This macro is for use inside setter functions. */
#define GDB_PY_SET_HANDLE_EXCEPTION(Exception) \
do { \
if (Exception.reason < 0) \
{ \
PyErr_Format (Exception.reason == RETURN_QUIT \
? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
"%s", Exception.message); \
return -1; \
} \
} while (0)
void gdbpy_print_stack (void); void gdbpy_print_stack (void);

View File

@ -668,6 +668,7 @@ Enables or disables auto-loading of Python code when an object is opened."),
gdbpy_initialize_functions (); gdbpy_initialize_functions ();
gdbpy_initialize_types (); gdbpy_initialize_types ();
gdbpy_initialize_objfile (); gdbpy_initialize_objfile ();
gdbpy_initialize_breakpoints ();
gdbpy_initialize_lazy_string (); gdbpy_initialize_lazy_string ();
PyRun_SimpleString ("import gdb"); PyRun_SimpleString ("import gdb");
@ -726,6 +727,9 @@ static PyMethodDef GdbMethods[] =
{ "parameter", gdbpy_parameter, METH_VARARGS, { "parameter", gdbpy_parameter, METH_VARARGS,
"Return a gdb parameter's value" }, "Return a gdb parameter's value" },
{ "breakpoints", gdbpy_breakpoints, METH_NOARGS,
"Return a tuple of all breakpoint objects" },
{ "default_visualizer", gdbpy_default_visualizer, METH_VARARGS, { "default_visualizer", gdbpy_default_visualizer, METH_VARARGS,
"Find the default visualizer for a Value." }, "Find the default visualizer for a Value." },

View File

@ -1,3 +1,8 @@
2010-04-09 Phil Muldoon <pmuldoon@redhat.com>
* gdb.python/py-breakpoint.exp: New File.
* gdb.python/py-breakpoint.C: Ditto.
2010-04-08 Stan Shebs <stan@codesourcery.com> 2010-04-08 Stan Shebs <stan@codesourcery.com>
* gdb.trace/actions.exp: Clear default-collect. * gdb.trace/actions.exp: Clear default-collect.

View File

@ -2,7 +2,7 @@ VPATH = @srcdir@
srcdir = @srcdir@ srcdir = @srcdir@
EXECUTABLES = py-type py-value py-prettyprint py-template py-block \ EXECUTABLES = py-type py-value py-prettyprint py-template py-block \
py-symbol py-mi py-symbol py-mi py-breakpoint
all info install-info dvi install uninstall installcheck check: all info install-info dvi install uninstall installcheck check:
@echo "Nothing to be done for $@..." @echo "Nothing to be done for $@..."

View File

@ -0,0 +1,46 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2010 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
int multiply (int i)
{
return i * i;
}
int add (int i)
{
return i + i;
}
int main (int argc, char *argv[])
{
int foo = 5;
int bar = 42;
int result = 0;
int i;
for (i = 0; i < 10; i++)
{
result += multiply (foo); /* Break at multiply. */
result += add (bar); /* Break at add. */
}
return 0; /* Break at end. */
}

View File

@ -0,0 +1,142 @@
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This file is part of the GDB testsuite. It tests the mechanism
# exposing values to Python.
if $tracelevel then {
strace $tracelevel
}
set testfile "py-breakpoint"
set srcfile ${testfile}.c
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
return -1
}
# Run a command in GDB, and report a failure if a Python exception is thrown.
# If report_pass is true, report a pass if no exception is thrown.
proc gdb_py_test_silent_cmd {cmd name report_pass} {
global gdb_prompt
gdb_test_multiple $cmd $name {
-re "Traceback.*$gdb_prompt $" { fail $name }
-re "$gdb_prompt $" { if $report_pass { pass $name } }
}
}
# Start with a fresh gdb.
clean_restart ${testfile}
# Skip all tests if Python scripting is not enabled.
if { [skip_python_tests] } { continue }
if ![runto_main] then {
fail "Cannot run to main."
return 0
}
global hex decimal
# Initially there should be one breakpoint: main.
gdb_py_test_silent_cmd "python blist = gdb.breakpoints()" "Get Breakpoint List" 0
gdb_test "python print blist\[0\]" "<gdb.Breakpoint object at $hex>" "Check obj exists"
gdb_test "python print blist\[0\].location" "main." "Check breakpoint location"
gdb_breakpoint [gdb_get_line_number "Break at multiply."]
gdb_continue_to_breakpoint "Break at multiply."
# Check that the Python breakpoint code noted the addition of a
# breakpoint "behind the scenes".
gdb_py_test_silent_cmd "python blist = gdb.breakpoints()" "Get Breakpoint List" 0
gdb_test "python print len(blist)" "2" "Check for two breakpoints"
gdb_test "python print blist\[0\]" "<gdb.Breakpoint object at $hex>" "Check obj exists"
gdb_test "python print blist\[0\].location" "main." "Check breakpoint location"
gdb_test "python print blist\[1\]" "<gdb.Breakpoint object at $hex>" "Check obj exists"
gdb_test "python print blist\[1\].location" "py-breakpoint\.c:41*" "Check breakpoint location"
# Check hit and ignore counts.
gdb_test "python print blist\[1\].hit_count" "1" "Check breakpoint hit count"
gdb_py_test_silent_cmd "python blist\[1\].ignore_count = 4" "Set breakpoint hit count" 0
gdb_continue_to_breakpoint "Break at multiply."
gdb_test "python print blist\[1\].hit_count" "6" "Check breakpoint hit count"
gdb_test "print result" "545" "Check expected variable result after 6 iterations"
# Test breakpoint is enabled and disabled correctly..
gdb_breakpoint [gdb_get_line_number "Break at add."]
gdb_continue_to_breakpoint "Break at add."
gdb_test "python print blist\[1\].enabled" "True" "Check breakpoint enabled."
gdb_py_test_silent_cmd "python blist\[1\].enabled = False" "Set breakpoint disabled." 0
gdb_continue_to_breakpoint "Break at add."
gdb_py_test_silent_cmd "python blist\[1\].enabled = True" "Set breakpoint enabled." 0
gdb_continue_to_breakpoint "Break at multiply."
# Test other getters and setters.
gdb_py_test_silent_cmd "python blist = gdb.breakpoints()" "Get Breakpoint List" 0
gdb_test "python print blist\[1\].thread" "None" "Check breakpoint thread"
gdb_test "python print blist\[1\].type == gdb.BP_BREAKPOINT" "True" "Check breakpoint type"
gdb_test "python print blist\[0\].number" "1" "Check breakpoint number"
gdb_test "python print blist\[1\].number" "2" "Check breakpoint number"
gdb_test "python print blist\[2\].number" "3" "Check breakpoint number"
# Start with a fresh gdb.
clean_restart ${testfile}
if ![runto_main] then {
fail "Cannot run to main."
return 0
}
# Test conditional setting.
set bp_location1 [gdb_get_line_number "Break at multiply."]
gdb_py_test_silent_cmd "python bp1 = gdb.Breakpoint (\"$bp_location1\")" "Set breakpoint" 0
gdb_continue_to_breakpoint "Break at multiply."
gdb_py_test_silent_cmd "python bp1.condition = \"i == 5\"" "Set breakpoint" 0
gdb_test "python print bp1.condition" "i == 5" "Test conditional has been set"
gdb_continue_to_breakpoint "Break at multiply."
gdb_test "print i" "5" "Test conditional breakpoint stopped after five iterations"
gdb_py_test_silent_cmd "python bp1.condition = None" "Clear condition" 0
gdb_test "python print bp1.condition" "None" "Test conditional read"
gdb_continue_to_breakpoint "Break at multiply."
gdb_test "print i" "6" "Test breakpoint stopped after six iterations"
# Test commands.
gdb_breakpoint [gdb_get_line_number "Break at add."]
set test {commands $bpnum}
gdb_test_multiple $test $test { -re "\r\n>$" { pass $test } }
set test {print "Command for breakpoint has been executed."}
gdb_test_multiple $test $test { -re "\r\n>$" { pass $test } }
set test {print result}
gdb_test_multiple $test $test { -re "\r\n>$" { pass $test } }
gdb_test "end"
gdb_py_test_silent_cmd "python blist = gdb.breakpoints()" "Get Breakpoint List" 0
gdb_test "python print blist\[len(blist)-1\].commands" "print \"Command for breakpoint has been executed.\".*print result"
# Watchpoints
# Start with a fresh gdb.
clean_restart ${testfile}
if ![runto_main] then {
fail "Cannot run to main."
return 0
}
gdb_py_test_silent_cmd "python wp1 = gdb.Breakpoint (\"result\", type=gdb.BP_WATCHPOINT, wp_class=gdb.WP_WRITE )" "Set watchpoint" 0
gdb_test "continue" ".*watchpoint.*result.*Old value = 0.*New value = 25.*main.*" "Test watchpoint write"