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