public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Tom Tromey <tromey@adacore.com>
To: gdb-patches@sourceware.org
Subject: [PATCH 2/3] Emit stop reason details in Python stop events
Date: Tue, 14 Nov 2023 11:44:04 -0700	[thread overview]
Message-ID: <20231114-py-stop-reason-v1-2-4ff440c956a9@adacore.com> (raw)
In-Reply-To: <20231114-py-stop-reason-v1-0-4ff440c956a9@adacore.com>

This changes Python stop events to carry a "details" dictionary, that
holds any relevant information about the stop.  The details are
constructed using more or less the same procedure as is done for MI.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=13587
---
 gdb/NEWS                    |  4 +++
 gdb/doc/python.texi         | 11 ++++++++
 gdb/python/py-bpevent.c     |  5 ++--
 gdb/python/py-mi.c          |  2 +-
 gdb/python/py-signalevent.c |  5 ++--
 gdb/python/py-stopevent.c   | 65 +++++++++++++++++++++++++++++++++++++++++----
 gdb/python/py-stopevent.h   |  9 ++++---
 gdb/python/py-uiout.h       |  4 +--
 8 files changed, 90 insertions(+), 15 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 93fbcf1c13e..12387ad9f4a 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -50,6 +50,10 @@ disable missing-debug-handler LOCUS HANDLER
      sub-classed to create handlers for objfiles with missing debug
      information.
 
+  ** Stop events now have a "details" attribute that holds a
+     dictionary that carries the same information as an MI "*stopped"
+     event.
+
 * New commands
 
 maintenance info linux-lwps
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index b65991bbad0..ab2abcfc5b1 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -3750,6 +3750,17 @@ registry extend @code{gdb.StopEvent}.  As a child of
 thread when @value{GDBN} is running in non-stop mode.  Refer to
 @code{gdb.ThreadEvent} above for more details.
 
+@code{gdb.StopEvent} has the following additional attributes:
+
+@defvar StopEvent.details
+A dictionary holding any details relevant to the stop.  The exact keys
+and values depend on the type of stop, but are identical to the
+corresponding MI output (@pxref{GDB/MI Async Records}).
+
+A dictionary was used for this (rather than adding attributes directly
+to the event object) so that the MI keys could be used unchanged.
+@end defvar
+
 Emits @code{gdb.SignalEvent}, which extends @code{gdb.StopEvent}.
 
 This event indicates that the inferior or one of its threads has
diff --git a/gdb/python/py-bpevent.c b/gdb/python/py-bpevent.c
index 00fb625794b..b640ec9ddd9 100644
--- a/gdb/python/py-bpevent.c
+++ b/gdb/python/py-bpevent.c
@@ -24,10 +24,11 @@
    references to BREAKPOINT_LIST and FIRST_BP.  */
 
 gdbpy_ref<>
-create_breakpoint_event_object (PyObject *breakpoint_list, PyObject *first_bp)
+create_breakpoint_event_object (const gdbpy_ref<> &dict,
+				PyObject *breakpoint_list, PyObject *first_bp)
 {
   gdbpy_ref<> breakpoint_event_obj
-    = create_stop_event_object (&breakpoint_event_object_type);
+    = create_stop_event_object (&breakpoint_event_object_type, dict);
 
   if (breakpoint_event_obj == NULL)
     return NULL;
diff --git a/gdb/python/py-mi.c b/gdb/python/py-mi.c
index 2b265ad80d6..04873e86dd3 100644
--- a/gdb/python/py-mi.c
+++ b/gdb/python/py-mi.c
@@ -173,7 +173,7 @@ gdbpy_execute_mi_command (PyObject *self, PyObject *args, PyObject *kw)
       return nullptr;
     }
 
-  return uiout.result ();
+  return uiout.result ().release ();
 }
 
 /* Convert KEY_OBJ into a string that can be used as a field name in MI
diff --git a/gdb/python/py-signalevent.c b/gdb/python/py-signalevent.c
index 93d06706542..edbd9b0a7ec 100644
--- a/gdb/python/py-signalevent.c
+++ b/gdb/python/py-signalevent.c
@@ -21,10 +21,11 @@
 #include "py-stopevent.h"
 
 gdbpy_ref<>
-create_signal_event_object (enum gdb_signal stop_signal)
+create_signal_event_object (const gdbpy_ref<> &dict,
+			    enum gdb_signal stop_signal)
 {
   gdbpy_ref<> signal_event_obj
-    = create_stop_event_object (&signal_event_object_type);
+    = create_stop_event_object (&signal_event_object_type, dict);
 
   if (signal_event_obj == NULL)
     return NULL;
diff --git a/gdb/python/py-stopevent.c b/gdb/python/py-stopevent.c
index 0aa9d5381f8..f395e8c042e 100644
--- a/gdb/python/py-stopevent.c
+++ b/gdb/python/py-stopevent.c
@@ -19,12 +19,61 @@
 
 #include "defs.h"
 #include "py-stopevent.h"
+#include "py-uiout.h"
 
 gdbpy_ref<>
-create_stop_event_object (PyTypeObject *py_type)
+create_stop_event_object (PyTypeObject *py_type, const gdbpy_ref<> &dict)
 {
   gdbpy_ref<> thread = py_get_event_thread (inferior_ptid);
-  return create_thread_event_object (py_type, thread.get ());
+  if (thread == nullptr)
+    return nullptr;
+
+  gdbpy_ref<> result = create_thread_event_object (py_type, thread.get ());
+  if (result == nullptr)
+    return nullptr;
+
+  if (evpy_add_attribute (result.get (), "details", dict.get ()) < 0)
+    return nullptr;
+
+  return result;
+}
+
+/* Print BPSTAT to a new Python dictionary.  Returns the dictionary,
+   or null if a Python exception occurred.  */
+
+static gdbpy_ref<>
+py_print_bpstat (bpstat *bs, enum gdb_signal stop_signal)
+{
+  py_ui_out uiout;
+
+  try
+    {
+      scoped_restore save_uiout = make_scoped_restore (&current_uiout, &uiout);
+
+      thread_info *tp = inferior_thread ();
+      if (tp->thread_fsm () != nullptr && tp->thread_fsm ()->finished_p ())
+	{
+	  async_reply_reason reason = tp->thread_fsm ()->async_reply_reason ();
+	  uiout.field_string ("reason", async_reason_lookup (reason));
+	}
+
+      if (stop_signal != GDB_SIGNAL_0 && stop_signal != GDB_SIGNAL_TRAP)
+	print_signal_received_reason (&uiout, stop_signal);
+      else
+	{
+	  struct target_waitstatus last;
+	  get_last_target_status (nullptr, nullptr, &last);
+
+	  bpstat_print (bs, last.kind ());
+	}
+    }
+  catch (const gdb_exception &except)
+    {
+      gdbpy_convert_exception (except);
+      return nullptr;
+    }
+
+  return uiout.result ();
 }
 
 /* Callback observers when a stop event occurs.  This function will create a
@@ -45,6 +94,10 @@ emit_stop_event (struct bpstat *bs, enum gdb_signal stop_signal)
   if (evregpy_no_listeners_p (gdb_py_events.stop))
     return 0;
 
+  gdbpy_ref<> dict = py_print_bpstat (bs, stop_signal);
+  if (dict == nullptr)
+    return -1;
+
   /* Add any breakpoint set at this location to the list.  */
   for (current_bs = bs; current_bs != NULL; current_bs = current_bs->next)
     {
@@ -71,7 +124,8 @@ emit_stop_event (struct bpstat *bs, enum gdb_signal stop_signal)
 
   if (list != NULL)
     {
-      stop_event_obj = create_breakpoint_event_object (list.get (),
+      stop_event_obj = create_breakpoint_event_object (dict,
+						       list.get (),
 						       first_bp);
       if (stop_event_obj == NULL)
 	return -1;
@@ -81,7 +135,7 @@ emit_stop_event (struct bpstat *bs, enum gdb_signal stop_signal)
   if (stop_signal != GDB_SIGNAL_0
       && stop_signal != GDB_SIGNAL_TRAP)
     {
-      stop_event_obj = create_signal_event_object (stop_signal);
+      stop_event_obj = create_signal_event_object (dict, stop_signal);
       if (stop_event_obj == NULL)
 	return -1;
     }
@@ -90,7 +144,8 @@ emit_stop_event (struct bpstat *bs, enum gdb_signal stop_signal)
      be known and this should eventually be unused.  */
   if (stop_event_obj == NULL)
     {
-      stop_event_obj = create_stop_event_object (&stop_event_object_type);
+      stop_event_obj = create_stop_event_object (&stop_event_object_type,
+						 dict);
       if (stop_event_obj == NULL)
 	return -1;
     }
diff --git a/gdb/python/py-stopevent.h b/gdb/python/py-stopevent.h
index 649112f0488..92282c9c413 100644
--- a/gdb/python/py-stopevent.h
+++ b/gdb/python/py-stopevent.h
@@ -22,14 +22,17 @@
 
 #include "py-event.h"
 
-extern gdbpy_ref<> create_stop_event_object (PyTypeObject *py_type);
+extern gdbpy_ref<> create_stop_event_object (PyTypeObject *py_type,
+					     const gdbpy_ref<> &dict);
 
 extern int emit_stop_event (struct bpstat *bs,
 			    enum gdb_signal stop_signal);
 
-extern gdbpy_ref<> create_breakpoint_event_object (PyObject *breakpoint_list,
+extern gdbpy_ref<> create_breakpoint_event_object (const gdbpy_ref<> &dict,
+						   PyObject *breakpoint_list,
 						   PyObject *first_bp);
 
-extern gdbpy_ref<> create_signal_event_object (enum gdb_signal stop_signal);
+extern gdbpy_ref<> create_signal_event_object (const gdbpy_ref<> &dict,
+					       enum gdb_signal stop_signal);
 
 #endif /* PYTHON_PY_STOPEVENT_H */
diff --git a/gdb/python/py-uiout.h b/gdb/python/py-uiout.h
index e9abf8ee5be..6e43b425968 100644
--- a/gdb/python/py-uiout.h
+++ b/gdb/python/py-uiout.h
@@ -46,14 +46,14 @@ class py_ui_out : public ui_out
   /* Return the Python object that was created.  If a Python error
      occurred during the processing, set the Python error and return
      nullptr.  */
-  PyObject *result ()
+  gdbpy_ref<> result ()
   {
     if (m_error.has_value ())
       {
 	m_error->restore ();
 	return nullptr;
       }
-    return current ().obj.release ();
+    return std::move (current ().obj);
   }
 
 protected:

-- 
2.41.0


  parent reply	other threads:[~2023-11-14 18:44 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-14 18:44 [PATCH 0/3] Simplify DAP stop reason emission Tom Tromey
2023-11-14 18:44 ` [PATCH 1/3] Move py_ui_out to a new header Tom Tromey
2023-11-14 18:44 ` Tom Tromey [this message]
2023-11-14 19:12   ` [PATCH 2/3] Emit stop reason details in Python stop events Eli Zaretskii
2023-11-14 18:44 ` [PATCH 3/3] Simplify DAP stop-reason code Tom Tromey
2023-12-11 18:42 ` [PATCH 0/3] Simplify DAP stop reason emission Tom Tromey

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231114-py-stop-reason-v1-2-4ff440c956a9@adacore.com \
    --to=tromey@adacore.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).