]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/python/py-infevents.c
beb0598ab94743f680be76defd30897d60ddb49a
[thirdparty/binutils-gdb.git] / gdb / python / py-infevents.c
1 /* Python interface to inferior function events.
2
3 Copyright (C) 2013, 2014 Free Software Foundation, Inc.
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
20 #include "defs.h"
21 #include "py-event.h"
22
23 static PyTypeObject inferior_call_pre_event_object_type
24 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object");
25 static PyTypeObject inferior_call_post_event_object_type
26 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object");
27 static PyTypeObject register_changed_event_object_type
28 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object");
29 static PyTypeObject memory_changed_event_object_type
30 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object");
31
32 /* Construct either a gdb.InferiorCallPreEvent or a
33 gdb.InferiorCallPostEvent. */
34
35 static PyObject *
36 create_inferior_call_event_object (inferior_call_kind flag, ptid_t ptid,
37 CORE_ADDR addr)
38 {
39 int pid;
40 long tid, lwp;
41 PyObject *event;
42 PyObject *ptid_obj = NULL;
43 PyObject *addr_obj = NULL;
44 int failed;
45 struct cleanup *cleanups;
46 struct cleanup *member_cleanups;
47
48 switch (flag)
49 {
50 case INFERIOR_CALL_PRE:
51 event = create_event_object (&inferior_call_pre_event_object_type);
52 break;
53 case INFERIOR_CALL_POST:
54 event = create_event_object (&inferior_call_post_event_object_type);
55 break;
56 default:
57 return NULL;
58 }
59
60 cleanups = make_cleanup_py_decref (event);
61
62 ptid_obj = gdbpy_create_ptid_object (ptid);
63 if (ptid_obj == NULL)
64 goto fail;
65 member_cleanups = make_cleanup_py_decref (ptid_obj);
66
67 failed = evpy_add_attribute (event, "ptid", ptid_obj) < 0;
68 if (failed)
69 goto fail;
70
71 addr_obj = PyLong_FromLongLong (addr);
72 if (addr_obj == NULL)
73 goto fail;
74 make_cleanup_py_decref (addr_obj);
75
76 failed = evpy_add_attribute (event, "address", addr_obj) < 0;
77 if (failed)
78 goto fail;
79
80 do_cleanups (member_cleanups);
81 discard_cleanups (cleanups);
82 return event;
83
84 fail:
85 do_cleanups (cleanups);
86 return NULL;
87 }
88
89 /* Construct a gdb.RegisterChangedEvent containing the affected
90 register number. */
91
92 static PyObject *
93 create_register_changed_event_object (struct frame_info *frame,
94 int regnum)
95 {
96 PyObject *event;
97 PyObject *frame_obj = NULL;
98 PyObject *regnum_obj = NULL;
99 int failed;
100 struct cleanup *cleanups;
101 struct cleanup *member_cleanups;
102
103 event = create_event_object (&register_changed_event_object_type);
104 if (event == NULL)
105 return NULL;
106
107 cleanups = make_cleanup_py_decref (event);
108
109 frame_obj = frame_info_to_frame_object (frame);
110 if (frame_obj == NULL)
111 goto fail;
112 member_cleanups = make_cleanup_py_decref (frame_obj);
113
114 failed = evpy_add_attribute (event, "frame", frame_obj) < 0;
115 if (failed)
116 goto fail;
117
118 regnum_obj = PyLong_FromLongLong (regnum);
119 if (regnum_obj == NULL)
120 goto fail;
121 make_cleanup_py_decref (regnum_obj);
122
123 failed = evpy_add_attribute (event, "regnum", regnum_obj) < 0;
124 if (failed)
125 goto fail;
126
127 do_cleanups (member_cleanups);
128 discard_cleanups (cleanups);
129 return event;
130
131 fail:
132 do_cleanups (cleanups);
133 return NULL;
134 }
135
136 /* Construct a gdb.MemoryChangedEvent describing the extent of the
137 affected memory. */
138
139 static PyObject *
140 create_memory_changed_event_object (CORE_ADDR addr, ssize_t len)
141 {
142 PyObject *event;
143 PyObject *addr_obj = NULL;
144 PyObject *len_obj = NULL;
145 int failed;
146 struct cleanup *cleanups;
147 struct cleanup *member_cleanups;
148
149 event = create_event_object (&memory_changed_event_object_type);
150
151 if (event == NULL)
152 return NULL;
153 cleanups = make_cleanup_py_decref (event);
154
155 addr_obj = PyLong_FromLongLong (addr);
156 if (addr_obj == NULL)
157 goto fail;
158 member_cleanups = make_cleanup_py_decref (addr_obj);
159
160 failed = evpy_add_attribute (event, "address", addr_obj) < 0;
161 if (failed)
162 goto fail;
163
164 len_obj = PyLong_FromLong (len);
165 if (len_obj == NULL)
166 goto fail;
167 make_cleanup_py_decref (len_obj);
168
169 failed = evpy_add_attribute (event, "length", len_obj) < 0;
170 if (failed)
171 goto fail;
172
173 do_cleanups (member_cleanups);
174 discard_cleanups (cleanups);
175 return event;
176
177 fail:
178 do_cleanups (cleanups);
179 return NULL;
180 }
181
182 /* Callback function which notifies observers when an event occurs which
183 calls a function in the inferior.
184 This function will create a new Python inferior-call event object.
185 Return -1 if emit fails. */
186
187 int
188 emit_inferior_call_event (inferior_call_kind flag, ptid_t thread,
189 CORE_ADDR addr)
190 {
191 PyObject *event;
192
193 if (evregpy_no_listeners_p (gdb_py_events.inferior_call))
194 return 0;
195
196 event = create_inferior_call_event_object (flag, thread, addr);
197 if (event != NULL)
198 return evpy_emit_event (event, gdb_py_events.inferior_call);
199 return -1;
200 }
201
202 /* Callback when memory is modified by the user. This function will
203 create a new Python memory changed event object. */
204
205 int
206 emit_memory_changed_event (CORE_ADDR addr, ssize_t len)
207 {
208 PyObject *event;
209
210 if (evregpy_no_listeners_p (gdb_py_events.memory_changed))
211 return 0;
212
213 event = create_memory_changed_event_object (addr, len);
214 if (event != NULL)
215 return evpy_emit_event (event, gdb_py_events.memory_changed);
216 return -1;
217 }
218
219 /* Callback when a register is modified by the user. This function
220 will create a new Python register changed event object. */
221
222 int
223 emit_register_changed_event (struct frame_info* frame, int regnum)
224 {
225 PyObject *event;
226
227 if (evregpy_no_listeners_p (gdb_py_events.register_changed))
228 return 0;
229
230 event = create_register_changed_event_object (frame, regnum);
231 if (event != NULL)
232 return evpy_emit_event (event, gdb_py_events.register_changed);
233 return -1;
234 }
235
236
237 GDBPY_NEW_EVENT_TYPE (inferior_call_pre,
238 "gdb.InferiorCallPreEvent",
239 "InferiorCallPreEvent",
240 "GDB inferior function pre-call event object",
241 event_object_type,
242 static);
243
244 GDBPY_NEW_EVENT_TYPE (inferior_call_post,
245 "gdb.InferiorCallPostEvent",
246 "InferiorCallPostEvent",
247 "GDB inferior function post-call event object",
248 event_object_type,
249 static);
250
251 GDBPY_NEW_EVENT_TYPE (register_changed,
252 "gdb.RegisterChangedEvent",
253 "RegisterChangedEvent",
254 "GDB register change event object",
255 event_object_type,
256 static);
257
258 GDBPY_NEW_EVENT_TYPE (memory_changed,
259 "gdb.MemoryChangedEvent",
260 "MemoryChangedEvent",
261 "GDB memory change event object",
262 event_object_type,
263 static);