1 /* Python interface to inferior function events. 2 3 Copyright (C) 2013-2017 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 #include "py-ref.h" 23 24 extern PyTypeObject inferior_call_pre_event_object_type 25 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object"); 26 extern PyTypeObject inferior_call_post_event_object_type 27 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object"); 28 extern PyTypeObject register_changed_event_object_type 29 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object"); 30 extern PyTypeObject memory_changed_event_object_type 31 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("event_object"); 32 33 /* Construct either a gdb.InferiorCallPreEvent or a 34 gdb.InferiorCallPostEvent. */ 35 36 static PyObject * 37 create_inferior_call_event_object (inferior_call_kind flag, ptid_t ptid, 38 CORE_ADDR addr) 39 { 40 gdbpy_ref<> event; 41 int failed; 42 43 switch (flag) 44 { 45 case INFERIOR_CALL_PRE: 46 event.reset (create_event_object (&inferior_call_pre_event_object_type)); 47 break; 48 case INFERIOR_CALL_POST: 49 event.reset (create_event_object (&inferior_call_post_event_object_type)); 50 break; 51 default: 52 gdb_assert_not_reached ("invalid inferior_call_kind"); 53 } 54 55 gdbpy_ref<> ptid_obj (gdbpy_create_ptid_object (ptid)); 56 if (ptid_obj == NULL) 57 return NULL; 58 59 if (evpy_add_attribute (event.get (), "ptid", ptid_obj.get ()) < 0) 60 return NULL; 61 62 gdbpy_ref<> addr_obj (PyLong_FromLongLong (addr)); 63 if (addr_obj == NULL) 64 return NULL; 65 66 if (evpy_add_attribute (event.get (), "address", addr_obj.get ()) < 0) 67 return NULL; 68 69 return event.release (); 70 } 71 72 /* Construct a gdb.RegisterChangedEvent containing the affected 73 register number. */ 74 75 static PyObject * 76 create_register_changed_event_object (struct frame_info *frame, 77 int regnum) 78 { 79 gdbpy_ref<> event (create_event_object (®ister_changed_event_object_type)); 80 if (event == NULL) 81 return NULL; 82 83 gdbpy_ref<> frame_obj (frame_info_to_frame_object (frame)); 84 if (frame_obj == NULL) 85 return NULL; 86 87 if (evpy_add_attribute (event.get (), "frame", frame_obj.get ()) < 0) 88 return NULL; 89 90 gdbpy_ref<> regnum_obj (PyLong_FromLongLong (regnum)); 91 if (regnum_obj == NULL) 92 return NULL; 93 94 if (evpy_add_attribute (event.get (), "regnum", regnum_obj.get ()) < 0) 95 return NULL; 96 97 return event.release (); 98 } 99 100 /* Construct a gdb.MemoryChangedEvent describing the extent of the 101 affected memory. */ 102 103 static PyObject * 104 create_memory_changed_event_object (CORE_ADDR addr, ssize_t len) 105 { 106 gdbpy_ref<> event (create_event_object (&memory_changed_event_object_type)); 107 108 if (event == NULL) 109 return NULL; 110 111 gdbpy_ref<> addr_obj (PyLong_FromLongLong (addr)); 112 if (addr_obj == NULL) 113 return NULL; 114 115 if (evpy_add_attribute (event.get (), "address", addr_obj.get ()) < 0) 116 return NULL; 117 118 gdbpy_ref<> len_obj (PyLong_FromLong (len)); 119 if (len_obj == NULL) 120 return NULL; 121 122 if (evpy_add_attribute (event.get (), "length", len_obj.get ()) < 0) 123 return NULL; 124 125 return event.release (); 126 } 127 128 /* Callback function which notifies observers when an event occurs which 129 calls a function in the inferior. 130 This function will create a new Python inferior-call event object. 131 Return -1 if emit fails. */ 132 133 int 134 emit_inferior_call_event (inferior_call_kind flag, ptid_t thread, 135 CORE_ADDR addr) 136 { 137 if (evregpy_no_listeners_p (gdb_py_events.inferior_call)) 138 return 0; 139 140 gdbpy_ref<> event (create_inferior_call_event_object (flag, thread, addr)); 141 if (event != NULL) 142 return evpy_emit_event (event.get (), gdb_py_events.inferior_call); 143 return -1; 144 } 145 146 /* Callback when memory is modified by the user. This function will 147 create a new Python memory changed event object. */ 148 149 int 150 emit_memory_changed_event (CORE_ADDR addr, ssize_t len) 151 { 152 if (evregpy_no_listeners_p (gdb_py_events.memory_changed)) 153 return 0; 154 155 gdbpy_ref<> event (create_memory_changed_event_object (addr, len)); 156 if (event != NULL) 157 return evpy_emit_event (event.get (), gdb_py_events.memory_changed); 158 return -1; 159 } 160 161 /* Callback when a register is modified by the user. This function 162 will create a new Python register changed event object. */ 163 164 int 165 emit_register_changed_event (struct frame_info* frame, int regnum) 166 { 167 if (evregpy_no_listeners_p (gdb_py_events.register_changed)) 168 return 0; 169 170 gdbpy_ref<> event (create_register_changed_event_object (frame, regnum)); 171 if (event != NULL) 172 return evpy_emit_event (event.get (), gdb_py_events.register_changed); 173 return -1; 174 } 175 176 177 GDBPY_NEW_EVENT_TYPE (inferior_call_pre, 178 "gdb.InferiorCallPreEvent", 179 "InferiorCallPreEvent", 180 "GDB inferior function pre-call event object", 181 event_object_type); 182 183 GDBPY_NEW_EVENT_TYPE (inferior_call_post, 184 "gdb.InferiorCallPostEvent", 185 "InferiorCallPostEvent", 186 "GDB inferior function post-call event object", 187 event_object_type); 188 189 GDBPY_NEW_EVENT_TYPE (register_changed, 190 "gdb.RegisterChangedEvent", 191 "RegisterChangedEvent", 192 "GDB register change event object", 193 event_object_type); 194 195 GDBPY_NEW_EVENT_TYPE (memory_changed, 196 "gdb.MemoryChangedEvent", 197 "MemoryChangedEvent", 198 "GDB memory change event object", 199 event_object_type); 200