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