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