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 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 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 (®ister_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 243 GDBPY_NEW_EVENT_TYPE (inferior_call_post, 244 "gdb.InferiorCallPostEvent", 245 "InferiorCallPostEvent", 246 "GDB inferior function post-call event object", 247 event_object_type); 248 249 GDBPY_NEW_EVENT_TYPE (register_changed, 250 "gdb.RegisterChangedEvent", 251 "RegisterChangedEvent", 252 "GDB register change event object", 253 event_object_type); 254 255 GDBPY_NEW_EVENT_TYPE (memory_changed, 256 "gdb.MemoryChangedEvent", 257 "MemoryChangedEvent", 258 "GDB memory change event object", 259 event_object_type); 260