From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27462 invoked by alias); 9 Sep 2013 10:05:17 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 27453 invoked by uid 89); 9 Sep 2013 10:05:17 -0000 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 09 Sep 2013 10:05:17 +0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.9 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r89A5Ds3017446 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 9 Sep 2013 06:05:14 -0400 Received: from localhost.localdomain (ovpn-112-30.ams2.redhat.com [10.36.112.30]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r89A5CsS021493 for ; Mon, 9 Sep 2013 06:05:13 -0400 Message-ID: <522D9D57.5030309@redhat.com> Date: Mon, 09 Sep 2013 10:05:00 -0000 From: Phil Muldoon MIME-Version: 1.0 To: gdb-patches@sourceware.org Subject: [python][patch] Add temporary breakpoint features to Python breakpoints. Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-IsSubscribed: yes X-SW-Source: 2013-09/txt/msg00277.txt.bz2 This patch allows Python breakpoints to be made temporary on creation. It adds an optional argument, and keyword: "temporary". OK? Cheers, Phil 2013-09-09 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-09-09 Phil Muldoon * gdb.python/py-breakpoint.exp: Add temporary breakpoint tests. 2013-09-09 Phil Muldoon * gdb.texinfo (Breakpoints In Python): Document temporary option in breakpoint constructor, and add documentation to the temporary attribute. -- diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 21250fe..627d65e 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -26799,22 +26799,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) @@ -26935,6 +26940,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 87f1fdc..766ae56 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,19 @@ 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 +633,13 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs) return -1; } + if (temporary) + { + 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 +656,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 +1000,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/gdb.python/py-breakpoint.exp b/gdb/testsuite/gdb.python/py-breakpoint.exp index 687182d..8464cec 100644 --- a/gdb/testsuite/gdb.python/py-breakpoint.exp +++ b/gdb/testsuite/gdb.python/py-breakpoint.exp @@ -300,3 +300,28 @@ 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_silent_cmd "python ibp = gdb.Breakpoint(\"$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.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"