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 (®ister_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