]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/python/py-stopevent.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / python / py-stopevent.c
CommitLineData
c17a9e46
HZ
1/* Python interface to inferior stop events.
2
1d506c26 3 Copyright (C) 2009-2024 Free Software Foundation, Inc.
c17a9e46
HZ
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
d071a26b 20#include "defs.h"
c17a9e46 21#include "py-stopevent.h"
e187e7c9 22#include "py-uiout.h"
c17a9e46 23
35c61a1d 24gdbpy_ref<>
e187e7c9 25create_stop_event_object (PyTypeObject *py_type, const gdbpy_ref<> &dict)
c17a9e46 26{
db1337cc 27 gdbpy_ref<> thread = py_get_event_thread (inferior_ptid);
e187e7c9
TT
28 if (thread == nullptr)
29 return nullptr;
30
31 gdbpy_ref<> result = create_thread_event_object (py_type, thread.get ());
32 if (result == nullptr)
33 return nullptr;
34
35 if (evpy_add_attribute (result.get (), "details", dict.get ()) < 0)
36 return nullptr;
37
38 return result;
39}
40
41/* Print BPSTAT to a new Python dictionary. Returns the dictionary,
42 or null if a Python exception occurred. */
43
44static gdbpy_ref<>
45py_print_bpstat (bpstat *bs, enum gdb_signal stop_signal)
46{
47 py_ui_out uiout;
48
49 try
50 {
51 scoped_restore save_uiout = make_scoped_restore (&current_uiout, &uiout);
52
53 thread_info *tp = inferior_thread ();
54 if (tp->thread_fsm () != nullptr && tp->thread_fsm ()->finished_p ())
55 {
56 async_reply_reason reason = tp->thread_fsm ()->async_reply_reason ();
57 uiout.field_string ("reason", async_reason_lookup (reason));
58 }
59
60 if (stop_signal != GDB_SIGNAL_0 && stop_signal != GDB_SIGNAL_TRAP)
61 print_signal_received_reason (&uiout, stop_signal);
62 else
63 {
64 struct target_waitstatus last;
65 get_last_target_status (nullptr, nullptr, &last);
66
67 bpstat_print (bs, last.kind ());
68 }
69 }
70 catch (const gdb_exception &except)
71 {
72 gdbpy_convert_exception (except);
73 return nullptr;
74 }
75
76 return uiout.result ();
c17a9e46
HZ
77}
78
79/* Callback observers when a stop event occurs. This function will create a
80 new Python stop event object. If only a specific thread is stopped the
81 thread object of the event will be set to that thread. Otherwise, if all
82 threads are stopped thread object will be set to None.
83 return 0 if the event was created and emitted successfully otherwise
84 returns -1. */
85
86int
313f3b21 87emit_stop_event (struct bpstat *bs, enum gdb_signal stop_signal)
c17a9e46 88{
7780f186
TT
89 gdbpy_ref<> stop_event_obj;
90 gdbpy_ref<> list;
6839b47f 91 PyObject *first_bp = NULL;
313f3b21 92 struct bpstat *current_bs;
c17a9e46
HZ
93
94 if (evregpy_no_listeners_p (gdb_py_events.stop))
95 return 0;
96
e187e7c9
TT
97 gdbpy_ref<> dict = py_print_bpstat (bs, stop_signal);
98 if (dict == nullptr)
99 return -1;
100
6839b47f
KP
101 /* Add any breakpoint set at this location to the list. */
102 for (current_bs = bs; current_bs != NULL; current_bs = current_bs->next)
c17a9e46 103 {
6839b47f 104 if (current_bs->breakpoint_at
dda83cd7
SM
105 && current_bs->breakpoint_at->py_bp_object)
106 {
107 PyObject *current_py_bp =
108 (PyObject *) current_bs->breakpoint_at->py_bp_object;
109
110 if (list == NULL)
111 {
112 list.reset (PyList_New (0));
113 if (list == NULL)
abf5651e 114 return -1;
dda83cd7 115 }
6839b47f 116
dda83cd7 117 if (PyList_Append (list.get (), current_py_bp))
abf5651e 118 return -1;
6839b47f 119
dda83cd7
SM
120 if (first_bp == NULL)
121 first_bp = current_py_bp;
122 }
6839b47f
KP
123 }
124
125 if (list != NULL)
126 {
e187e7c9
TT
127 stop_event_obj = create_breakpoint_event_object (dict,
128 list.get (),
35c61a1d 129 first_bp);
abf5651e
TT
130 if (stop_event_obj == NULL)
131 return -1;
c17a9e46
HZ
132 }
133
134 /* Check if the signal is "Signal 0" or "Trace/breakpoint trap". */
a493e3e2
PA
135 if (stop_signal != GDB_SIGNAL_0
136 && stop_signal != GDB_SIGNAL_TRAP)
c17a9e46 137 {
e187e7c9 138 stop_event_obj = create_signal_event_object (dict, stop_signal);
abf5651e
TT
139 if (stop_event_obj == NULL)
140 return -1;
c17a9e46
HZ
141 }
142
143 /* If all fails emit an unknown stop event. All event types should
144 be known and this should eventually be unused. */
abf5651e 145 if (stop_event_obj == NULL)
c17a9e46 146 {
e187e7c9
TT
147 stop_event_obj = create_stop_event_object (&stop_event_object_type,
148 dict);
abf5651e
TT
149 if (stop_event_obj == NULL)
150 return -1;
c17a9e46
HZ
151 }
152
abf5651e 153 return evpy_emit_event (stop_event_obj.get (), gdb_py_events.stop);
c17a9e46 154}