GDB (xrefs)
Loading...
Searching...
No Matches
py-linetable.c
Go to the documentation of this file.
1/* Python interface to line tables.
2
3 Copyright (C) 2013-2023 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
24 PyObject_HEAD
25 /* The line table source line. */
26 int line;
27 /* The pc associated with the source line. */
28 CORE_ADDR pc;
29};
30
31extern PyTypeObject linetable_entry_object_type
32 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("linetable_entry_object");
33
35 PyObject_HEAD
36 /* The symtab python object. We store the Python object here as the
37 underlying symtab can become invalid, and we have to run validity
38 checks on it. */
40};
41
42extern PyTypeObject linetable_object_type
44
46 PyObject_HEAD
47 /* The current entry in the line table for the iterator */
49 /* Pointer back to the original source line table object. Needed to
50 check if the line table is still valid, and has not been invalidated
51 when an object file has been freed. */
53};
54
55extern PyTypeObject ltpy_iterator_object_type
56 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("ltpy_iterator_object");
57
58/* Internal helper function to extract gdb.Symtab from a gdb.LineTable
59 object. */
60
61static PyObject *
63{
65
66 return lt->symtab;
67}
68
69#define LTPY_REQUIRE_VALID(lt_obj, symtab) \
70 do { \
71 symtab = symtab_object_to_symtab (get_symtab (lt_obj)); \
72 if (symtab == NULL) \
73 { \
74 PyErr_SetString (PyExc_RuntimeError, \
75 _("Symbol Table in line table is invalid."));\
76 return NULL; \
77 } \
78 } while (0)
79
80
81/* Helper function to create a line table object that wraps a
82 gdb.Symtab object. */
83
86{
87 linetable_object *ltable;
88
89 ltable = PyObject_New (linetable_object, &linetable_object_type);
90 if (ltable != NULL)
91 {
92 ltable->symtab = symtab;
93 Py_INCREF (symtab);
94 }
95 return (PyObject *) ltable;
96}
97
98/* Internal helper function to build a line table object from a line
99 and an address. */
100
101static PyObject *
102build_linetable_entry (int line, CORE_ADDR address)
103{
105
106 obj = PyObject_New (linetable_entry_object,
108 if (obj != NULL)
109 {
110 obj->line = line;
111 obj->pc = address;
112 }
113
114 return (PyObject *) obj;
115}
116
117/* Internal helper function to build a Python Tuple from a vector.
118 A line table entry can have multiple PCs for a given source line.
119 Construct a Tuple of all entries for the given source line, LINE
120 from the line table PCS. Construct one line table entry object per
121 address. */
122
123static PyObject *
124build_line_table_tuple_from_pcs (int line, const std::vector<CORE_ADDR> &pcs)
125{
126 int i;
127
128 if (pcs.size () < 1)
129 Py_RETURN_NONE;
130
131 gdbpy_ref<> tuple (PyTuple_New (pcs.size ()));
132
133 if (tuple == NULL)
134 return NULL;
135
136 for (i = 0; i < pcs.size (); ++i)
137 {
138 CORE_ADDR pc = pcs[i];
139 gdbpy_ref<> obj (build_linetable_entry (line, pc));
140
141 if (obj == NULL)
142 return NULL;
143 else if (PyTuple_SetItem (tuple.get (), i, obj.release ()) != 0)
144 return NULL;
145 }
146
147 return tuple.release ();
148}
149
150/* Implementation of gdb.LineTable.line (self) -> Tuple. Returns a
151 tuple of LineTableEntry objects associated with this line from the
152 in the line table. */
153
154static PyObject *
156{
157 struct symtab *symtab;
158 gdb_py_longest py_line;
159 const linetable_entry *best_entry = nullptr;
160 std::vector<CORE_ADDR> pcs;
161
163
164 if (! PyArg_ParseTuple (args, GDB_PY_LL_ARG, &py_line))
165 return NULL;
166
167 try
168 {
169 pcs = find_pcs_for_symtab_line (symtab, py_line, &best_entry);
170 }
171 catch (const gdb_exception &except)
172 {
174 }
175
176 return build_line_table_tuple_from_pcs (py_line, pcs);
177}
178
179/* Implementation of gdb.LineTable.has_line (self, line) -> Boolean.
180 Returns a Python Boolean indicating whether a source line has any
181 line table entries corresponding to it. */
182
183static PyObject *
185{
186 struct symtab *symtab;
187 gdb_py_longest py_line;
188 int index;
189
191
192 if (! PyArg_ParseTuple (args, GDB_PY_LL_ARG, &py_line))
193 return NULL;
194
195 if (symtab->linetable () == NULL)
196 {
197 PyErr_SetString (PyExc_RuntimeError,
198 _("Linetable information not found in symbol table"));
199 return NULL;
200 }
201
202 for (index = 0; index < symtab->linetable ()->nitems; index++)
203 {
204 const linetable_entry *item = &(symtab->linetable ()->item[index]);
205 if (item->line == py_line)
206 Py_RETURN_TRUE;
207 }
208
209 Py_RETURN_FALSE;
210}
211
212/* Implementation of gdb.LineTable.source_lines (self) -> List.
213 Returns a Python List that contains source line entries in the
214 line table. This function will just return the source lines
215 without corresponding addresses. */
216
217static PyObject *
219{
220 struct symtab *symtab;
221 Py_ssize_t index;
222
224
225 if (symtab->linetable () == NULL)
226 {
227 PyErr_SetString (PyExc_RuntimeError,
228 _("Linetable information not found in symbol table"));
229 return NULL;
230 }
231
232 gdbpy_ref<> source_dict (PyDict_New ());
233 if (source_dict == NULL)
234 return NULL;
235
236 for (index = 0; index < symtab->linetable ()->nitems; index++)
237 {
238 const linetable_entry *item = &(symtab->linetable ()->item[index]);
239
240 /* 0 is used to signify end of line table information. Do not
241 include in the source set. */
242 if (item->line > 0)
243 {
245
246 if (line == NULL)
247 return NULL;
248
249 if (PyDict_SetItem (source_dict.get (), line.get (), Py_None) == -1)
250 return NULL;
251 }
252 }
253
254 return PyDict_Keys (source_dict.get ());
255}
256
257/* Implementation of gdb.LineTable.is_valid (self) -> Boolean.
258 Returns True if this line table object still exists in GDB. */
259
260static PyObject *
262{
263 struct symtab *symtab = NULL;
264
266
267 if (symtab == NULL)
268 Py_RETURN_FALSE;
269
270 Py_RETURN_TRUE;
271}
272
273/* Deconstructor for the line table object. Decrement the reference
274 to the symbol table object before calling the default free. */
275
276static void
278{
279 linetable_object *obj = (linetable_object *) self;
280
281 Py_DECREF (obj->symtab);
282 Py_TYPE (self)->tp_free (self);
283}
284
285/* Initialize LineTable, LineTableEntry and LineTableIterator
286 objects. */
287
290{
291 if (PyType_Ready (&linetable_object_type) < 0)
292 return -1;
293 if (PyType_Ready (&linetable_entry_object_type) < 0)
294 return -1;
295 if (PyType_Ready (&ltpy_iterator_object_type) < 0)
296 return -1;
297
298 Py_INCREF (&linetable_object_type);
299 Py_INCREF (&linetable_entry_object_type);
300 Py_INCREF (&ltpy_iterator_object_type);
301
302 if (gdb_pymodule_addobject (gdb_module, "LineTable",
304 return -1;
305
306 if (gdb_pymodule_addobject (gdb_module, "LineTableEntry",
308 return -1;
309
310 if (gdb_pymodule_addobject (gdb_module, "LineTableIterator",
312 return -1;
313
314 return 0;
315}
316
317/* LineTable entry object get functions. */
318
319/* Implementation of gdb.LineTableEntry.line (self) -> Long. Returns
320 a long integer associated with the line table entry. */
321
322static PyObject *
323ltpy_entry_get_line (PyObject *self, void *closure)
324{
326
327 return gdb_py_object_from_longest (obj->line).release ();
328}
329
330/* Implementation of gdb.LineTableEntry.pc (self) -> Long. Returns a
331 a long integer associated with the PC of the line table entry. */
332
333static PyObject *
334ltpy_entry_get_pc (PyObject *self, void *closure)
335{
337
338 return gdb_py_object_from_ulongest (obj->pc).release ();
339}
340
341/* LineTable iterator functions. */
342
343/* Return a new line table iterator. */
344
345static PyObject *
347{
348 ltpy_iterator_object *ltpy_iter_obj;
349 struct symtab *symtab = NULL;
350
352
353 ltpy_iter_obj = PyObject_New (ltpy_iterator_object,
355 if (ltpy_iter_obj == NULL)
356 return NULL;
357
358 ltpy_iter_obj->current_index = 0;
359 ltpy_iter_obj->source = self;
360
361 Py_INCREF (self);
362 return (PyObject *) ltpy_iter_obj;
363}
364
365static void
367{
368 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) obj;
369
370 Py_DECREF (iter_obj->source);
371 Py_TYPE (obj)->tp_free (obj);
372}
373
374/* Return a reference to the line table iterator. */
375
376static PyObject *
378{
379 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
380 struct symtab *symtab;
381
382 LTPY_REQUIRE_VALID (iter_obj->source, symtab);
383
384 Py_INCREF (self);
385 return self;
386}
387
388/* Return the next line table entry in the iteration through the line
389 table data structure. */
390
391static PyObject *
393{
394 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
395 struct symtab *symtab;
396 PyObject *obj;
397
398 LTPY_REQUIRE_VALID (iter_obj->source, symtab);
399
400 if (iter_obj->current_index >= symtab->linetable ()->nitems)
401 {
402 PyErr_SetNone (PyExc_StopIteration);
403 return NULL;
404 }
405
406 const linetable_entry *item
407 = &(symtab->linetable ()->item[iter_obj->current_index]);
408
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)
412 {
413 iter_obj->current_index++;
414
415 /* Exit if the internal value is the last item in the line table. */
416 if (iter_obj->current_index >= symtab->linetable ()->nitems)
417 {
418 PyErr_SetNone (PyExc_StopIteration);
419 return NULL;
420 }
421 item = &(symtab->linetable ()->item[iter_obj->current_index]);
422 }
423
424 struct objfile *objfile = symtab->compunit ()->objfile ();
425 obj = build_linetable_entry (item->line, item->pc (objfile));
426 iter_obj->current_index++;
427
428 return obj;
429}
430
431/* Implementation of gdb.LineTableIterator.is_valid (self) -> Boolean.
432 Returns True if this line table iterator object still exists in
433 GDB. */
434
435static PyObject *
437{
438 struct symtab *symtab = NULL;
439 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
440
442
443 if (symtab == NULL)
444 Py_RETURN_FALSE;
445
446 Py_RETURN_TRUE;
447}
448
450
451
452
453static PyMethodDef linetable_object_methods[] = {
454 { "line", ltpy_get_pcs_for_line, METH_VARARGS,
455 "line (lineno) -> Tuple\n\
456Return executable locations for a given source line." },
457 { "has_line", ltpy_has_line, METH_VARARGS,
458 "has_line (lineno) -> Boolean\n\
459Return 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\
462Return a list of all executable source lines." },
463 { "is_valid", ltpy_is_valid, METH_NOARGS,
464 "is_valid () -> Boolean.\n\
465Return True if this LineTable is valid, False if not." },
466 {NULL} /* Sentinel */
467};
468
469PyTypeObject 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 */
507};
508
509static PyMethodDef ltpy_iterator_methods[] = {
510 { "is_valid", ltpy_iter_is_valid, METH_NOARGS,
511 "is_valid () -> Boolean.\n\
512Return True if this LineTable iterator is valid, False if not." },
513 {NULL} /* Sentinel */
514};
515
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 */
545};
546
547
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 */
554};
555
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 */
594};
@ lt
Definition 1.cc:35
static PyObject * ltpy_entry_get_pc(PyObject *self, void *closure)
static PyObject * ltpy_iterator(PyObject *self)
#define LTPY_REQUIRE_VALID(lt_obj, symtab)
PyObject * symtab_to_linetable_object(PyObject *symtab)
static void ltpy_dealloc(PyObject *self)
PyTypeObject linetable_object_type
static void ltpy_iterator_dealloc(PyObject *obj)
static PyMethodDef ltpy_iterator_methods[]
static PyObject * ltpy_get_all_source_lines(PyObject *self, PyObject *args)
static PyObject * get_symtab(PyObject *linetable)
static gdb_PyGetSetDef linetable_entry_object_getset[]
static PyObject * ltpy_iter(PyObject *self)
static PyObject * ltpy_get_pcs_for_line(PyObject *self, PyObject *args)
static PyObject * build_linetable_entry(int line, CORE_ADDR address)
static PyObject * ltpy_is_valid(PyObject *self, PyObject *args)
static PyObject * ltpy_iter_is_valid(PyObject *self, PyObject *args)
static PyMethodDef linetable_object_methods[]
static PyObject * ltpy_entry_get_line(PyObject *self, void *closure)
static PyObject * ltpy_has_line(PyObject *self, PyObject *args)
static PyObject * ltpy_iternext(PyObject *self)
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION gdbpy_initialize_linetable(void)
PyTypeObject linetable_entry_object_type
PyTypeObject ltpy_iterator_object_type
static PyObject * build_line_table_tuple_from_pcs(int line, const std::vector< CORE_ADDR > &pcs)
gdb::ref_ptr< T, gdbpy_ref_policy< T > > gdbpy_ref
Definition py-ref.h:42
struct symtab * symtab_object_to_symtab(PyObject *obj)
Definition py-symtab.c:505
gdbpy_ref gdb_py_object_from_longest(LONGEST l)
Definition py-utils.c:282
int gdb_pymodule_addobject(PyObject *module, const char *name, PyObject *object)
Definition py-utils.c:334
gdbpy_ref gdb_py_object_from_ulongest(ULONGEST l)
Definition py-utils.c:293
PyObject * gdb_module
long gdb_py_longest
#define CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF(ARG)
#define GDB_PY_LL_ARG
#define CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
#define GDBPY_INITIALIZE_FILE(INIT,...)
#define GDB_PY_HANDLE_EXCEPTION(Exception)
struct objfile * objfile() const
Definition symtab.h:1788
PyObject_HEAD int line
CORE_ADDR pc
Definition symtab.h:1596
int line
Definition symtab.h:1622
CORE_ADDR pc(const struct objfile *objfile) const
Definition symtab.c:336
PyObject_HEAD PyObject * symtab
int nitems
Definition symtab.h:1656
struct linetable_entry item[1]
Definition symtab.h:1661
PyObject_HEAD int current_index
struct compunit_symtab * compunit() const
Definition symtab.h:1677
const struct linetable * linetable() const
Definition symtab.h:1687
std::vector< CORE_ADDR > find_pcs_for_symtab_line(struct symtab *symtab, int line, const linetable_entry **best_item)
Definition symtab.c:3430
int PyObject
Definition varobj.c:41