From f76c27b5bdd446964d9920464b2f761ae7a4f62a Mon Sep 17 00:00:00 2001 From: Phil Muldoon Date: Thu, 7 Nov 2013 12:04:45 +0000 Subject: [PATCH] 2013-11-07 Phil Muldoon * python/py-breakpoint.c (bppy_get_temporary): New function. (bppy_init): New keyword: temporary. Parse it and set breakpoint to temporary if True. 2013-11-07 Phil Muldoon * gdb.python/py-breakpoint.exp: Add temporary breakpoint tests. 2013-11-07 Phil Muldoon * gdb.texinfo (Breakpoints In Python): Document temporary option in breakpoint constructor, and add documentation to the temporary attribute. --- gdb/ChangeLog | 7 ++++ gdb/NEWS | 1 + gdb/doc/ChangeLog | 6 +++ gdb/doc/gdb.texinfo | 47 ++++++++++++++-------- gdb/python/py-breakpoint.c | 38 +++++++++++++++-- gdb/testsuite/ChangeLog | 4 ++ gdb/testsuite/gdb.python/py-breakpoint.exp | 34 ++++++++++++++++ 7 files changed, 117 insertions(+), 20 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 01f4453988..090aee7e36 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2013-11-07 Phil Muldoon + + * NEWS: Document Python temporary breakpoint support. + * python/py-breakpoint.c (bppy_get_temporary): New function. + (bppy_init): New keyword: temporary. Parse it and set breakpoint + to temporary if True. + 2013-11-07 Jose E. Marchesi * sparc-tdep.c (sparc_analyze_control_transfer): Assertion diff --git a/gdb/NEWS b/gdb/NEWS index efeda684b7..779cf30f47 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -35,6 +35,7 @@ * Python scripting ** Frame filters and frame decorators have been added. + ** Temporary breakpoints are now supported. * New targets diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 12ceb01511..1a29b4f877 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,9 @@ +2013-11-07 Phil Muldoon + + * gdb.texinfo (Breakpoints In Python): Document temporary + option in breakpoint constructor, and add documentation to the + temporary attribute. + 2013-11-07 Yao Qi * gdb.texinfo (GDB/MI Variable Objects): Update doc about the diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 80ddaf9552..c735b90173 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -27025,22 +27025,27 @@ Return the static block of the underlying symbol table. Python code can manipulate breakpoints via the @code{gdb.Breakpoint} class. -@defun Breakpoint.__init__ (spec @r{[}, type @r{[}, wp_class @r{[},internal@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{gdb.BP_BREAKPOINT} or @code{gdb.BP_WATCHPOINT}. @var{type} -defaults to @code{gdb.BP_BREAKPOINT}. The optional @var{internal} argument -allows the breakpoint to become invisible to the user. The breakpoint -will neither be reported when created, nor will it be listed in the -output from @code{info breakpoints} (but will be listed with the -@code{maint info breakpoints} command). The optional @var{wp_class} -argument defines the class of watchpoint to create, if @var{type} is -@code{gdb.BP_WATCHPOINT}. If a watchpoint class is not provided, it is -assumed to be a @code{gdb.WP_WRITE} class. +@defun Breakpoint.__init__ (spec @r{[}, type @r{[}, wp_class @r{[},internal @r{[},temporary@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{gdb.BP_BREAKPOINT} or @code{gdb.BP_WATCHPOINT}. @var{type} +defaults to @code{gdb.BP_BREAKPOINT}. The optional @var{internal} +argument allows the breakpoint to become invisible to the user. The +breakpoint will neither be reported when created, nor will it be +listed in the output from @code{info breakpoints} (but will be listed +with the @code{maint info breakpoints} command). The optional +@var{temporary} argument makes the breakpoint a temporary breakpoint. +Temporary breakpoints are deleted after they have been hit. Any +further access to the Python breakpoint after it has been hit will +result in a runtime error (as that breakpoint has now been +automatically deleted). The optional @var{wp_class} argument defines +the class of watchpoint to create, if @var{type} is +@code{gdb.BP_WATCHPOINT}. If a watchpoint class is not provided, it +is assumed to be a @code{gdb.WP_WRITE} class. @end defun @defun Breakpoint.stop (self) @@ -27161,6 +27166,16 @@ when set, or when the @samp{info breakpoints} command is run. This attribute is not writable. @end defvar +@defvar Breakpoint.temporary +This attribute indicates whether the breakpoint was created as a +temporary breakpoint. Temporary breakpoints are automatically deleted +after that breakpoint has been hit. Access to this attribute, and all +other attributes and functions other than the @code{is_valid} +function, will result in an error after the breakpoint has been hit +(as it has been automatically deleted). This attribute is not +writable. +@end defvar + The available types are represented by constants defined in the @code{gdb} module: diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c index 87f1fdc1f8..e83471e5f2 100644 --- a/gdb/python/py-breakpoint.c +++ b/gdb/python/py-breakpoint.c @@ -529,6 +529,23 @@ bppy_get_visibility (PyObject *self, void *closure) Py_RETURN_TRUE; } +/* Python function to determine if the breakpoint is a temporary + breakpoint. */ + +static PyObject * +bppy_get_temporary (PyObject *self, void *closure) +{ + breakpoint_object *self_bp = (breakpoint_object *) self; + + BPPY_REQUIRE_VALID (self_bp); + + if (self_bp->bp->disposition == disp_del + || self_bp->bp->disposition == disp_del_at_next_stop) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; +} + /* Python function to get the breakpoint's number. */ static PyObject * bppy_get_number (PyObject *self, void *closure) @@ -594,16 +611,20 @@ bppy_get_ignore_count (PyObject *self, void *closure) static int bppy_init (PyObject *self, PyObject *args, PyObject *kwargs) { - static char *keywords[] = { "spec", "type", "wp_class", "internal", NULL }; + static char *keywords[] = { "spec", "type", "wp_class", "internal", + "temporary", NULL }; const char *spec; int type = bp_breakpoint; int access_type = hw_write; PyObject *internal = NULL; + PyObject *temporary = NULL; int internal_bp = 0; + int temporary_bp = 0; volatile struct gdb_exception except; - if (! PyArg_ParseTupleAndKeywords (args, kwargs, "s|iiO", keywords, - &spec, &type, &access_type, &internal)) + if (! PyArg_ParseTupleAndKeywords (args, kwargs, "s|iiOO", keywords, + &spec, &type, &access_type, + &internal, &temporary)) return -1; if (internal) @@ -613,6 +634,13 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs) return -1; } + if (temporary != NULL) + { + temporary_bp = PyObject_IsTrue (temporary); + if (temporary_bp == -1) + return -1; + } + bppy_pending_object = (breakpoint_object *) self; bppy_pending_object->number = -1; bppy_pending_object->bp = NULL; @@ -629,7 +657,7 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs) create_breakpoint (python_gdbarch, copy, NULL, -1, NULL, 0, - 0, bp_breakpoint, + temporary_bp, bp_breakpoint, 0, AUTO_BOOLEAN_TRUE, &bkpt_breakpoint_ops, @@ -973,6 +1001,8 @@ or None if no condition set."}, "Type of breakpoint."}, { "visible", bppy_get_visibility, NULL, "Whether the breakpoint is visible to the user."}, + { "temporary", bppy_get_temporary, NULL, + "Whether this breakpoint is a temporary breakpoint."}, { NULL } /* Sentinel. */ }; diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 40ff2980e9..11ca125e58 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2013-11-07 Phil Muldoon + + * gdb.python/py-breakpoint.exp: Add temporary breakpoint tests. + 2013-11-06 Doug Evans * gdb.python/py-arch.exp: Tweak test name for bad memory access test. diff --git a/gdb/testsuite/gdb.python/py-breakpoint.exp b/gdb/testsuite/gdb.python/py-breakpoint.exp index 687182dc1e..e2a169b549 100644 --- a/gdb/testsuite/gdb.python/py-breakpoint.exp +++ b/gdb/testsuite/gdb.python/py-breakpoint.exp @@ -300,3 +300,37 @@ gdb_py_test_silent_cmd "python wp1 = wp_eval (\"result\", type=gdb.BP_WATCHPOIN gdb_test "continue" ".*\[Ww\]atchpoint.*result.*Old value =.*New value = 788.*" "Test watchpoint write" gdb_test "python print (never_eval_bp1.count)" "0" \ "Check that this unrelated breakpoints eval function was never called." + +# Test temporary breakpoint + +# Start with a fresh gdb. +clean_restart ${testfile} + +if ![runto_main] then { + fail "Cannot run to main." + return 0 +} +delete_breakpoints +gdb_py_test_multiple "Sub-class and check temporary breakpoint" \ + "python" "" \ + "class temp_bp (gdb.Breakpoint):" "" \ + " count = 0" "" \ + " def stop (self):" "" \ + " self.count = self.count + 1" "" \ + " return True" "" \ + "end" "" +gdb_py_test_silent_cmd "python ibp = temp_bp(\"$ibp_location\", temporary=True)" \ + "Set temporary breakpoint" 0 +gdb_test "info breakpoints" "2.*breakpoint.*del.*py-breakpoint\.c:$ibp_location.*" \ + "Check info breakpoints shows breakpoint with temporary status" +gdb_test "python print (ibp.location)" "py-breakpoint\.c:$ibp_location*" \ + "Check temporary breakpoint location" +gdb_test "python print (ibp.temporary)" "True" \ + "Check breakpoint temporary status" +gdb_continue_to_breakpoint "Break at multiply." ".*/$srcfile:$ibp_location.*" +gdb_test "python print (ibp.count)" "1" \ + "Check temporary stop callback executed before deletion." +gdb_test "python print (ibp.temporary)" "RuntimeError: Breakpoint 2 is invalid.*" \ + "Check temporary breakpoint is deleted after being hit" +gdb_test "info breakpoints" "No breakpoints or watchpoints.*" \ + "Check info breakpoints shows temporary breakpoint is deleted"