xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/python/py-infevents.c (revision d909946ca08dceb44d7d0f22ec9488679695d976)
1 /* Python interface to inferior function events.
2 
3    Copyright (C) 2013-2015 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);
264