]> Git Repo - binutils.git/blob - gdb/python/py-connection.c
gdb: remove SYMTAB_COMPUNIT macro, add getter/setter
[binutils.git] / gdb / python / py-connection.c
1 /* Python interface to inferiors.
2
3    Copyright (C) 2009-2022 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"
22 #include "process-stratum-target.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
36 struct connection_object
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).  */
46   struct process_stratum_target *target;
47 };
48
49 extern PyTypeObject connection_object_type
50   CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("connection_object");
51
52 extern 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.  */
69 static std::map<process_stratum_target *,
70                 gdbpy_ref<connection_object>> all_connection_objects;
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
79 gdbpy_ref<>
80 target_to_connection_object (process_stratum_target *target)
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))
92         type = &remote_connection_object_type;
93       else
94         type = &connection_object_type;
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
114 PyObject *
115 gdbpy_connections (PyObject *self, PyObject *args)
116 {
117   gdbpy_ref<> list (PyList_New (0));
118   if (list == nullptr)
119     return nullptr;
120
121   for (process_stratum_target *target : all_non_exited_process_targets ())
122     {
123       gdb_assert (target != nullptr);
124
125       gdbpy_ref<> conn = target_to_connection_object (target);
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
140 static int
141 emit_connection_event (process_stratum_target *target,
142                        eventregistry_object *registry)
143 {
144   gdbpy_ref<> event_obj
145     = create_event_object (&connection_event_object_type);
146   if (event_obj == nullptr)
147     return -1;
148
149   gdbpy_ref<> conn = target_to_connection_object (target);
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
158 static void
159 connpy_connection_removed (process_stratum_target *target)
160 {
161   if (!gdb_python_initialized)
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)
168       gdbpy_print_stack ();
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
181 static void
182 connpy_connection_dealloc (PyObject *obj)
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
200 static PyObject *
201 connpy_repr (PyObject *obj)
202 {
203   connection_object *self = (connection_object *) obj;
204   process_stratum_target *target = self->target;
205
206   if (target == nullptr)
207     return PyString_FromFormat ("<%s (invalid)>", Py_TYPE (obj)->tp_name);
208
209   return PyString_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
219 static PyObject *
220 connpy_is_valid (PyObject *self, PyObject *args)
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
232 static PyObject *
233 connpy_get_connection_num (PyObject *self, void *closure)
234 {
235   connection_object *conn = (connection_object *) self;
236
237   CONNPY_REQUIRE_VALID (conn);
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
245 static PyObject *
246 connpy_get_connection_type (PyObject *self, void *closure)
247 {
248   connection_object *conn = (connection_object *) self;
249
250   CONNPY_REQUIRE_VALID (conn);
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
258 static PyObject *
259 connpy_get_description (PyObject *self, void *closure)
260 {
261   connection_object *conn = (connection_object *) self;
262
263   CONNPY_REQUIRE_VALID (conn);
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
272 static PyObject *
273 connpy_get_connection_details (PyObject *self, void *closure)
274 {
275   connection_object *conn = (connection_object *) self;
276
277   CONNPY_REQUIRE_VALID (conn);
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
288 int
289 gdbpy_initialize_connection (void)
290 {
291   if (PyType_Ready (&connection_object_type) < 0)
292     return -1;
293
294   if (gdb_pymodule_addobject (gdb_module, "TargetConnection",
295                               (PyObject *) &connection_object_type) < 0)
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",
302                               (PyObject *) &remote_connection_object_type) < 0)
303     return -1;
304
305   return 0;
306 }
307
308 /* Set of callbacks used to implement gdb.send_packet.  */
309
310 struct py_send_packet_callbacks : public send_remote_packet_callbacks
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
316   py_send_packet_callbacks ()
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
356   gdbpy_ref<> result () const
357   {
358     return m_result;
359   }
360
361 private:
362
363   /* A reference to the result value.  */
364
365   gdbpy_ref<> m_result;
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
373 static PyObject *
374 connpy_send_packet (PyObject *self, PyObject *args, PyObject *kw)
375 {
376   connection_object *conn = (connection_object *) self;
377
378   CONNPY_REQUIRE_VALID (conn);
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;
421       switch_to_target_no_thread (conn->target);
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     {
435       gdbpy_convert_exception (except);
436       return nullptr;
437     }
438 }
439
440 /* Global initialization for this file.  */
441
442 void _initialize_py_connection ();
443 void
444 _initialize_py_connection ()
445 {
446   gdb::observers::connection_removed.attach (connpy_connection_removed,
447                                              "py-connection");
448 }
449
450 /* Methods for the gdb.TargetConnection object type.  */
451
452 static PyMethodDef connection_object_methods[] =
453 {
454   { "is_valid", connpy_is_valid, METH_NOARGS,
455     "is_valid () -> Boolean.\n\
456 Return true if this TargetConnection is valid, false if not." },
457   { NULL }
458 };
459
460 /* Methods for the gdb.RemoteTargetConnection object type.  */
461
462 static PyMethodDef remote_connection_object_methods[] =
463 {
464   { "send_packet", (PyCFunction) connpy_send_packet,
465     METH_VARARGS | METH_KEYWORDS,
466     "send_packet (PACKET) -> Bytes\n\
467 Send PACKET to a remote target, return the reply as a bytes array." },
468   { NULL }
469 };
470
471 /* Attributes for the gdb.TargetConnection object type.  */
472
473 static gdb_PyGetSetDef connection_object_getset[] =
474 {
475   { "num", connpy_get_connection_num, NULL,
476     "ID number of this connection, as assigned by GDB.", NULL },
477   { "type", connpy_get_connection_type, NULL,
478     "A short string that is the name for this connection type.", NULL },
479   { "description", connpy_get_description, NULL,
480     "A longer string describing this connection type.", NULL },
481   { "details", connpy_get_connection_details, NULL,
482     "A string containing additional connection details.", NULL },
483   { NULL }
484 };
485
486 /* Define the gdb.TargetConnection object type.  */
487
488 PyTypeObject connection_object_type =
489 {
490   PyVarObject_HEAD_INIT (NULL, 0)
491   "gdb.TargetConnection",         /* tp_name */
492   sizeof (connection_object),     /* tp_basicsize */
493   0,                              /* tp_itemsize */
494   connpy_connection_dealloc,      /* tp_dealloc */
495   0,                              /* tp_print */
496   0,                              /* tp_getattr */
497   0,                              /* tp_setattr */
498   0,                              /* tp_compare */
499   connpy_repr,                    /* tp_repr */
500   0,                              /* tp_as_number */
501   0,                              /* tp_as_sequence */
502   0,                              /* tp_as_mapping */
503   0,                              /* tp_hash  */
504   0,                              /* tp_call */
505   0,                              /* tp_str */
506   0,                              /* tp_getattro */
507   0,                              /* tp_setattro */
508   0,                              /* tp_as_buffer */
509   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,     /* tp_flags */
510   "GDB target connection object", /* tp_doc */
511   0,                              /* tp_traverse */
512   0,                              /* tp_clear */
513   0,                              /* tp_richcompare */
514   0,                              /* tp_weaklistoffset */
515   0,                              /* tp_iter */
516   0,                              /* tp_iternext */
517   connection_object_methods,      /* tp_methods */
518   0,                              /* tp_members */
519   connection_object_getset,       /* tp_getset */
520   0,                              /* tp_base */
521   0,                              /* tp_dict */
522   0,                              /* tp_descr_get */
523   0,                              /* tp_descr_set */
524   0,                              /* tp_dictoffset */
525   0,                              /* tp_init */
526   0                               /* tp_alloc */
527 };
528
529 /* Define the gdb.RemoteTargetConnection object type.  */
530
531 PyTypeObject remote_connection_object_type =
532 {
533   PyVarObject_HEAD_INIT (NULL, 0)
534   "gdb.RemoteTargetConnection",   /* tp_name */
535   sizeof (connection_object),     /* tp_basicsize */
536   0,                              /* tp_itemsize */
537   connpy_connection_dealloc,      /* tp_dealloc */
538   0,                              /* tp_print */
539   0,                              /* tp_getattr */
540   0,                              /* tp_setattr */
541   0,                              /* tp_compare */
542   connpy_repr,                    /* tp_repr */
543   0,                              /* tp_as_number */
544   0,                              /* tp_as_sequence */
545   0,                              /* tp_as_mapping */
546   0,                              /* tp_hash  */
547   0,                              /* tp_call */
548   0,                              /* tp_str */
549   0,                              /* tp_getattro */
550   0,                              /* tp_setattro */
551   0,                              /* tp_as_buffer */
552   Py_TPFLAGS_DEFAULT,             /* tp_flags */
553   "GDB remote target connection object",          /* tp_doc */
554   0,                              /* tp_traverse */
555   0,                              /* tp_clear */
556   0,                              /* tp_richcompare */
557   0,                              /* tp_weaklistoffset */
558   0,                              /* tp_iter */
559   0,                              /* tp_iternext */
560   remote_connection_object_methods,       /* tp_methods */
561   0,                              /* tp_members */
562   0,                              /* tp_getset */
563   &connection_object_type,        /* tp_base */
564   0,                              /* tp_dict */
565   0,                              /* tp_descr_get */
566   0,                              /* tp_descr_set */
567   0,                              /* tp_dictoffset */
568   0,                              /* tp_init */
569   0                               /* tp_alloc */
570 };
This page took 0.059024 seconds and 4 git commands to generate.