Replace bsearch with a std::lower_bound-based search
[deliverable/binutils-gdb.git] / gdb / python / py-block.c
1 /* Python interface to blocks.
2
3 Copyright (C) 2008-2019 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 typedef struct blpy_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 struct blpy_block_object *prev;
38 struct blpy_block_object *next;
39 } block_object;
40
41 typedef struct {
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 struct blpy_block_object *source;
53 } block_syms_iterator_object;
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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
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 }
280
281 /* Given a block, and a block_object that has previously been
282 allocated and initialized, populate the block_object with the
283 struct block data. Also, register the block_object life-cycle
284 with the life-cycle of the object file associated with this
285 block, if needed. */
286 static void
287 set_block (block_object *obj, const struct block *block,
288 struct objfile *objfile)
289 {
290 obj->block = block;
291 obj->prev = NULL;
292 if (objfile)
293 {
294 obj->objfile = objfile;
295 obj->next = ((struct blpy_block_object *)
296 objfile_data (objfile, blpy_objfile_data_key));
297 if (obj->next)
298 obj->next->prev = obj;
299 set_objfile_data (objfile, blpy_objfile_data_key, obj);
300 }
301 else
302 obj->next = NULL;
303 }
304
305 /* Create a new block object (gdb.Block) that encapsulates the struct
306 block object from GDB. */
307 PyObject *
308 block_to_block_object (const struct block *block, struct objfile *objfile)
309 {
310 block_object *block_obj;
311
312 block_obj = PyObject_New (block_object, &block_object_type);
313 if (block_obj)
314 set_block (block_obj, block, objfile);
315
316 return (PyObject *) block_obj;
317 }
318
319 /* Return struct block reference that is wrapped by this object. */
320 const struct block *
321 block_object_to_block (PyObject *obj)
322 {
323 if (! PyObject_TypeCheck (obj, &block_object_type))
324 return NULL;
325 return ((block_object *) obj)->block;
326 }
327
328 /* Return a reference to the block iterator. */
329 static PyObject *
330 blpy_block_syms_iter (PyObject *self)
331 {
332 block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) self;
333
334 BLPY_ITER_REQUIRE_VALID (iter_obj->source);
335
336 Py_INCREF (self);
337 return self;
338 }
339
340 /* Return the next symbol in the iteration through the block's
341 dictionary. */
342 static PyObject *
343 blpy_block_syms_iternext (PyObject *self)
344 {
345 block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) self;
346 struct symbol *sym;
347
348 BLPY_ITER_REQUIRE_VALID (iter_obj->source);
349
350 if (!iter_obj->initialized_p)
351 {
352 sym = block_iterator_first (iter_obj->block, &(iter_obj->iter));
353 iter_obj->initialized_p = 1;
354 }
355 else
356 sym = block_iterator_next (&(iter_obj->iter));
357
358 if (sym == NULL)
359 {
360 PyErr_SetString (PyExc_StopIteration, _("Symbol is null."));
361 return NULL;
362 }
363
364 return symbol_to_symbol_object (sym);
365 }
366
367 static void
368 blpy_block_syms_dealloc (PyObject *obj)
369 {
370 block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) obj;
371
372 Py_XDECREF (iter_obj->source);
373 }
374
375 /* Implementation of gdb.Block.is_valid (self) -> Boolean.
376 Returns True if this block object still exists in GDB. */
377
378 static PyObject *
379 blpy_is_valid (PyObject *self, PyObject *args)
380 {
381 const struct block *block;
382
383 block = block_object_to_block (self);
384 if (block == NULL)
385 Py_RETURN_FALSE;
386
387 Py_RETURN_TRUE;
388 }
389
390 /* Implementation of gdb.BlockIterator.is_valid (self) -> Boolean.
391 Returns True if this block iterator object still exists in GDB */
392
393 static PyObject *
394 blpy_iter_is_valid (PyObject *self, PyObject *args)
395 {
396 block_syms_iterator_object *iter_obj =
397 (block_syms_iterator_object *) self;
398
399 if (iter_obj->source->block == NULL)
400 Py_RETURN_FALSE;
401
402 Py_RETURN_TRUE;
403 }
404
405 /* This function is called when an objfile is about to be freed.
406 Invalidate the block as further actions on the block would result
407 in bad data. All access to obj->symbol should be gated by
408 BLPY_REQUIRE_VALID which will raise an exception on invalid
409 blocks. */
410 static void
411 del_objfile_blocks (struct objfile *objfile, void *datum)
412 {
413 block_object *obj = (block_object *) datum;
414
415 while (obj)
416 {
417 block_object *next = obj->next;
418
419 obj->block = NULL;
420 obj->objfile = NULL;
421 obj->next = NULL;
422 obj->prev = NULL;
423
424 obj = next;
425 }
426 }
427
428 int
429 gdbpy_initialize_blocks (void)
430 {
431 block_object_type.tp_new = PyType_GenericNew;
432 if (PyType_Ready (&block_object_type) < 0)
433 return -1;
434
435 block_syms_iterator_object_type.tp_new = PyType_GenericNew;
436 if (PyType_Ready (&block_syms_iterator_object_type) < 0)
437 return -1;
438
439 /* Register an objfile "free" callback so we can properly
440 invalidate blocks when an object file is about to be
441 deleted. */
442 blpy_objfile_data_key
443 = register_objfile_data_with_cleanup (NULL, del_objfile_blocks);
444
445 if (gdb_pymodule_addobject (gdb_module, "Block",
446 (PyObject *) &block_object_type) < 0)
447 return -1;
448
449 return gdb_pymodule_addobject (gdb_module, "BlockIterator",
450 (PyObject *) &block_syms_iterator_object_type);
451 }
452
453 \f
454
455 static PyMethodDef block_object_methods[] = {
456 { "is_valid", blpy_is_valid, METH_NOARGS,
457 "is_valid () -> Boolean.\n\
458 Return true if this block is valid, false if not." },
459 {NULL} /* Sentinel */
460 };
461
462 static gdb_PyGetSetDef block_object_getset[] = {
463 { "start", blpy_get_start, NULL, "Start address of the block.", NULL },
464 { "end", blpy_get_end, NULL, "End address of the block.", NULL },
465 { "function", blpy_get_function, NULL,
466 "Symbol that names the block, or None.", NULL },
467 { "superblock", blpy_get_superblock, NULL,
468 "Block containing the block, or None.", NULL },
469 { "global_block", blpy_get_global_block, NULL,
470 "Block containing the global block.", NULL },
471 { "static_block", blpy_get_static_block, NULL,
472 "Block containing the static block.", NULL },
473 { "is_static", blpy_is_static, NULL,
474 "Whether this block is a static block.", NULL },
475 { "is_global", blpy_is_global, NULL,
476 "Whether this block is a global block.", NULL },
477 { NULL } /* Sentinel */
478 };
479
480 static PyMappingMethods block_object_as_mapping = {
481 NULL,
482 blpy_getitem,
483 NULL
484 };
485
486 PyTypeObject block_object_type = {
487 PyVarObject_HEAD_INIT (NULL, 0)
488 "gdb.Block", /*tp_name*/
489 sizeof (block_object), /*tp_basicsize*/
490 0, /*tp_itemsize*/
491 blpy_dealloc, /*tp_dealloc*/
492 0, /*tp_print*/
493 0, /*tp_getattr*/
494 0, /*tp_setattr*/
495 0, /*tp_compare*/
496 0, /*tp_repr*/
497 0, /*tp_as_number*/
498 0, /*tp_as_sequence*/
499 &block_object_as_mapping, /*tp_as_mapping*/
500 0, /*tp_hash */
501 0, /*tp_call*/
502 0, /*tp_str*/
503 0, /*tp_getattro*/
504 0, /*tp_setattro*/
505 0, /*tp_as_buffer*/
506 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
507 "GDB block object", /* tp_doc */
508 0, /* tp_traverse */
509 0, /* tp_clear */
510 0, /* tp_richcompare */
511 0, /* tp_weaklistoffset */
512 blpy_iter, /* tp_iter */
513 0, /* tp_iternext */
514 block_object_methods, /* tp_methods */
515 0, /* tp_members */
516 block_object_getset /* tp_getset */
517 };
518
519 static PyMethodDef block_iterator_object_methods[] = {
520 { "is_valid", blpy_iter_is_valid, METH_NOARGS,
521 "is_valid () -> Boolean.\n\
522 Return true if this block iterator is valid, false if not." },
523 {NULL} /* Sentinel */
524 };
525
526 PyTypeObject block_syms_iterator_object_type = {
527 PyVarObject_HEAD_INIT (NULL, 0)
528 "gdb.BlockIterator", /*tp_name*/
529 sizeof (block_syms_iterator_object), /*tp_basicsize*/
530 0, /*tp_itemsize*/
531 blpy_block_syms_dealloc, /*tp_dealloc*/
532 0, /*tp_print*/
533 0, /*tp_getattr*/
534 0, /*tp_setattr*/
535 0, /*tp_compare*/
536 0, /*tp_repr*/
537 0, /*tp_as_number*/
538 0, /*tp_as_sequence*/
539 0, /*tp_as_mapping*/
540 0, /*tp_hash */
541 0, /*tp_call*/
542 0, /*tp_str*/
543 0, /*tp_getattro*/
544 0, /*tp_setattro*/
545 0, /*tp_as_buffer*/
546 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
547 "GDB block syms iterator object", /*tp_doc */
548 0, /*tp_traverse */
549 0, /*tp_clear */
550 0, /*tp_richcompare */
551 0, /*tp_weaklistoffset */
552 blpy_block_syms_iter, /*tp_iter */
553 blpy_block_syms_iternext, /*tp_iternext */
554 block_iterator_object_methods /*tp_methods */
555 };
This page took 0.047453 seconds and 4 git commands to generate.