xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/python/py-progspace.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* Python interface to program spaces.
2 
3    Copyright (C) 2010-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"
22 #include "charset.h"
23 #include "progspace.h"
24 #include "objfiles.h"
25 #include "language.h"
26 #include "arch-utils.h"
27 #include "solib.h"
28 #include "block.h"
29 
30 struct pspace_object
31 {
32   PyObject_HEAD
33 
34   /* The corresponding pspace.  */
35   struct program_space *pspace;
36 
37   /* Dictionary holding user-added attributes.
38      This is the __dict__ attribute of the object.  */
39   PyObject *dict;
40 
41   /* The pretty-printer list of functions.  */
42   PyObject *printers;
43 
44   /* The frame filter list of functions.  */
45   PyObject *frame_filters;
46 
47   /* The frame unwinder list.  */
48   PyObject *frame_unwinders;
49 
50   /* The type-printer list.  */
51   PyObject *type_printers;
52 
53   /* The debug method list.  */
54   PyObject *xmethods;
55 };
56 
57 extern PyTypeObject pspace_object_type
58     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("pspace_object");
59 
60 /* Clear the PSPACE pointer in a Pspace object and remove the reference.  */
61 struct pspace_deleter
62 {
63   void operator() (pspace_object *obj)
64   {
65     /* This is a fiction, but we're in a nasty spot: The pspace is in the
66        process of being deleted, we can't rely on anything in it.  Plus
67        this is one time when the current program space and current inferior
68        are not in sync: All inferiors that use PSPACE may no longer exist.
69        We don't need to do much here, and since "there is always an inferior"
70        using target_gdbarch suffices.
71        Note: We cannot call get_current_arch because it may try to access
72        the target, which may involve accessing data in the pspace currently
73        being deleted.  */
74     struct gdbarch *arch = target_gdbarch ();
75 
76     gdbpy_enter enter_py (arch);
77     gdbpy_ref<pspace_object> object (obj);
78     object->pspace = NULL;
79   }
80 };
81 
82 static const registry<program_space>::key<pspace_object, pspace_deleter>
83      pspy_pspace_data_key;
84 
85 /* Require that PSPACE_OBJ be a valid program space ID.  */
86 #define PSPY_REQUIRE_VALID(pspace_obj)				\
87   do {								\
88     if (pspace_obj->pspace == nullptr)				\
89       {								\
90 	PyErr_SetString (PyExc_RuntimeError,			\
91 			 _("Program space no longer exists."));	\
92 	return NULL;						\
93       }								\
94   } while (0)
95 
96 /* An Objfile method which returns the objfile's file name, or None.  */
97 
98 static PyObject *
99 pspy_get_filename (PyObject *self, void *closure)
100 {
101   pspace_object *obj = (pspace_object *) self;
102 
103   if (obj->pspace)
104     {
105       struct objfile *objfile = obj->pspace->symfile_object_file;
106 
107       if (objfile)
108 	return (host_string_to_python_string (objfile_name (objfile))
109 		.release ());
110     }
111   Py_RETURN_NONE;
112 }
113 
114 static void
115 pspy_dealloc (PyObject *self)
116 {
117   pspace_object *ps_self = (pspace_object *) self;
118 
119   Py_XDECREF (ps_self->dict);
120   Py_XDECREF (ps_self->printers);
121   Py_XDECREF (ps_self->frame_filters);
122   Py_XDECREF (ps_self->frame_unwinders);
123   Py_XDECREF (ps_self->type_printers);
124   Py_XDECREF (ps_self->xmethods);
125   Py_TYPE (self)->tp_free (self);
126 }
127 
128 /* Initialize a pspace_object.
129    The result is a boolean indicating success.  */
130 
131 static int
132 pspy_initialize (pspace_object *self)
133 {
134   self->pspace = NULL;
135 
136   self->dict = PyDict_New ();
137   if (self->dict == NULL)
138     return 0;
139 
140   self->printers = PyList_New (0);
141   if (self->printers == NULL)
142     return 0;
143 
144   self->frame_filters = PyDict_New ();
145   if (self->frame_filters == NULL)
146     return 0;
147 
148   self->frame_unwinders = PyList_New (0);
149   if (self->frame_unwinders == NULL)
150     return 0;
151 
152   self->type_printers = PyList_New (0);
153   if (self->type_printers == NULL)
154     return 0;
155 
156   self->xmethods = PyList_New (0);
157   if (self->xmethods == NULL)
158     return 0;
159 
160   return 1;
161 }
162 
163 static PyObject *
164 pspy_new (PyTypeObject *type, PyObject *args, PyObject *keywords)
165 {
166   gdbpy_ref<pspace_object> self ((pspace_object *) type->tp_alloc (type, 0));
167 
168   if (self != NULL)
169     {
170       if (!pspy_initialize (self.get ()))
171 	return NULL;
172     }
173 
174   return (PyObject *) self.release ();
175 }
176 
177 PyObject *
178 pspy_get_printers (PyObject *o, void *ignore)
179 {
180   pspace_object *self = (pspace_object *) o;
181 
182   Py_INCREF (self->printers);
183   return self->printers;
184 }
185 
186 static int
187 pspy_set_printers (PyObject *o, PyObject *value, void *ignore)
188 {
189   pspace_object *self = (pspace_object *) o;
190 
191   if (! value)
192     {
193       PyErr_SetString (PyExc_TypeError,
194 		       "cannot delete the pretty_printers attribute");
195       return -1;
196     }
197 
198   if (! PyList_Check (value))
199     {
200       PyErr_SetString (PyExc_TypeError,
201 		       "the pretty_printers attribute must be a list");
202       return -1;
203     }
204 
205   /* Take care in case the LHS and RHS are related somehow.  */
206   gdbpy_ref<> tmp (self->printers);
207   Py_INCREF (value);
208   self->printers = value;
209 
210   return 0;
211 }
212 
213 /* Return the Python dictionary attribute containing frame filters for
214    this program space.  */
215 PyObject *
216 pspy_get_frame_filters (PyObject *o, void *ignore)
217 {
218   pspace_object *self = (pspace_object *) o;
219 
220   Py_INCREF (self->frame_filters);
221   return self->frame_filters;
222 }
223 
224 /* Set this object file's frame filters dictionary to FILTERS.  */
225 static int
226 pspy_set_frame_filters (PyObject *o, PyObject *frame, void *ignore)
227 {
228   pspace_object *self = (pspace_object *) o;
229 
230   if (! frame)
231     {
232       PyErr_SetString (PyExc_TypeError,
233 		       "cannot delete the frame filter attribute");
234       return -1;
235     }
236 
237   if (! PyDict_Check (frame))
238     {
239       PyErr_SetString (PyExc_TypeError,
240 		       "the frame filter attribute must be a dictionary");
241       return -1;
242     }
243 
244   /* Take care in case the LHS and RHS are related somehow.  */
245   gdbpy_ref<> tmp (self->frame_filters);
246   Py_INCREF (frame);
247   self->frame_filters = frame;
248 
249   return 0;
250 }
251 
252 /* Return the list of the frame unwinders for this program space.  */
253 
254 PyObject *
255 pspy_get_frame_unwinders (PyObject *o, void *ignore)
256 {
257   pspace_object *self = (pspace_object *) o;
258 
259   Py_INCREF (self->frame_unwinders);
260   return self->frame_unwinders;
261 }
262 
263 /* Set this program space's list of the unwinders to UNWINDERS.  */
264 
265 static int
266 pspy_set_frame_unwinders (PyObject *o, PyObject *unwinders, void *ignore)
267 {
268   pspace_object *self = (pspace_object *) o;
269 
270   if (!unwinders)
271     {
272       PyErr_SetString (PyExc_TypeError,
273 		       "cannot delete the frame unwinders list");
274       return -1;
275     }
276 
277   if (!PyList_Check (unwinders))
278     {
279       PyErr_SetString (PyExc_TypeError,
280 		       "the frame unwinders attribute must be a list");
281       return -1;
282     }
283 
284   /* Take care in case the LHS and RHS are related somehow.  */
285   gdbpy_ref<> tmp (self->frame_unwinders);
286   Py_INCREF (unwinders);
287   self->frame_unwinders = unwinders;
288 
289   return 0;
290 }
291 
292 /* Get the 'type_printers' attribute.  */
293 
294 static PyObject *
295 pspy_get_type_printers (PyObject *o, void *ignore)
296 {
297   pspace_object *self = (pspace_object *) o;
298 
299   Py_INCREF (self->type_printers);
300   return self->type_printers;
301 }
302 
303 /* Get the 'xmethods' attribute.  */
304 
305 PyObject *
306 pspy_get_xmethods (PyObject *o, void *ignore)
307 {
308   pspace_object *self = (pspace_object *) o;
309 
310   Py_INCREF (self->xmethods);
311   return self->xmethods;
312 }
313 
314 /* Set the 'type_printers' attribute.  */
315 
316 static int
317 pspy_set_type_printers (PyObject *o, PyObject *value, void *ignore)
318 {
319   pspace_object *self = (pspace_object *) o;
320 
321   if (! value)
322     {
323       PyErr_SetString (PyExc_TypeError,
324 		       "cannot delete the type_printers attribute");
325       return -1;
326     }
327 
328   if (! PyList_Check (value))
329     {
330       PyErr_SetString (PyExc_TypeError,
331 		       "the type_printers attribute must be a list");
332       return -1;
333     }
334 
335   /* Take care in case the LHS and RHS are related somehow.  */
336   gdbpy_ref<> tmp (self->type_printers);
337   Py_INCREF (value);
338   self->type_printers = value;
339 
340   return 0;
341 }
342 
343 /* Implement the objfiles method.  */
344 
345 static PyObject *
346 pspy_get_objfiles (PyObject *self_, PyObject *args)
347 {
348   pspace_object *self = (pspace_object *) self_;
349 
350   PSPY_REQUIRE_VALID (self);
351 
352   gdbpy_ref<> list (PyList_New (0));
353   if (list == NULL)
354     return NULL;
355 
356   if (self->pspace != NULL)
357     {
358       for (objfile *objf : self->pspace->objfiles ())
359 	{
360 	  gdbpy_ref<> item = objfile_to_objfile_object (objf);
361 
362 	  if (item == nullptr
363 	      || PyList_Append (list.get (), item.get ()) == -1)
364 	    return NULL;
365 	}
366     }
367 
368   return list.release ();
369 }
370 
371 /* Implementation of solib_name (Long) -> String.
372    Returns the name of the shared library holding a given address, or None.  */
373 
374 static PyObject *
375 pspy_solib_name (PyObject *o, PyObject *args)
376 {
377   CORE_ADDR pc;
378   PyObject *pc_obj;
379 
380   pspace_object *self = (pspace_object *) o;
381 
382   PSPY_REQUIRE_VALID (self);
383 
384   if (!PyArg_ParseTuple (args, "O", &pc_obj))
385     return NULL;
386   if (get_addr_from_python (pc_obj, &pc) < 0)
387     return nullptr;
388 
389   const char *soname = solib_name_from_address (self->pspace, pc);
390   if (soname == nullptr)
391     Py_RETURN_NONE;
392   return host_string_to_python_string (soname).release ();
393 }
394 
395 /* Return the innermost lexical block containing the specified pc value,
396    or 0 if there is none.  */
397 static PyObject *
398 pspy_block_for_pc (PyObject *o, PyObject *args)
399 {
400   pspace_object *self = (pspace_object *) o;
401   CORE_ADDR pc;
402   PyObject *pc_obj;
403   const struct block *block = NULL;
404   struct compunit_symtab *cust = NULL;
405 
406   PSPY_REQUIRE_VALID (self);
407 
408   if (!PyArg_ParseTuple (args, "O", &pc_obj))
409     return NULL;
410   if (get_addr_from_python (pc_obj, &pc) < 0)
411     return nullptr;
412 
413   try
414     {
415       scoped_restore_current_program_space saver;
416 
417       set_current_program_space (self->pspace);
418       cust = find_pc_compunit_symtab (pc);
419 
420       if (cust != NULL && cust->objfile () != NULL)
421 	block = block_for_pc (pc);
422     }
423   catch (const gdb_exception &except)
424     {
425       GDB_PY_HANDLE_EXCEPTION (except);
426     }
427 
428   if (cust == NULL || cust->objfile () == NULL)
429     Py_RETURN_NONE;
430 
431   if (block)
432     return block_to_block_object (block, cust->objfile ());
433 
434   Py_RETURN_NONE;
435 }
436 
437 /* Implementation of the find_pc_line function.
438    Returns the gdb.Symtab_and_line object corresponding to a PC value.  */
439 
440 static PyObject *
441 pspy_find_pc_line (PyObject *o, PyObject *args)
442 {
443   CORE_ADDR pc;
444   PyObject *result = NULL; /* init for gcc -Wall */
445   PyObject *pc_obj;
446   pspace_object *self = (pspace_object *) o;
447 
448   PSPY_REQUIRE_VALID (self);
449 
450   if (!PyArg_ParseTuple (args, "O", &pc_obj))
451     return NULL;
452   if (get_addr_from_python (pc_obj, &pc) < 0)
453     return nullptr;
454 
455   try
456     {
457       struct symtab_and_line sal;
458       scoped_restore_current_program_space saver;
459 
460       set_current_program_space (self->pspace);
461 
462       sal = find_pc_line (pc, 0);
463       result = symtab_and_line_to_sal_object (sal);
464     }
465   catch (const gdb_exception &except)
466     {
467       GDB_PY_HANDLE_EXCEPTION (except);
468     }
469 
470   return result;
471 }
472 
473 /* Implementation of is_valid (self) -> Boolean.
474    Returns True if this program space still exists in GDB.  */
475 
476 static PyObject *
477 pspy_is_valid (PyObject *o, PyObject *args)
478 {
479   pspace_object *self = (pspace_object *) o;
480 
481   if (self->pspace == NULL)
482     Py_RETURN_FALSE;
483 
484   Py_RETURN_TRUE;
485 }
486 
487 
488 
489 /* Return a new reference to the Python object of type Pspace
490    representing PSPACE.  If the object has already been created,
491    return it.  Otherwise, create it.  Return NULL and set the Python
492    error on failure.  */
493 
494 gdbpy_ref<>
495 pspace_to_pspace_object (struct program_space *pspace)
496 {
497   PyObject *result = (PyObject *) pspy_pspace_data_key.get (pspace);
498   if (result == NULL)
499     {
500       gdbpy_ref<pspace_object> object
501 	((pspace_object *) PyObject_New (pspace_object, &pspace_object_type));
502       if (object == NULL)
503 	return NULL;
504       if (!pspy_initialize (object.get ()))
505 	return NULL;
506 
507       object->pspace = pspace;
508       pspy_pspace_data_key.set (pspace, object.get ());
509       result = (PyObject *) object.release ();
510     }
511 
512   return gdbpy_ref<>::new_reference (result);
513 }
514 
515 /* See python-internal.h.  */
516 
517 struct program_space *
518 progspace_object_to_program_space (PyObject *obj)
519 {
520   gdb_assert (gdbpy_is_progspace (obj));
521   return ((pspace_object *) obj)->pspace;
522 }
523 
524 /* See python-internal.h.  */
525 
526 bool
527 gdbpy_is_progspace (PyObject *obj)
528 {
529   return PyObject_TypeCheck (obj, &pspace_object_type);
530 }
531 
532 int
533 gdbpy_initialize_pspace (void)
534 {
535   if (PyType_Ready (&pspace_object_type) < 0)
536     return -1;
537 
538   return gdb_pymodule_addobject (gdb_module, "Progspace",
539 				 (PyObject *) &pspace_object_type);
540 }
541 
542 
543 
544 static gdb_PyGetSetDef pspace_getset[] =
545 {
546   { "__dict__", gdb_py_generic_dict, NULL,
547     "The __dict__ for this progspace.", &pspace_object_type },
548   { "filename", pspy_get_filename, NULL,
549     "The progspace's main filename, or None.", NULL },
550   { "pretty_printers", pspy_get_printers, pspy_set_printers,
551     "Pretty printers.", NULL },
552   { "frame_filters", pspy_get_frame_filters, pspy_set_frame_filters,
553     "Frame filters.", NULL },
554   { "frame_unwinders", pspy_get_frame_unwinders, pspy_set_frame_unwinders,
555     "Frame unwinders.", NULL },
556   { "type_printers", pspy_get_type_printers, pspy_set_type_printers,
557     "Type printers.", NULL },
558   { "xmethods", pspy_get_xmethods, NULL,
559     "Debug methods.", NULL },
560   { NULL }
561 };
562 
563 static PyMethodDef progspace_object_methods[] =
564 {
565   { "objfiles", pspy_get_objfiles, METH_NOARGS,
566     "Return a sequence of objfiles associated to this program space." },
567   { "solib_name", pspy_solib_name, METH_VARARGS,
568     "solib_name (Long) -> String.\n\
569 Return the name of the shared library holding a given address, or None." },
570   { "block_for_pc", pspy_block_for_pc, METH_VARARGS,
571     "Return the block containing the given pc value, or None." },
572   { "find_pc_line", pspy_find_pc_line, METH_VARARGS,
573     "find_pc_line (pc) -> Symtab_and_line.\n\
574 Return the gdb.Symtab_and_line object corresponding to the pc value." },
575   { "is_valid", pspy_is_valid, METH_NOARGS,
576     "is_valid () -> Boolean.\n\
577 Return true if this program space is valid, false if not." },
578   { NULL }
579 };
580 
581 PyTypeObject pspace_object_type =
582 {
583   PyVarObject_HEAD_INIT (NULL, 0)
584   "gdb.Progspace",		  /*tp_name*/
585   sizeof (pspace_object),	  /*tp_basicsize*/
586   0,				  /*tp_itemsize*/
587   pspy_dealloc,			  /*tp_dealloc*/
588   0,				  /*tp_print*/
589   0,				  /*tp_getattr*/
590   0,				  /*tp_setattr*/
591   0,				  /*tp_compare*/
592   0,				  /*tp_repr*/
593   0,				  /*tp_as_number*/
594   0,				  /*tp_as_sequence*/
595   0,				  /*tp_as_mapping*/
596   0,				  /*tp_hash */
597   0,				  /*tp_call*/
598   0,				  /*tp_str*/
599   0,				  /*tp_getattro*/
600   0,				  /*tp_setattro*/
601   0,				  /*tp_as_buffer*/
602   Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
603   "GDB progspace object",	  /* tp_doc */
604   0,				  /* tp_traverse */
605   0,				  /* tp_clear */
606   0,				  /* tp_richcompare */
607   0,				  /* tp_weaklistoffset */
608   0,				  /* tp_iter */
609   0,				  /* tp_iternext */
610   progspace_object_methods,	  /* tp_methods */
611   0,				  /* tp_members */
612   pspace_getset,		  /* tp_getset */
613   0,				  /* tp_base */
614   0,				  /* tp_dict */
615   0,				  /* tp_descr_get */
616   0,				  /* tp_descr_set */
617   offsetof (pspace_object, dict), /* tp_dictoffset */
618   0,				  /* tp_init */
619   0,				  /* tp_alloc */
620   pspy_new,			  /* tp_new */
621 };
622