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