Update readelf's display of RELR sections to include the number of locations relocated
[binutils-gdb.git] / gdb / python / py-linetable.c
blobe3e71f9e43672208e57823140680dc27e844ae17
1 /* Python interface to line tables.
3 Copyright (C) 2013-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
20 #include "python-internal.h"
22 struct linetable_entry_object {
23 PyObject_HEAD
24 /* The line table source line. */
25 int line;
26 /* The pc associated with the source line. */
27 CORE_ADDR pc;
30 extern PyTypeObject linetable_entry_object_type
31 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("linetable_entry_object");
33 struct linetable_object {
34 PyObject_HEAD
35 /* The symtab python object. We store the Python object here as the
36 underlying symtab can become invalid, and we have to run validity
37 checks on it. */
38 PyObject *symtab;
41 extern PyTypeObject linetable_object_type
42 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("linetable_object");
44 struct ltpy_iterator_object {
45 PyObject_HEAD
46 /* The current entry in the line table for the iterator */
47 int current_index;
48 /* Pointer back to the original source line table object. Needed to
49 check if the line table is still valid, and has not been invalidated
50 when an object file has been freed. */
51 PyObject *source;
54 extern PyTypeObject ltpy_iterator_object_type
55 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("ltpy_iterator_object");
57 /* Internal helper function to extract gdb.Symtab from a gdb.LineTable
58 object. */
60 static PyObject *
61 get_symtab (PyObject *linetable)
63 linetable_object *lt = (linetable_object *) linetable;
65 return lt->symtab;
68 #define LTPY_REQUIRE_VALID(lt_obj, symtab) \
69 do { \
70 symtab = symtab_object_to_symtab (get_symtab (lt_obj)); \
71 if (symtab == NULL) \
72 { \
73 PyErr_SetString (PyExc_RuntimeError, \
74 _("Symbol Table in line table is invalid."));\
75 return NULL; \
76 } \
77 } while (0)
80 /* Helper function to create a line table object that wraps a
81 gdb.Symtab object. */
83 PyObject *
84 symtab_to_linetable_object (PyObject *symtab)
86 linetable_object *ltable;
88 ltable = PyObject_New (linetable_object, &linetable_object_type);
89 if (ltable != NULL)
91 ltable->symtab = symtab;
92 Py_INCREF (symtab);
94 return (PyObject *) ltable;
97 /* Internal helper function to build a line table object from a line
98 and an address. */
100 static PyObject *
101 build_linetable_entry (int line, CORE_ADDR address)
103 linetable_entry_object *obj;
105 obj = PyObject_New (linetable_entry_object,
106 &linetable_entry_object_type);
107 if (obj != NULL)
109 obj->line = line;
110 obj->pc = address;
113 return (PyObject *) obj;
116 /* Internal helper function to build a Python Tuple from a vector.
117 A line table entry can have multiple PCs for a given source line.
118 Construct a Tuple of all entries for the given source line, LINE
119 from the line table PCS. Construct one line table entry object per
120 address. */
122 static PyObject *
123 build_line_table_tuple_from_pcs (int line, const std::vector<CORE_ADDR> &pcs)
125 int i;
127 if (pcs.size () < 1)
128 Py_RETURN_NONE;
130 gdbpy_ref<> tuple (PyTuple_New (pcs.size ()));
132 if (tuple == NULL)
133 return NULL;
135 for (i = 0; i < pcs.size (); ++i)
137 CORE_ADDR pc = pcs[i];
138 gdbpy_ref<> obj (build_linetable_entry (line, pc));
140 if (obj == NULL)
141 return NULL;
142 else if (PyTuple_SetItem (tuple.get (), i, obj.release ()) != 0)
143 return NULL;
146 return tuple.release ();
149 /* Implementation of gdb.LineTable.line (self) -> Tuple. Returns a
150 tuple of LineTableEntry objects associated with this line from the
151 in the line table. */
153 static PyObject *
154 ltpy_get_pcs_for_line (PyObject *self, PyObject *args)
156 struct symtab *symtab;
157 gdb_py_longest py_line;
158 const linetable_entry *best_entry = nullptr;
159 std::vector<CORE_ADDR> pcs;
161 LTPY_REQUIRE_VALID (self, symtab);
163 if (! PyArg_ParseTuple (args, GDB_PY_LL_ARG, &py_line))
164 return NULL;
168 pcs = find_pcs_for_symtab_line (symtab, py_line, &best_entry);
170 catch (const gdb_exception &except)
172 GDB_PY_HANDLE_EXCEPTION (except);
175 return build_line_table_tuple_from_pcs (py_line, pcs);
178 /* Implementation of gdb.LineTable.has_line (self, line) -> Boolean.
179 Returns a Python Boolean indicating whether a source line has any
180 line table entries corresponding to it. */
182 static PyObject *
183 ltpy_has_line (PyObject *self, PyObject *args)
185 struct symtab *symtab;
186 gdb_py_longest py_line;
187 int index;
189 LTPY_REQUIRE_VALID (self, symtab);
191 if (! PyArg_ParseTuple (args, GDB_PY_LL_ARG, &py_line))
192 return NULL;
194 if (symtab->linetable () == NULL)
196 PyErr_SetString (PyExc_RuntimeError,
197 _("Linetable information not found in symbol table"));
198 return NULL;
201 for (index = 0; index < symtab->linetable ()->nitems; index++)
203 const linetable_entry *item = &(symtab->linetable ()->item[index]);
204 if (item->line == py_line)
205 Py_RETURN_TRUE;
208 Py_RETURN_FALSE;
211 /* Implementation of gdb.LineTable.source_lines (self) -> List.
212 Returns a Python List that contains source line entries in the
213 line table. This function will just return the source lines
214 without corresponding addresses. */
216 static PyObject *
217 ltpy_get_all_source_lines (PyObject *self, PyObject *args)
219 struct symtab *symtab;
220 Py_ssize_t index;
222 LTPY_REQUIRE_VALID (self, symtab);
224 if (symtab->linetable () == NULL)
226 PyErr_SetString (PyExc_RuntimeError,
227 _("Linetable information not found in symbol table"));
228 return NULL;
231 gdbpy_ref<> source_dict (PyDict_New ());
232 if (source_dict == NULL)
233 return NULL;
235 for (index = 0; index < symtab->linetable ()->nitems; index++)
237 const linetable_entry *item = &(symtab->linetable ()->item[index]);
239 /* 0 is used to signify end of line table information. Do not
240 include in the source set. */
241 if (item->line > 0)
243 gdbpy_ref<> line = gdb_py_object_from_longest (item->line);
245 if (line == NULL)
246 return NULL;
248 if (PyDict_SetItem (source_dict.get (), line.get (), Py_None) == -1)
249 return NULL;
253 return PyDict_Keys (source_dict.get ());
256 /* Implementation of gdb.LineTable.is_valid (self) -> Boolean.
257 Returns True if this line table object still exists in GDB. */
259 static PyObject *
260 ltpy_is_valid (PyObject *self, PyObject *args)
262 struct symtab *symtab = NULL;
264 symtab = symtab_object_to_symtab (get_symtab (self));
266 if (symtab == NULL)
267 Py_RETURN_FALSE;
269 Py_RETURN_TRUE;
272 /* Deconstructor for the line table object. Decrement the reference
273 to the symbol table object before calling the default free. */
275 static void
276 ltpy_dealloc (PyObject *self)
278 linetable_object *obj = (linetable_object *) self;
280 Py_DECREF (obj->symtab);
281 Py_TYPE (self)->tp_free (self);
284 /* Initialize LineTable, LineTableEntry and LineTableIterator
285 objects. */
287 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
288 gdbpy_initialize_linetable (void)
290 if (PyType_Ready (&linetable_object_type) < 0)
291 return -1;
292 if (PyType_Ready (&linetable_entry_object_type) < 0)
293 return -1;
294 if (PyType_Ready (&ltpy_iterator_object_type) < 0)
295 return -1;
297 Py_INCREF (&linetable_object_type);
298 Py_INCREF (&linetable_entry_object_type);
299 Py_INCREF (&ltpy_iterator_object_type);
301 if (gdb_pymodule_addobject (gdb_module, "LineTable",
302 (PyObject *) &linetable_object_type) < 0)
303 return -1;
305 if (gdb_pymodule_addobject (gdb_module, "LineTableEntry",
306 (PyObject *) &linetable_entry_object_type) < 0)
307 return -1;
309 if (gdb_pymodule_addobject (gdb_module, "LineTableIterator",
310 (PyObject *) &ltpy_iterator_object_type) < 0)
311 return -1;
313 return 0;
316 /* LineTable entry object get functions. */
318 /* Implementation of gdb.LineTableEntry.line (self) -> Long. Returns
319 a long integer associated with the line table entry. */
321 static PyObject *
322 ltpy_entry_get_line (PyObject *self, void *closure)
324 linetable_entry_object *obj = (linetable_entry_object *) self;
326 return gdb_py_object_from_longest (obj->line).release ();
329 /* Implementation of gdb.LineTableEntry.pc (self) -> Long. Returns a
330 a long integer associated with the PC of the line table entry. */
332 static PyObject *
333 ltpy_entry_get_pc (PyObject *self, void *closure)
335 linetable_entry_object *obj = (linetable_entry_object *) self;
337 return gdb_py_object_from_ulongest (obj->pc).release ();
340 /* LineTable iterator functions. */
342 /* Return a new line table iterator. */
344 static PyObject *
345 ltpy_iter (PyObject *self)
347 ltpy_iterator_object *ltpy_iter_obj;
348 struct symtab *symtab = NULL;
350 LTPY_REQUIRE_VALID (self, symtab);
352 ltpy_iter_obj = PyObject_New (ltpy_iterator_object,
353 &ltpy_iterator_object_type);
354 if (ltpy_iter_obj == NULL)
355 return NULL;
357 ltpy_iter_obj->current_index = 0;
358 ltpy_iter_obj->source = self;
360 Py_INCREF (self);
361 return (PyObject *) ltpy_iter_obj;
364 static void
365 ltpy_iterator_dealloc (PyObject *obj)
367 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) obj;
369 Py_DECREF (iter_obj->source);
370 Py_TYPE (obj)->tp_free (obj);
373 /* Return a reference to the line table iterator. */
375 static PyObject *
376 ltpy_iterator (PyObject *self)
378 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
379 struct symtab *symtab;
381 LTPY_REQUIRE_VALID (iter_obj->source, symtab);
383 Py_INCREF (self);
384 return self;
387 /* Return the next line table entry in the iteration through the line
388 table data structure. */
390 static PyObject *
391 ltpy_iternext (PyObject *self)
393 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
394 struct symtab *symtab;
395 PyObject *obj;
397 LTPY_REQUIRE_VALID (iter_obj->source, symtab);
399 if (symtab->linetable () == nullptr
400 || iter_obj->current_index >= symtab->linetable ()->nitems)
402 PyErr_SetNone (PyExc_StopIteration);
403 return NULL;
406 const linetable_entry *item
407 = &(symtab->linetable ()->item[iter_obj->current_index]);
409 /* Skip over internal entries such as 0. 0 signifies the end of
410 line table data and is not useful to the API user. */
411 while (item->line < 1)
413 iter_obj->current_index++;
415 /* Exit if the internal value is the last item in the line table. */
416 if (iter_obj->current_index >= symtab->linetable ()->nitems)
418 PyErr_SetNone (PyExc_StopIteration);
419 return NULL;
421 item = &(symtab->linetable ()->item[iter_obj->current_index]);
424 struct objfile *objfile = symtab->compunit ()->objfile ();
425 obj = build_linetable_entry (item->line, item->pc (objfile));
426 iter_obj->current_index++;
428 return obj;
431 /* Implementation of gdb.LineTableIterator.is_valid (self) -> Boolean.
432 Returns True if this line table iterator object still exists in
433 GDB. */
435 static PyObject *
436 ltpy_iter_is_valid (PyObject *self, PyObject *args)
438 struct symtab *symtab = NULL;
439 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
441 symtab = symtab_object_to_symtab (get_symtab (iter_obj->source));
443 if (symtab == NULL)
444 Py_RETURN_FALSE;
446 Py_RETURN_TRUE;
449 GDBPY_INITIALIZE_FILE (gdbpy_initialize_linetable);
453 static PyMethodDef linetable_object_methods[] = {
454 { "line", ltpy_get_pcs_for_line, METH_VARARGS,
455 "line (lineno) -> Tuple\n\
456 Return executable locations for a given source line." },
457 { "has_line", ltpy_has_line, METH_VARARGS,
458 "has_line (lineno) -> Boolean\n\
459 Return TRUE if this line has executable information, FALSE if not." },
460 { "source_lines", ltpy_get_all_source_lines, METH_NOARGS,
461 "source_lines () -> List\n\
462 Return a list of all executable source lines." },
463 { "is_valid", ltpy_is_valid, METH_NOARGS,
464 "is_valid () -> Boolean.\n\
465 Return True if this LineTable is valid, False if not." },
466 {NULL} /* Sentinel */
469 PyTypeObject linetable_object_type = {
470 PyVarObject_HEAD_INIT (NULL, 0)
471 "gdb.LineTable", /*tp_name*/
472 sizeof (linetable_object), /*tp_basicsize*/
473 0, /*tp_itemsize*/
474 ltpy_dealloc, /*tp_dealloc*/
475 0, /*tp_print*/
476 0, /*tp_getattr*/
477 0, /*tp_setattr*/
478 0, /*tp_compare*/
479 0, /*tp_repr*/
480 0, /*tp_as_number*/
481 0, /*tp_as_sequence*/
482 0, /*tp_as_mapping*/
483 0, /*tp_hash */
484 0, /*tp_call*/
485 0, /*tp_str*/
486 0, /*tp_getattro*/
487 0, /*tp_setattro*/
488 0, /*tp_as_buffer*/
489 Py_TPFLAGS_DEFAULT, /*tp_flags*/
490 "GDB line table object", /* tp_doc */
491 0, /* tp_traverse */
492 0, /* tp_clear */
493 0, /* tp_richcompare */
494 0, /* tp_weaklistoffset */
495 ltpy_iter, /* tp_iter */
496 0, /* tp_iternext */
497 linetable_object_methods, /* tp_methods */
498 0, /* tp_members */
499 0, /* tp_getset */
500 0, /* tp_base */
501 0, /* tp_dict */
502 0, /* tp_descr_get */
503 0, /* tp_descr_set */
504 0, /* tp_dictoffset */
505 0, /* tp_init */
506 0, /* tp_alloc */
509 static PyMethodDef ltpy_iterator_methods[] = {
510 { "is_valid", ltpy_iter_is_valid, METH_NOARGS,
511 "is_valid () -> Boolean.\n\
512 Return True if this LineTable iterator is valid, False if not." },
513 {NULL} /* Sentinel */
516 PyTypeObject ltpy_iterator_object_type = {
517 PyVarObject_HEAD_INIT (NULL, 0)
518 "gdb.LineTableIterator", /*tp_name*/
519 sizeof (ltpy_iterator_object), /*tp_basicsize*/
520 0, /*tp_itemsize*/
521 ltpy_iterator_dealloc, /*tp_dealloc*/
522 0, /*tp_print*/
523 0, /*tp_getattr*/
524 0, /*tp_setattr*/
525 0, /*tp_compare*/
526 0, /*tp_repr*/
527 0, /*tp_as_number*/
528 0, /*tp_as_sequence*/
529 0, /*tp_as_mapping*/
530 0, /*tp_hash */
531 0, /*tp_call*/
532 0, /*tp_str*/
533 0, /*tp_getattro*/
534 0, /*tp_setattro*/
535 0, /*tp_as_buffer*/
536 Py_TPFLAGS_DEFAULT, /*tp_flags*/
537 "GDB line table iterator object", /*tp_doc */
538 0, /*tp_traverse */
539 0, /*tp_clear */
540 0, /*tp_richcompare */
541 0, /*tp_weaklistoffset */
542 ltpy_iterator, /*tp_iter */
543 ltpy_iternext, /*tp_iternext */
544 ltpy_iterator_methods /*tp_methods */
548 static gdb_PyGetSetDef linetable_entry_object_getset[] = {
549 { "line", ltpy_entry_get_line, NULL,
550 "The line number in the source file.", NULL },
551 { "pc", ltpy_entry_get_pc, NULL,
552 "The memory address for this line number.", NULL },
553 { NULL } /* Sentinel */
556 PyTypeObject linetable_entry_object_type = {
557 PyVarObject_HEAD_INIT (NULL, 0)
558 "gdb.LineTableEntry", /*tp_name*/
559 sizeof (linetable_entry_object), /*tp_basicsize*/
560 0, /*tp_itemsize*/
561 0, /*tp_dealloc*/
562 0, /*tp_print*/
563 0, /*tp_getattr*/
564 0, /*tp_setattr*/
565 0, /*tp_compare*/
566 0, /*tp_repr*/
567 0, /*tp_as_number*/
568 0, /*tp_as_sequence*/
569 0, /*tp_as_mapping*/
570 0, /*tp_hash */
571 0, /*tp_call*/
572 0, /*tp_str*/
573 0, /*tp_getattro*/
574 0, /*tp_setattro*/
575 0, /*tp_as_buffer*/
576 Py_TPFLAGS_DEFAULT, /*tp_flags*/
577 "GDB line table entry object", /* tp_doc */
578 0, /* tp_traverse */
579 0, /* tp_clear */
580 0, /* tp_richcompare */
581 0, /* tp_weaklistoffset */
582 0, /* tp_iter */
583 0, /* tp_iternext */
584 0, /* tp_methods */
585 0, /* tp_members */
586 linetable_entry_object_getset, /* tp_getset */
587 0, /* tp_base */
588 0, /* tp_dict */
589 0, /* tp_descr_get */
590 0, /* tp_descr_set */
591 0, /* tp_dictoffset */
592 0, /* tp_init */
593 0, /* tp_alloc */