1 /* Python interface to inferiors.
2
3 Copyright (C) 2009-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 "python-internal.h"
21 #include "process-stratum-target.h"
22 #include "inferior.h"
23 #include "observable.h"
24 #include "target-connection.h"
25 #include "py-events.h"
26 #include "py-event.h"
27 #include "arch-utils.h"
28 #include "remote.h"
29 #include "charset.h"
30
31 #include <map>
32
33 /* The Python object that represents a connection. */
34
35 struct connection_object
36 {
37 PyObject_HEAD
38
39 /* The process target that represents this connection. When a
40 connection_object is created this field will always point at a valid
41 target. Later, if GDB stops using this target (the target is popped
42 from all target stacks) then this field is set to nullptr, which
43 indicates that this Python object is now in the invalid state (see
44 the is_valid() method below). */
45 struct process_stratum_target *target;
46 };
47
48 extern PyTypeObject connection_object_type
49 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("connection_object");
50
51 extern PyTypeObject remote_connection_object_type
52 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("remote_connection_object");
53
54 /* Require that CONNECTION be valid. */
55 #define CONNPY_REQUIRE_VALID(connection) \
56 do { \
57 if (connection->target == nullptr) \
58 { \
59 PyErr_SetString (PyExc_RuntimeError, \
60 _("Connection no longer exists.")); \
61 return nullptr; \
62 } \
63 } while (0)
64
65 /* A map between process_stratum targets and the Python object representing
66 them. We actually hold a gdbpy_ref around the Python object so that
67 reference counts are handled correctly when entries are deleted. */
68 static std::map<process_stratum_target *,
69 gdbpy_ref<connection_object>> all_connection_objects;
70
71 /* Return a reference to a gdb.TargetConnection object for TARGET. If
72 TARGET is nullptr then a reference to None is returned.
73
74 Previously created gdb.TargetConnection objects are cached, and
75 additional references to the same connection object can be returned with
76 later calls to this function. */
77
78 gdbpy_ref<>
target_to_connection_object(process_stratum_target * target)79 target_to_connection_object (process_stratum_target *target)
80 {
81 if (target == nullptr)
82 return gdbpy_ref<>::new_reference (Py_None);
83
84 gdbpy_ref <connection_object> conn_obj;
85 auto conn_obj_iter = all_connection_objects.find (target);
86 if (conn_obj_iter == all_connection_objects.end ())
87 {
88 PyTypeObject *type;
89
90 if (is_remote_target (target))
91 type = &remote_connection_object_type;
92 else
93 type = &connection_object_type;
94
95 conn_obj.reset (PyObject_New (connection_object, type));
96 if (conn_obj == nullptr)
97 return nullptr;
98 conn_obj->target = target;
99 all_connection_objects.emplace (target, conn_obj);
100 }
101 else
102 conn_obj = conn_obj_iter->second;
103
104 gdb_assert (conn_obj != nullptr);
105
106 /* Repackage the result as a PyObject reference. */
107 return gdbpy_ref<> ((PyObject *) conn_obj.release ());
108 }
109
110 /* Return a list of gdb.TargetConnection objects, one for each currently
111 active connection. The returned list is in no particular order. */
112
113 PyObject *
gdbpy_connections(PyObject * self,PyObject * args)114 gdbpy_connections (PyObject *self, PyObject *args)
115 {
116 gdbpy_ref<> list (PyList_New (0));
117 if (list == nullptr)
118 return nullptr;
119
120 for (process_stratum_target *target : all_non_exited_process_targets ())
121 {
122 gdb_assert (target != nullptr);
123
124 gdbpy_ref<> conn = target_to_connection_object (target);
125 if (conn == nullptr)
126 return nullptr;
127 gdb_assert (conn.get () != Py_None);
128
129 if (PyList_Append (list.get (), conn.get ()) < 0)
130 return nullptr;
131 }
132
133 return list.release ();
134 }
135
136 /* Emit a connection event for TARGET to REGISTRY. Return 0 on success, or
137 a negative value on error. */
138
139 static int
emit_connection_event(process_stratum_target * target,eventregistry_object * registry)140 emit_connection_event (process_stratum_target *target,
141 eventregistry_object *registry)
142 {
143 gdbpy_ref<> event_obj
144 = create_event_object (&connection_event_object_type);
145 if (event_obj == nullptr)
146 return -1;
147
148 gdbpy_ref<> conn = target_to_connection_object (target);
149 if (evpy_add_attribute (event_obj.get (), "connection", conn.get ()) < 0)
150 return -1;
151
152 return evpy_emit_event (event_obj.get (), registry);
153 }
154
155 /* Callback for the connection_removed observer. */
156
157 static void
connpy_connection_removed(process_stratum_target * target)158 connpy_connection_removed (process_stratum_target *target)
159 {
160 if (!gdb_python_initialized)
161 return;
162
163 gdbpy_enter enter_py;
164
165 if (!evregpy_no_listeners_p (gdb_py_events.connection_removed))
166 if (emit_connection_event (target, gdb_py_events.connection_removed) < 0)
167 gdbpy_print_stack ();
168
169 auto conn_obj_iter = all_connection_objects.find (target);
170 if (conn_obj_iter != all_connection_objects.end ())
171 {
172 gdbpy_ref <connection_object> conn_obj = conn_obj_iter->second;
173 conn_obj->target = nullptr;
174 all_connection_objects.erase (target);
175 }
176 }
177
178 /* Called when a gdb.TargetConnection object is deallocated. */
179
180 static void
connpy_connection_dealloc(PyObject * obj)181 connpy_connection_dealloc (PyObject *obj)
182 {
183 connection_object *conn_obj = (connection_object *) obj;
184
185 /* As the all_connection_objects map holds a reference to each connection
186 object we can only enter the dealloc function when the reference in
187 all_connection_objects has been erased.
188
189 As we always set the target pointer back to nullptr before we erase
190 items from all_connection_objects then, when we get here, the target
191 pointer must be nullptr. */
192 gdb_assert (conn_obj->target == nullptr);
193
194 Py_TYPE (obj)->tp_free (obj);
195 }
196
197 /* Implement repr() for gdb.TargetConnection. */
198
199 static PyObject *
connpy_repr(PyObject * obj)200 connpy_repr (PyObject *obj)
201 {
202 connection_object *self = (connection_object *) obj;
203 process_stratum_target *target = self->target;
204
205 if (target == nullptr)
206 return gdb_py_invalid_object_repr (obj);
207
208 return PyUnicode_FromFormat ("<%s num=%d, what=\"%s\">",
209 Py_TYPE (obj)->tp_name,
210 target->connection_number,
211 make_target_connection_string (target).c_str ());
212 }
213
214 /* Implementation of gdb.TargetConnection.is_valid() -> Boolean. Returns
215 True if this connection object is still associated with a
216 process_stratum_target, otherwise, returns False. */
217
218 static PyObject *
connpy_is_valid(PyObject * self,PyObject * args)219 connpy_is_valid (PyObject *self, PyObject *args)
220 {
221 connection_object *conn = (connection_object *) self;
222
223 if (conn->target == nullptr)
224 Py_RETURN_FALSE;
225
226 Py_RETURN_TRUE;
227 }
228
229 /* Return the id number of this connection. */
230
231 static PyObject *
connpy_get_connection_num(PyObject * self,void * closure)232 connpy_get_connection_num (PyObject *self, void *closure)
233 {
234 connection_object *conn = (connection_object *) self;
235
236 CONNPY_REQUIRE_VALID (conn);
237
238 auto num = conn->target->connection_number;
239 return gdb_py_object_from_longest (num).release ();
240 }
241
242 /* Return a string that gives the short name for this connection type. */
243
244 static PyObject *
connpy_get_connection_type(PyObject * self,void * closure)245 connpy_get_connection_type (PyObject *self, void *closure)
246 {
247 connection_object *conn = (connection_object *) self;
248
249 CONNPY_REQUIRE_VALID (conn);
250
251 const char *shortname = conn->target->shortname ();
252 return host_string_to_python_string (shortname).release ();
253 }
254
255 /* Return a string that gives a longer description of this connection type. */
256
257 static PyObject *
connpy_get_description(PyObject * self,void * closure)258 connpy_get_description (PyObject *self, void *closure)
259 {
260 connection_object *conn = (connection_object *) self;
261
262 CONNPY_REQUIRE_VALID (conn);
263
264 const char *longname = conn->target->longname ();
265 return host_string_to_python_string (longname).release ();
266 }
267
268 /* Return a string that gives additional details about this connection, or
269 None, if there are no additional details for this connection type. */
270
271 static PyObject *
connpy_get_connection_details(PyObject * self,void * closure)272 connpy_get_connection_details (PyObject *self, void *closure)
273 {
274 connection_object *conn = (connection_object *) self;
275
276 CONNPY_REQUIRE_VALID (conn);
277
278 const char *details = conn->target->connection_string ();
279 if (details != nullptr)
280 return host_string_to_python_string (details).release ();
281 else
282 Py_RETURN_NONE;
283 }
284
285 /* Python specific initialization for this file. */
286
287 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
gdbpy_initialize_connection(void)288 gdbpy_initialize_connection (void)
289 {
290 if (PyType_Ready (&connection_object_type) < 0)
291 return -1;
292
293 if (gdb_pymodule_addobject (gdb_module, "TargetConnection",
294 (PyObject *) &connection_object_type) < 0)
295 return -1;
296
297 if (PyType_Ready (&remote_connection_object_type) < 0)
298 return -1;
299
300 if (gdb_pymodule_addobject (gdb_module, "RemoteTargetConnection",
301 (PyObject *) &remote_connection_object_type) < 0)
302 return -1;
303
304 return 0;
305 }
306
307 /* Set of callbacks used to implement gdb.send_packet. */
308
309 struct py_send_packet_callbacks : public send_remote_packet_callbacks
310 {
311 /* Constructor, initialise the result to nullptr. It is invalid to try
312 and read the result before sending a packet and processing the
313 reply. */
314
py_send_packet_callbackspy_send_packet_callbacks315 py_send_packet_callbacks ()
316 : m_result (nullptr)
317 { /* Nothing. */ }
318
319 /* There's nothing to do when the packet is sent. */
320
sendingpy_send_packet_callbacks321 void sending (gdb::array_view<const char> &buf) override
322 { /* Nothing. */ }
323
324 /* When the result is returned create a Python object and assign this
325 into M_RESULT. If for any reason we can't create a Python object to
326 represent the result then M_RESULT is set to nullptr, and Python's
327 internal error flags will be set. If the result we got back from the
328 remote is empty then set the result to None. */
329
receivedpy_send_packet_callbacks330 void received (gdb::array_view<const char> &buf) override
331 {
332 if (buf.size () > 0 && buf.data ()[0] != '\0')
333 m_result.reset (PyBytes_FromStringAndSize (buf.data (), buf.size ()));
334 else
335 {
336 /* We didn't get back any result data; set the result to None. */
337 Py_INCREF (Py_None);
338 m_result.reset (Py_None);
339 }
340 }
341
342 /* Get a reference to the result as a Python object. It is invalid to
343 call this before sending a packet to the remote and processing the
344 reply.
345
346 The result value is setup in the RECEIVED call above. If the RECEIVED
347 call causes an error then the result value will be set to nullptr,
348 and the error reason is left stored in Python's global error state.
349
350 It is important that the result is inspected immediately after sending
351 a packet to the remote, and any error fetched, calling any other
352 Python functions that might clear the error state, or rely on an error
353 not being set will cause undefined behaviour. */
354
resultpy_send_packet_callbacks355 gdbpy_ref<> result () const
356 {
357 return m_result;
358 }
359
360 private:
361
362 /* A reference to the result value. */
363
364 gdbpy_ref<> m_result;
365 };
366
367 /* Implement RemoteTargetConnection.send_packet function. Send a packet to
368 the target identified by SELF. The connection must still be valid, and
369 the packet to be sent must be non-empty, otherwise an exception will be
370 thrown. */
371
372 static PyObject *
connpy_send_packet(PyObject * self,PyObject * args,PyObject * kw)373 connpy_send_packet (PyObject *self, PyObject *args, PyObject *kw)
374 {
375 connection_object *conn = (connection_object *) self;
376
377 CONNPY_REQUIRE_VALID (conn);
378
379 static const char *keywords[] = {"packet", nullptr};
380 PyObject *packet_obj;
381
382 if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "O", keywords,
383 &packet_obj))
384 return nullptr;
385
386 /* If the packet is a unicode string then convert it to a bytes object. */
387 if (PyUnicode_Check (packet_obj))
388 {
389 /* We encode the string to bytes using the ascii codec, if this fails
390 then a suitable error will have been set. */
391 packet_obj = PyUnicode_AsASCIIString (packet_obj);
392 if (packet_obj == nullptr)
393 return nullptr;
394 }
395
396 /* Check the packet is now a bytes object. */
397 if (!PyBytes_Check (packet_obj))
398 {
399 PyErr_SetString (PyExc_TypeError, _("Packet is not a bytes object"));
400 return nullptr;
401 }
402
403 Py_ssize_t packet_len = 0;
404 char *packet_str_nonconst = nullptr;
405 if (PyBytes_AsStringAndSize (packet_obj, &packet_str_nonconst,
406 &packet_len) < 0)
407 return nullptr;
408 const char *packet_str = packet_str_nonconst;
409 gdb_assert (packet_str != nullptr);
410
411 if (packet_len == 0)
412 {
413 PyErr_SetString (PyExc_ValueError, _("Packet must not be empty"));
414 return nullptr;
415 }
416
417 try
418 {
419 scoped_restore_current_thread restore_thread;
420 switch_to_target_no_thread (conn->target);
421
422 gdb::array_view<const char> view (packet_str, packet_len);
423 py_send_packet_callbacks callbacks;
424 send_remote_packet (view, &callbacks);
425 PyObject *result = callbacks.result ().release ();
426 /* If we encountered an error converting the reply to a Python
427 object, then the result here can be nullptr. In that case, Python
428 should be aware that an error occurred. */
429 gdb_assert ((result == nullptr) == (PyErr_Occurred () != nullptr));
430 return result;
431 }
432 catch (const gdb_exception &except)
433 {
434 gdbpy_convert_exception (except);
435 return nullptr;
436 }
437 }
438
439 /* Global initialization for this file. */
440
441 void _initialize_py_connection ();
442 void
_initialize_py_connection()443 _initialize_py_connection ()
444 {
445 gdb::observers::connection_removed.attach (connpy_connection_removed,
446 "py-connection");
447 }
448
449 GDBPY_INITIALIZE_FILE (gdbpy_initialize_connection);
450
451 /* Methods for the gdb.TargetConnection object type. */
452
453 static PyMethodDef connection_object_methods[] =
454 {
455 { "is_valid", connpy_is_valid, METH_NOARGS,
456 "is_valid () -> Boolean.\n\
457 Return true if this TargetConnection is valid, false if not." },
458 { NULL }
459 };
460
461 /* Methods for the gdb.RemoteTargetConnection object type. */
462
463 static PyMethodDef remote_connection_object_methods[] =
464 {
465 { "send_packet", (PyCFunction) connpy_send_packet,
466 METH_VARARGS | METH_KEYWORDS,
467 "send_packet (PACKET) -> Bytes\n\
468 Send PACKET to a remote target, return the reply as a bytes array." },
469 { NULL }
470 };
471
472 /* Attributes for the gdb.TargetConnection object type. */
473
474 static gdb_PyGetSetDef connection_object_getset[] =
475 {
476 { "num", connpy_get_connection_num, NULL,
477 "ID number of this connection, as assigned by GDB.", NULL },
478 { "type", connpy_get_connection_type, NULL,
479 "A short string that is the name for this connection type.", NULL },
480 { "description", connpy_get_description, NULL,
481 "A longer string describing this connection type.", NULL },
482 { "details", connpy_get_connection_details, NULL,
483 "A string containing additional connection details.", NULL },
484 { NULL }
485 };
486
487 /* Define the gdb.TargetConnection object type. */
488
489 PyTypeObject connection_object_type =
490 {
491 PyVarObject_HEAD_INIT (NULL, 0)
492 "gdb.TargetConnection", /* tp_name */
493 sizeof (connection_object), /* tp_basicsize */
494 0, /* tp_itemsize */
495 connpy_connection_dealloc, /* tp_dealloc */
496 0, /* tp_print */
497 0, /* tp_getattr */
498 0, /* tp_setattr */
499 0, /* tp_compare */
500 connpy_repr, /* tp_repr */
501 0, /* tp_as_number */
502 0, /* tp_as_sequence */
503 0, /* tp_as_mapping */
504 0, /* tp_hash */
505 0, /* tp_call */
506 0, /* tp_str */
507 0, /* tp_getattro */
508 0, /* tp_setattro */
509 0, /* tp_as_buffer */
510 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
511 "GDB target connection object", /* tp_doc */
512 0, /* tp_traverse */
513 0, /* tp_clear */
514 0, /* tp_richcompare */
515 0, /* tp_weaklistoffset */
516 0, /* tp_iter */
517 0, /* tp_iternext */
518 connection_object_methods, /* tp_methods */
519 0, /* tp_members */
520 connection_object_getset, /* tp_getset */
521 0, /* tp_base */
522 0, /* tp_dict */
523 0, /* tp_descr_get */
524 0, /* tp_descr_set */
525 0, /* tp_dictoffset */
526 0, /* tp_init */
527 0 /* tp_alloc */
528 };
529
530 /* Define the gdb.RemoteTargetConnection object type. */
531
532 PyTypeObject remote_connection_object_type =
533 {
534 PyVarObject_HEAD_INIT (NULL, 0)
535 "gdb.RemoteTargetConnection", /* tp_name */
536 sizeof (connection_object), /* tp_basicsize */
537 0, /* tp_itemsize */
538 connpy_connection_dealloc, /* tp_dealloc */
539 0, /* tp_print */
540 0, /* tp_getattr */
541 0, /* tp_setattr */
542 0, /* tp_compare */
543 connpy_repr, /* tp_repr */
544 0, /* tp_as_number */
545 0, /* tp_as_sequence */
546 0, /* tp_as_mapping */
547 0, /* tp_hash */
548 0, /* tp_call */
549 0, /* tp_str */
550 0, /* tp_getattro */
551 0, /* tp_setattro */
552 0, /* tp_as_buffer */
553 Py_TPFLAGS_DEFAULT, /* tp_flags */
554 "GDB remote target connection object", /* tp_doc */
555 0, /* tp_traverse */
556 0, /* tp_clear */
557 0, /* tp_richcompare */
558 0, /* tp_weaklistoffset */
559 0, /* tp_iter */
560 0, /* tp_iternext */
561 remote_connection_object_methods, /* tp_methods */
562 0, /* tp_members */
563 0, /* tp_getset */
564 &connection_object_type, /* tp_base */
565 0, /* tp_dict */
566 0, /* tp_descr_get */
567 0, /* tp_descr_set */
568 0, /* tp_dictoffset */
569 0, /* tp_init */
570 0 /* tp_alloc */
571 };
572