gdb/python: allow for catchpoint type breakpoints in python
authorAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 5 May 2021 14:26:28 +0000 (15:26 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Fri, 25 Jun 2021 17:22:07 +0000 (18:22 +0100)
This commit adds initial support for catchpoints to the python
breakpoint API.

This commit adds a BP_CATCHPOINT constant which corresponds to
GDB's internal bp_catchpoint.  The new constant is documented in the
manual.

The user can't create breakpoints with type BP_CATCHPOINT after this
commit, but breakpoints that already exist, obtained with the
`gdb.breakpoints` function, can now have this type.  Additionally,
when a stop event is reported for hitting a catchpoint, GDB will now
report a BreakpointEvent with the attached breakpoint being of type
BP_CATCHPOINT - previously GDB would report a generic StopEvent in
this situation.

gdb/ChangeLog:

* NEWS: Mention Python BP_CATCHPOINT feature.
* python/py-breakpoint.c (pybp_codes): Add bp_catchpoint support.
(bppy_init): Likewise.
(gdbpy_breakpoint_created): Likewise.

gdb/doc/ChangeLog:

* python.texinfo (Breakpoints In Python): Add BP_CATCHPOINT
description.

gdb/testsuite/ChangeLog:

* gdb.python/py-breakpoint.c (do_throw): New function.
(main): Call do_throw.
* gdb.python/py-breakpoint.exp (test_catchpoints): New proc.

gdb/ChangeLog
gdb/NEWS
gdb/doc/ChangeLog
gdb/doc/python.texi
gdb/python/py-breakpoint.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.python/py-breakpoint.c
gdb/testsuite/gdb.python/py-breakpoint.exp

index b610f75d22646543bf9c586e8da1cdb319267adf..5045e713a64f65889eeb8eb9fd88bb1fbed141e3 100644 (file)
@@ -1,3 +1,10 @@
+2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * NEWS: Mention Python BP_CATCHPOINT feature.
+       * python/py-breakpoint.c (pybp_codes): Add bp_catchpoint support.
+       (bppy_init): Likewise.
+       (gdbpy_breakpoint_created): Likewise.
+
 2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * guile/scm-breakpoint.c (bpscm_type_to_string): Handle
index 151c4f113fbc3db69757c7ccd0db2b4a240b2205..aae3b49b40821f412326cd786670c2a34cc61c8c 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -231,6 +231,10 @@ QMemTags
   ** New method gdb.PendingFrame.level() which returns the stack level
      of the frame object.
 
+  ** When hitting a catchpoint, the Python API will now emit a
+     gdb.BreakpointEvent rather than a gdb.StopEvent.  The
+     gdb.Breakpoint attached to the event will have type BP_CATCHPOINT.
+
 *** Changes in GDB 10
 
 * There are new feature names for ARC targets: "org.gnu.gdb.arc.core"
index 1f197838a59c9399d2d864f938961f7050eedd57..fc16fc5f2a7d378c3447dc8110f5804309d2adea 100644 (file)
@@ -1,3 +1,8 @@
+2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * python.texinfo (Breakpoints In Python): Add BP_CATCHPOINT
+       description.
+
 2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * guile.texinfo (Breakpoints In Guile): Add BP_CATCHPOINT
index 01a2e8b7974006a35f5aa434ef58d07ffaa1ddcd..f4865b3d6a6bb68a4e8c86c5209a44fe3ef7bb4a 100644 (file)
@@ -5517,6 +5517,13 @@ Hardware assisted read watchpoint.
 @vindex BP_ACCESS_WATCHPOINT
 @item gdb.BP_ACCESS_WATCHPOINT
 Hardware assisted access watchpoint.
+
+@vindex BP_CATCHPOINT
+@item gdb.BP_CATCHPOINT
+Catchpoint.  Currently, this type can't be used when creating
+@code{gdb.Breakpoint} objects, but will be present in
+@code{gdb.Breakpoint} objects reported from
+@code{gdb.BreakpointEvent}s (@pxref{Events In Python}).
 @end vtable
 
 The available watchpoint types are represented by constants defined in the
index a2ce4cdd06fd7ab3cf42a3bd6d2b00e907b8d127..edff03282a1ec09d360231851de2ed194d2a4ca0 100644 (file)
@@ -86,6 +86,7 @@ static struct pybp_code pybp_codes[] =
   { "BP_HARDWARE_WATCHPOINT", bp_hardware_watchpoint},
   { "BP_READ_WATCHPOINT", bp_read_watchpoint},
   { "BP_ACCESS_WATCHPOINT", bp_access_watchpoint},
+  { "BP_CATCHPOINT", bp_catchpoint},
   {NULL} /* Sentinel.  */
 };
 
@@ -883,6 +884,8 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
              error(_("Cannot understand watchpoint access type."));
            break;
          }
+       case bp_catchpoint:
+         error (_("BP_CATCHPOINT not supported"));
        default:
          error(_("Do not understand breakpoint type to set."));
        }
@@ -1038,7 +1041,8 @@ gdbpy_breakpoint_created (struct breakpoint *bp)
       && bp->type != bp_watchpoint
       && bp->type != bp_hardware_watchpoint
       && bp->type != bp_read_watchpoint
-      && bp->type != bp_access_watchpoint)
+      && bp->type != bp_access_watchpoint
+      && bp->type != bp_catchpoint)
     {
       pybp_debug_printf ("is not a breakpoint or watchpoint");
       return;
index 30db2611d1e6747885eaf53886425bfce1ba04b3..567c1342870ac8d328af86deb626292418fb2cda 100644 (file)
@@ -1,3 +1,9 @@
+2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.python/py-breakpoint.c (do_throw): New function.
+       (main): Call do_throw.
+       * gdb.python/py-breakpoint.exp (test_catchpoints): New proc.
+
 2021-06-25  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * gdb.guile/scm-breakpoint.exp (test_catchpoints): New proc.
index 830e4c29fae08f9f85f65088ebf691e583fae99e..dca668d6c225dcc0a295dbcd83b31669206e7dff 100644 (file)
@@ -39,6 +39,11 @@ int add (int i)
   return i + i;  /* Break at function add.  */
 }
 
+void
+do_throw ()
+{
+  throw 123;
+}
 
 int main (int argc, char *argv[])
 {
@@ -46,6 +51,15 @@ int main (int argc, char *argv[])
   int bar = 42;
   int i;
 
+  try
+    {
+      do_throw ();
+    }
+  catch (...)
+    {
+      /* Nothing.  */
+    }
+
   for (i = 0; i < 10; i++)
     {
       result += multiply (foo);  /* Break at multiply. */
index 64a70abb1264f187f46738dd116d8e0366ced740..d8fb85b784c119145a65cda7ae83068332dfca7f 100644 (file)
@@ -737,11 +737,71 @@ proc_with_prefix test_bkpt_probe {} {
        "-probe in spec string"
 }
 
+proc_with_prefix test_catchpoints {} {
+    global srcfile testfile
+    global gdb_prompt decimal
+
+    # Start with a fresh gdb.
+    clean_restart ${testfile}
+
+    if ![runto_main] then {
+       fail "cannot run to main."
+       return 0
+    }
+
+    # Try to create a catchpoint, currently this isn't supported via
+    # the python api.
+    gdb_test "python gdb.Breakpoint (\"syscall\", type=gdb.BP_CATCHPOINT)" \
+       [multi_line \
+            "gdb.error: BP_CATCHPOINT not supported" \
+            "Error while executing Python code\\."] \
+       "create a catchpoint via the api"
+
+    # Setup a catchpoint.
+    set num "XXX"
+    gdb_test_multiple "catch throw" "" {
+       -re "The feature \'catch throw\' is not supported.*\r\n$gdb_prompt $" {
+           unsupported "catch syscall isn't supported"
+           return -1
+       }
+       -re "Catchpoint ($decimal) \\(throw\\)\r\n$gdb_prompt $" {
+           set num $expect_out(1,string)
+           pass $gdb_test_name
+       }
+    }
+
+    # Look for the catchpoint in the breakpoint list.
+    gdb_test_multiline "scan breakpoint list for BP_CATCHPOINT" \
+       "python" "" \
+       "def scan_bp_list ():" "" \
+       "  for b in gdb.breakpoints():" "" \
+       "    if b.type == gdb.BP_CATCHPOINT:" "" \
+       "      print(\"breakpoint #%d, type BP_CATCHPOINT\" % b.number)" "" \
+       "end" ""
+    gdb_test "python scan_bp_list ()" \
+       "breakpoint #${num}, type BP_CATCHPOINT" \
+       "scan breakpoint for BP_CATCHPOINT"
+
+    # Arrange to print something when GDB stops, then continue to the
+    # catchpoint and check we get the expected event.
+    gdb_test_multiline "setup stop event handler" \
+       "python" "" \
+       "def stop_handler (event):" "" \
+       "  if (isinstance (event, gdb.BreakpointEvent)" "" \
+       "      and isinstance (event.breakpoint, gdb.Breakpoint)" "" \
+       "      and event.breakpoint.type == gdb.BP_CATCHPOINT):" "" \
+       "    print (\"Stopped at catchpoint event: %d\" % event.breakpoint.number)" "" \
+       "end" "" \
+       "python gdb.events.stop.connect (stop_handler)" ""
+    gdb_test "continue" "Stopped at catchpoint event: ${num}"
+}
+
 test_bkpt_basic
 test_bkpt_deletion
 test_bkpt_cond_and_cmds
 test_bkpt_invisible
 test_hardware_breakpoints
+test_catchpoints
 test_watchpoints
 test_bkpt_internal
 test_bkpt_eval_funcs