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