1 /* Python interface to blocks.
2 
3    Copyright (C) 2008-2021 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 "block.h"
22 #include "dictionary.h"
23 #include "symtab.h"
24 #include "python-internal.h"
25 #include "objfiles.h"
26 
27 struct block_object {
28   PyObject_HEAD
29   /* The GDB block structure that represents a frame's code block.  */
30   const struct block *block;
31   /* The backing object file.  There is no direct relationship in GDB
32      between a block and an object file.  When a block is created also
33      store a pointer to the object file for later use.  */
34   struct objfile *objfile;
35   /* Keep track of all blocks with a doubly-linked list.  Needed for
36      block invalidation if the source object file has been freed.  */
37   block_object *prev;
38   block_object *next;
39 };
40 
41 struct block_syms_iterator_object {
42   PyObject_HEAD
43   /* The block.  */
44   const struct block *block;
45   /* The iterator for that block.  */
46   struct block_iterator iter;
47   /* Has the iterator been initialized flag.  */
48   int initialized_p;
49   /* Pointer back to the original source block object.  Needed to
50      check if the block is still valid, and has not been invalidated
51      when an object file has been freed.  */
52   block_object *source;
53 };
54 
55 /* Require a valid block.  All access to block_object->block should be
56    gated by this call.  */
57 #define BLPY_REQUIRE_VALID(block_obj, block)		\
58   do {							\
59     block = block_object_to_block (block_obj);		\
60     if (block == NULL)					\
61       {							\
62 	PyErr_SetString (PyExc_RuntimeError,		\
63 			 _("Block is invalid."));	\
64 	return NULL;					\
65       }							\
66   } while (0)
67 
68 /* Require a valid block.  This macro is called during block iterator
69    creation, and at each next call.  */
70 #define BLPY_ITER_REQUIRE_VALID(block_obj)				\
71   do {									\
72     if (block_obj->block == NULL)					\
73       {									\
74 	PyErr_SetString (PyExc_RuntimeError,				\
75 			 _("Source block for iterator is invalid."));	\
76 	return NULL;							\
77       }									\
78   } while (0)
79 
80 extern PyTypeObject block_syms_iterator_object_type
81     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("block_syms_iterator_object");
82 static const struct objfile_data *blpy_objfile_data_key;
83 
84 static PyObject *
blpy_iter(PyObject * self)85 blpy_iter (PyObject *self)
86 {
87   block_syms_iterator_object *block_iter_obj;
88   const struct block *block = NULL;
89 
90   BLPY_REQUIRE_VALID (self, block);
91 
92   block_iter_obj = PyObject_New (block_syms_iterator_object,
93 				 &block_syms_iterator_object_type);
94   if (block_iter_obj == NULL)
95       return NULL;
96 
97   block_iter_obj->block = block;
98   block_iter_obj->initialized_p = 0;
99   Py_INCREF (self);
100   block_iter_obj->source = (block_object *) self;
101 
102   return (PyObject *) block_iter_obj;
103 }
104 
105 static PyObject *
blpy_get_start(PyObject * self,void * closure)106 blpy_get_start (PyObject *self, void *closure)
107 {
108   const struct block *block = NULL;
109 
110   BLPY_REQUIRE_VALID (self, block);
111 
112   return gdb_py_object_from_ulongest (BLOCK_START (block)).release ();
113 }
114 
115 static PyObject *
blpy_get_end(PyObject * self,void * closure)116 blpy_get_end (PyObject *self, void *closure)
117 {
118   const struct block *block = NULL;
119 
120   BLPY_REQUIRE_VALID (self, block);
121 
122   return gdb_py_object_from_ulongest (BLOCK_END (block)).release ();
123 }
124 
125 static PyObject *
blpy_get_function(PyObject * self,void * closure)126 blpy_get_function (PyObject *self, void *closure)
127 {
128   struct symbol *sym;
129   const struct block *block;
130 
131   BLPY_REQUIRE_VALID (self, block);
132 
133   sym = BLOCK_FUNCTION (block);
134   if (sym)
135     return symbol_to_symbol_object (sym);
136 
137   Py_RETURN_NONE;
138 }
139 
140 static PyObject *
blpy_get_superblock(PyObject * self,void * closure)141 blpy_get_superblock (PyObject *self, void *closure)
142 {
143   const struct block *block;
144   const struct block *super_block;
145   block_object *self_obj  = (block_object *) self;
146 
147   BLPY_REQUIRE_VALID (self, block);
148 
149   super_block = BLOCK_SUPERBLOCK (block);
150   if (super_block)
151     return block_to_block_object (super_block, self_obj->objfile);
152 
153   Py_RETURN_NONE;
154 }
155 
156 /* Return the global block associated to this block.  */
157 
158 static PyObject *
blpy_get_global_block(PyObject * self,void * closure)159 blpy_get_global_block (PyObject *self, void *closure)
160 {
161   const struct block *block;
162   const struct block *global_block;
163   block_object *self_obj  = (block_object *) self;
164 
165   BLPY_REQUIRE_VALID (self, block);
166 
167   global_block = block_global_block (block);
168 
169   return block_to_block_object (global_block,
170 				self_obj->objfile);
171 
172 }
173 
174 /* Return the static block associated to this block.  Return None
175    if we cannot get the static block (this is the global block).  */
176 
177 static PyObject *
blpy_get_static_block(PyObject * self,void * closure)178 blpy_get_static_block (PyObject *self, void *closure)
179 {
180   const struct block *block;
181   const struct block *static_block;
182   block_object *self_obj  = (block_object *) self;
183 
184   BLPY_REQUIRE_VALID (self, block);
185 
186   if (BLOCK_SUPERBLOCK (block) == NULL)
187     Py_RETURN_NONE;
188 
189   static_block = block_static_block (block);
190 
191   return block_to_block_object (static_block, self_obj->objfile);
192 }
193 
194 /* Implementation of gdb.Block.is_global (self) -> Boolean.
195    Returns True if this block object is a global block.  */
196 
197 static PyObject *
blpy_is_global(PyObject * self,void * closure)198 blpy_is_global (PyObject *self, void *closure)
199 {
200   const struct block *block;
201 
202   BLPY_REQUIRE_VALID (self, block);
203 
204   if (BLOCK_SUPERBLOCK (block))
205     Py_RETURN_FALSE;
206 
207   Py_RETURN_TRUE;
208 }
209 
210 /* Implementation of gdb.Block.is_static (self) -> Boolean.
211    Returns True if this block object is a static block.  */
212 
213 static PyObject *
blpy_is_static(PyObject * self,void * closure)214 blpy_is_static (PyObject *self, void *closure)
215 {
216   const struct block *block;
217 
218   BLPY_REQUIRE_VALID (self, block);
219 
220   if (BLOCK_SUPERBLOCK (block) != NULL
221      && BLOCK_SUPERBLOCK (BLOCK_SUPERBLOCK (block)) == NULL)
222     Py_RETURN_TRUE;
223 
224   Py_RETURN_FALSE;
225 }
226 
227 /* Given a string, returns the gdb.Symbol representing that symbol in this
228    block.  If such a symbol does not exist, returns NULL with a Python
229    exception.  */
230 
231 static PyObject *
blpy_getitem(PyObject * self,PyObject * key)232 blpy_getitem (PyObject *self, PyObject *key)
233 {
234   const struct block *block;
235 
236   BLPY_REQUIRE_VALID (self, block);
237 
238   gdb::unique_xmalloc_ptr<char> name = python_string_to_host_string (key);
239   if (name == nullptr)
240     return nullptr;
241 
242   lookup_name_info lookup_name (name.get(), symbol_name_match_type::FULL);
243 
244   /* We use ALL_BLOCK_SYMBOLS_WITH_NAME instead of block_lookup_symbol so
245      that we can look up symbols irrespective of the domain, matching the
246      iterator. It would be confusing if the iterator returns symbols you
247      can't find via getitem.  */
248   struct block_iterator iter;
249   struct symbol *sym = nullptr;
250   ALL_BLOCK_SYMBOLS_WITH_NAME (block, lookup_name, iter, sym)
251     {
252       /* Just stop at the first match */
253       break;
254     }
255 
256   if (sym == nullptr)
257     {
258       PyErr_SetObject (PyExc_KeyError, key);
259       return nullptr;
260     }
261   return symbol_to_symbol_object (sym);
262 }
263 
264 static void
blpy_dealloc(PyObject * obj)265 blpy_dealloc (PyObject *obj)
266 {
267   block_object *block = (block_object *) obj;
268 
269   if (block->prev)
270     block->prev->next = block->next;
271   else if (block->objfile)
272     {
273       set_objfile_data (block->objfile, blpy_objfile_data_key,
274 			block->next);
275     }
276   if (block->next)
277     block->next->prev = block->prev;
278   block->block = NULL;
279   Py_TYPE (obj)->tp_free (obj);
280 }
281 
282 /* Given a block, and a block_object that has previously been
283    allocated and initialized, populate the block_object with the
284    struct block data.  Also, register the block_object life-cycle
285    with the life-cycle of the object file associated with this
286    block, if needed.  */
287 static void
set_block(block_object * obj,const struct block * block,struct objfile * objfile)288 set_block (block_object *obj, const struct block *block,
289 	   struct objfile *objfile)
290 {
291   obj->block = block;
292   obj->prev = NULL;
293   if (objfile)
294     {
295       obj->objfile = objfile;
296       obj->next = ((block_object *)
297 		   objfile_data (objfile, blpy_objfile_data_key));
298       if (obj->next)
299 	obj->next->prev = obj;
300       set_objfile_data (objfile, blpy_objfile_data_key, obj);
301     }
302   else
303     obj->next = NULL;
304 }
305 
306 /* Create a new block object (gdb.Block) that encapsulates the struct
307    block object from GDB.  */
308 PyObject *
block_to_block_object(const struct block * block,struct objfile * objfile)309 block_to_block_object (const struct block *block, struct objfile *objfile)
310 {
311   block_object *block_obj;
312 
313   block_obj = PyObject_New (block_object, &block_object_type);
314   if (block_obj)
315     set_block (block_obj, block, objfile);
316 
317   return (PyObject *) block_obj;
318 }
319 
320 /* Return struct block reference that is wrapped by this object.  */
321 const struct block *
block_object_to_block(PyObject * obj)322 block_object_to_block (PyObject *obj)
323 {
324   if (! PyObject_TypeCheck (obj, &block_object_type))
325     return NULL;
326   return ((block_object *) obj)->block;
327 }
328 
329 /* Return a reference to the block iterator.  */
330 static PyObject *
blpy_block_syms_iter(PyObject * self)331 blpy_block_syms_iter (PyObject *self)
332 {
333   block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) self;
334 
335   BLPY_ITER_REQUIRE_VALID (iter_obj->source);
336 
337   Py_INCREF (self);
338   return self;
339 }
340 
341 /* Return the next symbol in the iteration through the block's
342    dictionary.  */
343 static PyObject *
blpy_block_syms_iternext(PyObject * self)344 blpy_block_syms_iternext (PyObject *self)
345 {
346   block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) self;
347   struct symbol *sym;
348 
349   BLPY_ITER_REQUIRE_VALID (iter_obj->source);
350 
351   if (!iter_obj->initialized_p)
352     {
353       sym = block_iterator_first (iter_obj->block,  &(iter_obj->iter));
354       iter_obj->initialized_p = 1;
355     }
356   else
357     sym = block_iterator_next (&(iter_obj->iter));
358 
359   if (sym == NULL)
360     {
361       PyErr_SetString (PyExc_StopIteration, _("Symbol is null."));
362       return NULL;
363     }
364 
365   return symbol_to_symbol_object (sym);
366 }
367 
368 static void
blpy_block_syms_dealloc(PyObject * obj)369 blpy_block_syms_dealloc (PyObject *obj)
370 {
371   block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) obj;
372 
373   Py_XDECREF (iter_obj->source);
374   Py_TYPE (obj)->tp_free (obj);
375 }
376 
377 /* Implementation of gdb.Block.is_valid (self) -> Boolean.
378    Returns True if this block object still exists in GDB.  */
379 
380 static PyObject *
blpy_is_valid(PyObject * self,PyObject * args)381 blpy_is_valid (PyObject *self, PyObject *args)
382 {
383   const struct block *block;
384 
385   block = block_object_to_block (self);
386   if (block == NULL)
387     Py_RETURN_FALSE;
388 
389   Py_RETURN_TRUE;
390 }
391 
392 /* Implementation of gdb.BlockIterator.is_valid (self) -> Boolean.
393    Returns True if this block iterator object still exists in GDB  */
394 
395 static PyObject *
blpy_iter_is_valid(PyObject * self,PyObject * args)396 blpy_iter_is_valid (PyObject *self, PyObject *args)
397 {
398   block_syms_iterator_object *iter_obj =
399     (block_syms_iterator_object *) self;
400 
401   if (iter_obj->source->block == NULL)
402     Py_RETURN_FALSE;
403 
404   Py_RETURN_TRUE;
405 }
406 
407 /* This function is called when an objfile is about to be freed.
408    Invalidate the block as further actions on the block would result
409    in bad data.  All access to obj->symbol should be gated by
410    BLPY_REQUIRE_VALID which will raise an exception on invalid
411    blocks.  */
412 static void
del_objfile_blocks(struct objfile * objfile,void * datum)413 del_objfile_blocks (struct objfile *objfile, void *datum)
414 {
415   block_object *obj = (block_object *) datum;
416 
417   while (obj)
418     {
419       block_object *next = obj->next;
420 
421       obj->block = NULL;
422       obj->objfile = NULL;
423       obj->next = NULL;
424       obj->prev = NULL;
425 
426       obj = next;
427     }
428 }
429 
430 void _initialize_py_block ();
431 void
_initialize_py_block()432 _initialize_py_block ()
433 {
434   /* Register an objfile "free" callback so we can properly
435      invalidate blocks when an object file is about to be
436      deleted.  */
437   blpy_objfile_data_key
438     = register_objfile_data_with_cleanup (NULL, del_objfile_blocks);
439 }
440 
441 int
gdbpy_initialize_blocks(void)442 gdbpy_initialize_blocks (void)
443 {
444   block_object_type.tp_new = PyType_GenericNew;
445   if (PyType_Ready (&block_object_type) < 0)
446     return -1;
447 
448   block_syms_iterator_object_type.tp_new = PyType_GenericNew;
449   if (PyType_Ready (&block_syms_iterator_object_type) < 0)
450     return -1;
451 
452   if (gdb_pymodule_addobject (gdb_module, "Block",
453 			      (PyObject *) &block_object_type) < 0)
454     return -1;
455 
456   return gdb_pymodule_addobject (gdb_module, "BlockIterator",
457 				 (PyObject *) &block_syms_iterator_object_type);
458 }
459 
460 
461 
462 static PyMethodDef block_object_methods[] = {
463   { "is_valid", blpy_is_valid, METH_NOARGS,
464     "is_valid () -> Boolean.\n\
465 Return true if this block is valid, false if not." },
466   {NULL}  /* Sentinel */
467 };
468 
469 static gdb_PyGetSetDef block_object_getset[] = {
470   { "start", blpy_get_start, NULL, "Start address of the block.", NULL },
471   { "end", blpy_get_end, NULL, "End address of the block.", NULL },
472   { "function", blpy_get_function, NULL,
473     "Symbol that names the block, or None.", NULL },
474   { "superblock", blpy_get_superblock, NULL,
475     "Block containing the block, or None.", NULL },
476   { "global_block", blpy_get_global_block, NULL,
477     "Block containing the global block.", NULL },
478   { "static_block", blpy_get_static_block, NULL,
479     "Block containing the static block.", NULL },
480   { "is_static", blpy_is_static, NULL,
481     "Whether this block is a static block.", NULL },
482   { "is_global", blpy_is_global, NULL,
483     "Whether this block is a global block.", NULL },
484   { NULL }  /* Sentinel */
485 };
486 
487 static PyMappingMethods block_object_as_mapping = {
488   NULL,
489   blpy_getitem,
490   NULL
491 };
492 
493 PyTypeObject block_object_type = {
494   PyVarObject_HEAD_INIT (NULL, 0)
495   "gdb.Block",			  /*tp_name*/
496   sizeof (block_object),	  /*tp_basicsize*/
497   0,				  /*tp_itemsize*/
498   blpy_dealloc,                   /*tp_dealloc*/
499   0,				  /*tp_print*/
500   0,				  /*tp_getattr*/
501   0,				  /*tp_setattr*/
502   0,				  /*tp_compare*/
503   0,				  /*tp_repr*/
504   0,				  /*tp_as_number*/
505   0,				  /*tp_as_sequence*/
506   &block_object_as_mapping,	  /*tp_as_mapping*/
507   0,				  /*tp_hash */
508   0,				  /*tp_call*/
509   0,				  /*tp_str*/
510   0,				  /*tp_getattro*/
511   0,				  /*tp_setattro*/
512   0,				  /*tp_as_buffer*/
513   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,  /*tp_flags*/
514   "GDB block object",		  /* tp_doc */
515   0,				  /* tp_traverse */
516   0,				  /* tp_clear */
517   0,				  /* tp_richcompare */
518   0,				  /* tp_weaklistoffset */
519   blpy_iter,			  /* tp_iter */
520   0,				  /* tp_iternext */
521   block_object_methods,		  /* tp_methods */
522   0,				  /* tp_members */
523   block_object_getset		  /* tp_getset */
524 };
525 
526 static PyMethodDef block_iterator_object_methods[] = {
527   { "is_valid", blpy_iter_is_valid, METH_NOARGS,
528     "is_valid () -> Boolean.\n\
529 Return true if this block iterator is valid, false if not." },
530   {NULL}  /* Sentinel */
531 };
532 
533 PyTypeObject block_syms_iterator_object_type = {
534   PyVarObject_HEAD_INIT (NULL, 0)
535   "gdb.BlockIterator",		  /*tp_name*/
536   sizeof (block_syms_iterator_object),	      /*tp_basicsize*/
537   0,				  /*tp_itemsize*/
538   blpy_block_syms_dealloc,	  /*tp_dealloc*/
539   0,				  /*tp_print*/
540   0,				  /*tp_getattr*/
541   0,				  /*tp_setattr*/
542   0,				  /*tp_compare*/
543   0,				  /*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 | Py_TPFLAGS_HAVE_ITER,  /*tp_flags*/
554   "GDB block syms iterator object",	      /*tp_doc */
555   0,				  /*tp_traverse */
556   0,				  /*tp_clear */
557   0,				  /*tp_richcompare */
558   0,				  /*tp_weaklistoffset */
559   blpy_block_syms_iter,           /*tp_iter */
560   blpy_block_syms_iternext,	  /*tp_iternext */
561   block_iterator_object_methods   /*tp_methods */
562 };
563