aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2023-11-03 13:23:41 -0600
committerTom Tromey <tromey@adacore.com>2023-12-11 10:51:32 -0700
commite187e7c9696fbf66cf25d5fb8113bc3bc06b9e8b (patch)
treedb8bf8c6a14650905a6831cb35de0fea3e504510
parentf2e2493b1f892bd377b772307c5ad37bdcda4e12 (diff)
downloadgdb-e187e7c9696fbf66cf25d5fb8113bc3bc06b9e8b.zip
gdb-e187e7c9696fbf66cf25d5fb8113bc3bc06b9e8b.tar.gz
gdb-e187e7c9696fbf66cf25d5fb8113bc3bc06b9e8b.tar.bz2
Emit stop reason details in Python stop events
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 Reviewed-By: Eli Zaretskii <eliz@gnu.org>
-rw-r--r--gdb/NEWS4
-rw-r--r--gdb/doc/python.texi11
-rw-r--r--gdb/python/py-bpevent.c5
-rw-r--r--gdb/python/py-mi.c2
-rw-r--r--gdb/python/py-signalevent.c5
-rw-r--r--gdb/python/py-stopevent.c65
-rw-r--r--gdb/python/py-stopevent.h9
-rw-r--r--gdb/python/py-uiout.h4
8 files changed, 90 insertions, 15 deletions
diff --git a/gdb/NEWS b/gdb/NEWS
index aaf8faa..7ffbcbd 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -75,6 +75,10 @@ show remote thread-options-packet
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.
+
* Debugger Adapter Protocol changes
** GDB now emits the "process" event.
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 3a35c5c..39137aa 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 00fb625..b640ec9 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 8b26568..36a55e4 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 93d0670..edbd9b0 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 0aa9d53..f395e8c 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 649112f..92282c9 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 d5a50db..9c9617e 100644
--- a/gdb/python/py-uiout.h
+++ b/gdb/python/py-uiout.h
@@ -46,14 +46,14 @@ public:
/* 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: