xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/python/py-progspace.c (revision 99e23f81b2b10aef1a10b03588663e472627bb76)
1 /* Python interface to program spaces.
2 
3    Copyright (C) 2010-2017 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 "py-ref.h"
28 
29 typedef struct
30 {
31   PyObject_HEAD
32 
33   /* The corresponding pspace.  */
34   struct program_space *pspace;
35 
36   /* Dictionary holding user-added attributes.
37      This is the __dict__ attribute of the object.  */
38   PyObject *dict;
39 
40   /* The pretty-printer list of functions.  */
41   PyObject *printers;
42 
43   /* The frame filter list of functions.  */
44   PyObject *frame_filters;
45 
46   /* The frame unwinder list.  */
47   PyObject *frame_unwinders;
48 
49   /* The type-printer list.  */
50   PyObject *type_printers;
51 
52   /* The debug method list.  */
53   PyObject *xmethods;
54 } pspace_object;
55 
56 extern PyTypeObject pspace_object_type
57     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("pspace_object");
58 
59 static const struct program_space_data *pspy_pspace_data_key;
60 
61 
62 
63 /* An Objfile method which returns the objfile's file name, or None.  */
64 
65 static PyObject *
66 pspy_get_filename (PyObject *self, void *closure)
67 {
68   pspace_object *obj = (pspace_object *) self;
69 
70   if (obj->pspace)
71     {
72       struct objfile *objfile = obj->pspace->symfile_object_file;
73 
74       if (objfile)
75 	return host_string_to_python_string (objfile_name (objfile));
76     }
77   Py_RETURN_NONE;
78 }
79 
80 static void
81 pspy_dealloc (PyObject *self)
82 {
83   pspace_object *ps_self = (pspace_object *) self;
84 
85   Py_XDECREF (ps_self->dict);
86   Py_XDECREF (ps_self->printers);
87   Py_XDECREF (ps_self->frame_filters);
88   Py_XDECREF (ps_self->frame_unwinders);
89   Py_XDECREF (ps_self->type_printers);
90   Py_XDECREF (ps_self->xmethods);
91   Py_TYPE (self)->tp_free (self);
92 }
93 
94 /* Initialize a pspace_object.
95    The result is a boolean indicating success.  */
96 
97 static int
98 pspy_initialize (pspace_object *self)
99 {
100   self->pspace = NULL;
101 
102   self->dict = PyDict_New ();
103   if (self->dict == NULL)
104     return 0;
105 
106   self->printers = PyList_New (0);
107   if (self->printers == NULL)
108     return 0;
109 
110   self->frame_filters = PyDict_New ();
111   if (self->frame_filters == NULL)
112     return 0;
113 
114   self->frame_unwinders = PyList_New (0);
115   if (self->frame_unwinders == NULL)
116     return 0;
117 
118   self->type_printers = PyList_New (0);
119   if (self->type_printers == NULL)
120     return 0;
121 
122   self->xmethods = PyList_New (0);
123   if (self->xmethods == NULL)
124     return 0;
125 
126   return 1;
127 }
128 
129 static PyObject *
130 pspy_new (PyTypeObject *type, PyObject *args, PyObject *keywords)
131 {
132   gdbpy_ref<pspace_object> self ((pspace_object *) type->tp_alloc (type, 0));
133 
134   if (self != NULL)
135     {
136       if (!pspy_initialize (self.get ()))
137 	return NULL;
138     }
139 
140   return (PyObject *) self.release ();
141 }
142 
143 PyObject *
144 pspy_get_printers (PyObject *o, void *ignore)
145 {
146   pspace_object *self = (pspace_object *) o;
147 
148   Py_INCREF (self->printers);
149   return self->printers;
150 }
151 
152 static int
153 pspy_set_printers (PyObject *o, PyObject *value, void *ignore)
154 {
155   PyObject *tmp;
156   pspace_object *self = (pspace_object *) o;
157 
158   if (! value)
159     {
160       PyErr_SetString (PyExc_TypeError,
161 		       "cannot delete the pretty_printers attribute");
162       return -1;
163     }
164 
165   if (! PyList_Check (value))
166     {
167       PyErr_SetString (PyExc_TypeError,
168 		       "the pretty_printers attribute must be a list");
169       return -1;
170     }
171 
172   /* Take care in case the LHS and RHS are related somehow.  */
173   tmp = self->printers;
174   Py_INCREF (value);
175   self->printers = value;
176   Py_XDECREF (tmp);
177 
178   return 0;
179 }
180 
181 /* Return the Python dictionary attribute containing frame filters for
182    this program space.  */
183 PyObject *
184 pspy_get_frame_filters (PyObject *o, void *ignore)
185 {
186   pspace_object *self = (pspace_object *) o;
187 
188   Py_INCREF (self->frame_filters);
189   return self->frame_filters;
190 }
191 
192 /* Set this object file's frame filters dictionary to FILTERS.  */
193 static int
194 pspy_set_frame_filters (PyObject *o, PyObject *frame, void *ignore)
195 {
196   PyObject *tmp;
197   pspace_object *self = (pspace_object *) o;
198 
199   if (! frame)
200     {
201       PyErr_SetString (PyExc_TypeError,
202 		       "cannot delete the frame filter attribute");
203       return -1;
204     }
205 
206   if (! PyDict_Check (frame))
207     {
208       PyErr_SetString (PyExc_TypeError,
209 		       "the frame filter attribute must be a dictionary");
210       return -1;
211     }
212 
213   /* Take care in case the LHS and RHS are related somehow.  */
214   tmp = self->frame_filters;
215   Py_INCREF (frame);
216   self->frame_filters = frame;
217   Py_XDECREF (tmp);
218 
219   return 0;
220 }
221 
222 /* Return the list of the frame unwinders for this program space.  */
223 
224 PyObject *
225 pspy_get_frame_unwinders (PyObject *o, void *ignore)
226 {
227   pspace_object *self = (pspace_object *) o;
228 
229   Py_INCREF (self->frame_unwinders);
230   return self->frame_unwinders;
231 }
232 
233 /* Set this program space's list of the unwinders to UNWINDERS.  */
234 
235 static int
236 pspy_set_frame_unwinders (PyObject *o, PyObject *unwinders, void *ignore)
237 {
238   PyObject *tmp;
239   pspace_object *self = (pspace_object *) o;
240 
241   if (!unwinders)
242     {
243       PyErr_SetString (PyExc_TypeError,
244 		       "cannot delete the frame unwinders list");
245       return -1;
246     }
247 
248   if (!PyList_Check (unwinders))
249     {
250       PyErr_SetString (PyExc_TypeError,
251 		       "the frame unwinders attribute must be a list");
252       return -1;
253     }
254 
255   /* Take care in case the LHS and RHS are related somehow.  */
256   tmp = self->frame_unwinders;
257   Py_INCREF (unwinders);
258   self->frame_unwinders = unwinders;
259   Py_XDECREF (tmp);
260 
261   return 0;
262 }
263 
264 /* Get the 'type_printers' attribute.  */
265 
266 static PyObject *
267 pspy_get_type_printers (PyObject *o, void *ignore)
268 {
269   pspace_object *self = (pspace_object *) o;
270 
271   Py_INCREF (self->type_printers);
272   return self->type_printers;
273 }
274 
275 /* Get the 'xmethods' attribute.  */
276 
277 PyObject *
278 pspy_get_xmethods (PyObject *o, void *ignore)
279 {
280   pspace_object *self = (pspace_object *) o;
281 
282   Py_INCREF (self->xmethods);
283   return self->xmethods;
284 }
285 
286 /* Set the 'type_printers' attribute.  */
287 
288 static int
289 pspy_set_type_printers (PyObject *o, PyObject *value, void *ignore)
290 {
291   PyObject *tmp;
292   pspace_object *self = (pspace_object *) o;
293 
294   if (! value)
295     {
296       PyErr_SetString (PyExc_TypeError,
297 		       "cannot delete the type_printers attribute");
298       return -1;
299     }
300 
301   if (! PyList_Check (value))
302     {
303       PyErr_SetString (PyExc_TypeError,
304 		       "the type_printers attribute must be a list");
305       return -1;
306     }
307 
308   /* Take care in case the LHS and RHS are related somehow.  */
309   tmp = self->type_printers;
310   Py_INCREF (value);
311   self->type_printers = value;
312   Py_XDECREF (tmp);
313 
314   return 0;
315 }
316 
317 
318 
319 /* Clear the PSPACE pointer in a Pspace object and remove the reference.  */
320 
321 static void
322 py_free_pspace (struct program_space *pspace, void *datum)
323 {
324   /* This is a fiction, but we're in a nasty spot: The pspace is in the
325      process of being deleted, we can't rely on anything in it.  Plus
326      this is one time when the current program space and current inferior
327      are not in sync: All inferiors that use PSPACE may no longer exist.
328      We don't need to do much here, and since "there is always an inferior"
329      using target_gdbarch suffices.
330      Note: We cannot call get_current_arch because it may try to access
331      the target, which may involve accessing data in the pspace currently
332      being deleted.  */
333   struct gdbarch *arch = target_gdbarch ();
334 
335   gdbpy_enter enter_py (arch, current_language);
336   gdbpy_ref<pspace_object> object ((pspace_object *) datum);
337   object->pspace = NULL;
338 }
339 
340 /* Return a borrowed reference to the Python object of type Pspace
341    representing PSPACE.  If the object has already been created,
342    return it.  Otherwise, create it.  Return NULL and set the Python
343    error on failure.  */
344 
345 PyObject *
346 pspace_to_pspace_object (struct program_space *pspace)
347 {
348   gdbpy_ref<pspace_object> object
349     ((pspace_object *) program_space_data (pspace, pspy_pspace_data_key));
350   if (object == NULL)
351     {
352       object.reset (PyObject_New (pspace_object, &pspace_object_type));
353       if (object != NULL)
354 	{
355 	  if (!pspy_initialize (object.get ()))
356 	    return NULL;
357 
358 	  object->pspace = pspace;
359 	  set_program_space_data (pspace, pspy_pspace_data_key, object.get ());
360 	}
361     }
362 
363   return (PyObject *) object.release ();
364 }
365 
366 int
367 gdbpy_initialize_pspace (void)
368 {
369   pspy_pspace_data_key
370     = register_program_space_data_with_cleanup (NULL, py_free_pspace);
371 
372   if (PyType_Ready (&pspace_object_type) < 0)
373     return -1;
374 
375   return gdb_pymodule_addobject (gdb_module, "Progspace",
376 				 (PyObject *) &pspace_object_type);
377 }
378 
379 
380 
381 static gdb_PyGetSetDef pspace_getset[] =
382 {
383   { "__dict__", gdb_py_generic_dict, NULL,
384     "The __dict__ for this progspace.", &pspace_object_type },
385   { "filename", pspy_get_filename, NULL,
386     "The progspace's main filename, or None.", NULL },
387   { "pretty_printers", pspy_get_printers, pspy_set_printers,
388     "Pretty printers.", NULL },
389   { "frame_filters", pspy_get_frame_filters, pspy_set_frame_filters,
390     "Frame filters.", NULL },
391   { "frame_unwinders", pspy_get_frame_unwinders, pspy_set_frame_unwinders,
392     "Frame unwinders.", NULL },
393   { "type_printers", pspy_get_type_printers, pspy_set_type_printers,
394     "Type printers.", NULL },
395   { "xmethods", pspy_get_xmethods, NULL,
396     "Debug methods.", NULL },
397   { NULL }
398 };
399 
400 PyTypeObject pspace_object_type =
401 {
402   PyVarObject_HEAD_INIT (NULL, 0)
403   "gdb.Progspace",		  /*tp_name*/
404   sizeof (pspace_object),	  /*tp_basicsize*/
405   0,				  /*tp_itemsize*/
406   pspy_dealloc,			  /*tp_dealloc*/
407   0,				  /*tp_print*/
408   0,				  /*tp_getattr*/
409   0,				  /*tp_setattr*/
410   0,				  /*tp_compare*/
411   0,				  /*tp_repr*/
412   0,				  /*tp_as_number*/
413   0,				  /*tp_as_sequence*/
414   0,				  /*tp_as_mapping*/
415   0,				  /*tp_hash */
416   0,				  /*tp_call*/
417   0,				  /*tp_str*/
418   0,				  /*tp_getattro*/
419   0,				  /*tp_setattro*/
420   0,				  /*tp_as_buffer*/
421   Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
422   "GDB progspace object",	  /* tp_doc */
423   0,				  /* tp_traverse */
424   0,				  /* tp_clear */
425   0,				  /* tp_richcompare */
426   0,				  /* tp_weaklistoffset */
427   0,				  /* tp_iter */
428   0,				  /* tp_iternext */
429   0,				  /* tp_methods */
430   0,				  /* tp_members */
431   pspace_getset,		  /* tp_getset */
432   0,				  /* tp_base */
433   0,				  /* tp_dict */
434   0,				  /* tp_descr_get */
435   0,				  /* tp_descr_set */
436   offsetof (pspace_object, dict), /* tp_dictoffset */
437   0,				  /* tp_init */
438   0,				  /* tp_alloc */
439   pspy_new,			  /* tp_new */
440 };
441