]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/python/py-linetable.c
libsframe: fix error code in sframe_decode
[thirdparty/binutils-gdb.git] / gdb / python / py-linetable.c
1 /* Python interface to line tables.
2
3 Copyright (C) 2013-2025 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 "python-internal.h"
21
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;
28 };
29
30 extern PyTypeObject linetable_entry_object_type
31 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("linetable_entry_object");
32
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;
39 };
40
41 extern PyTypeObject linetable_object_type
42 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("linetable_object");
43
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;
52 };
53
54 extern PyTypeObject ltpy_iterator_object_type
55 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("ltpy_iterator_object");
56
57 /* Internal helper function to extract gdb.Symtab from a gdb.LineTable
58 object. */
59
60 static PyObject *
61 get_symtab (PyObject *linetable)
62 {
63 linetable_object *lt = (linetable_object *) linetable;
64
65 return lt->symtab;
66 }
67
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)
78
79
80 /* Helper function to create a line table object that wraps a
81 gdb.Symtab object. */
82
83 PyObject *
84 symtab_to_linetable_object (PyObject *symtab)
85 {
86 linetable_object *ltable;
87
88 ltable = PyObject_New (linetable_object, &linetable_object_type);
89 if (ltable != NULL)
90 {
91 ltable->symtab = symtab;
92 Py_INCREF (symtab);
93 }
94 return (PyObject *) ltable;
95 }
96
97 /* Internal helper function to build a line table object from a line
98 and an address. */
99
100 static PyObject *
101 build_linetable_entry (int line, CORE_ADDR address)
102 {
103 linetable_entry_object *obj;
104
105 obj = PyObject_New (linetable_entry_object,
106 &linetable_entry_object_type);
107 if (obj != NULL)
108 {
109 obj->line = line;
110 obj->pc = address;
111 }
112
113 return (PyObject *) obj;
114 }
115
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. */
121
122 static PyObject *
123 build_line_table_tuple_from_pcs (int line, const std::vector<CORE_ADDR> &pcs)
124 {
125 int i;
126
127 if (pcs.size () < 1)
128 Py_RETURN_NONE;
129
130 gdbpy_ref<> tuple (PyTuple_New (pcs.size ()));
131
132 if (tuple == NULL)
133 return NULL;
134
135 for (i = 0; i < pcs.size (); ++i)
136 {
137 CORE_ADDR pc = pcs[i];
138 gdbpy_ref<> obj (build_linetable_entry (line, pc));
139
140 if (obj == NULL)
141 return NULL;
142 else if (PyTuple_SetItem (tuple.get (), i, obj.release ()) != 0)
143 return NULL;
144 }
145
146 return tuple.release ();
147 }
148
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. */
152
153 static PyObject *
154 ltpy_get_pcs_for_line (PyObject *self, PyObject *args)
155 {
156 struct symtab *symtab;
157 gdb_py_longest py_line;
158 const linetable_entry *best_entry = nullptr;
159 std::vector<CORE_ADDR> pcs;
160
161 LTPY_REQUIRE_VALID (self, symtab);
162
163 if (! PyArg_ParseTuple (args, GDB_PY_LL_ARG, &py_line))
164 return NULL;
165
166 try
167 {
168 pcs = find_pcs_for_symtab_line (symtab, py_line, &best_entry);
169 }
170 catch (const gdb_exception &except)
171 {
172 return gdbpy_handle_gdb_exception (nullptr, except);
173 }
174
175 return build_line_table_tuple_from_pcs (py_line, pcs);
176 }
177
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. */
181
182 static PyObject *
183 ltpy_has_line (PyObject *self, PyObject *args)
184 {
185 struct symtab *symtab;
186 gdb_py_longest py_line;
187 int index;
188
189 LTPY_REQUIRE_VALID (self, symtab);
190
191 if (! PyArg_ParseTuple (args, GDB_PY_LL_ARG, &py_line))
192 return NULL;
193
194 if (symtab->linetable () == NULL)
195 {
196 PyErr_SetString (PyExc_RuntimeError,
197 _("Linetable information not found in symbol table"));
198 return NULL;
199 }
200
201 for (index = 0; index < symtab->linetable ()->nitems; index++)
202 {
203 const linetable_entry *item = &(symtab->linetable ()->item[index]);
204 if (item->line == py_line)
205 Py_RETURN_TRUE;
206 }
207
208 Py_RETURN_FALSE;
209 }
210
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. */
215
216 static PyObject *
217 ltpy_get_all_source_lines (PyObject *self, PyObject *args)
218 {
219 struct symtab *symtab;
220 Py_ssize_t index;
221
222 LTPY_REQUIRE_VALID (self, symtab);
223
224 if (symtab->linetable () == NULL)
225 {
226 PyErr_SetString (PyExc_RuntimeError,
227 _("Linetable information not found in symbol table"));
228 return NULL;
229 }
230
231 gdbpy_ref<> source_dict (PyDict_New ());
232 if (source_dict == NULL)
233 return NULL;
234
235 for (index = 0; index < symtab->linetable ()->nitems; index++)
236 {
237 const linetable_entry *item = &(symtab->linetable ()->item[index]);
238
239 /* 0 is used to signify end of line table information. Do not
240 include in the source set. */
241 if (item->line > 0)
242 {
243 gdbpy_ref<> line = gdb_py_object_from_longest (item->line);
244
245 if (line == NULL)
246 return NULL;
247
248 if (PyDict_SetItem (source_dict.get (), line.get (), Py_None) == -1)
249 return NULL;
250 }
251 }
252
253 return PyDict_Keys (source_dict.get ());
254 }
255
256 /* Implementation of gdb.LineTable.is_valid (self) -> Boolean.
257 Returns True if this line table object still exists in GDB. */
258
259 static PyObject *
260 ltpy_is_valid (PyObject *self, PyObject *args)
261 {
262 struct symtab *symtab = NULL;
263
264 symtab = symtab_object_to_symtab (get_symtab (self));
265
266 if (symtab == NULL)
267 Py_RETURN_FALSE;
268
269 Py_RETURN_TRUE;
270 }
271
272 /* Deconstructor for the line table object. Decrement the reference
273 to the symbol table object before calling the default free. */
274
275 static void
276 ltpy_dealloc (PyObject *self)
277 {
278 linetable_object *obj = (linetable_object *) self;
279
280 Py_DECREF (obj->symtab);
281 Py_TYPE (self)->tp_free (self);
282 }
283
284 /* Initialize LineTable, LineTableEntry and LineTableIterator
285 objects. */
286
287 static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
288 gdbpy_initialize_linetable (void)
289 {
290 if (gdbpy_type_ready (&linetable_object_type) < 0)
291 return -1;
292 if (gdbpy_type_ready (&linetable_entry_object_type) < 0)
293 return -1;
294 if (gdbpy_type_ready (&ltpy_iterator_object_type) < 0)
295 return -1;
296
297 return 0;
298 }
299
300 /* LineTable entry object get functions. */
301
302 /* Implementation of gdb.LineTableEntry.line (self) -> Long. Returns
303 a long integer associated with the line table entry. */
304
305 static PyObject *
306 ltpy_entry_get_line (PyObject *self, void *closure)
307 {
308 linetable_entry_object *obj = (linetable_entry_object *) self;
309
310 return gdb_py_object_from_longest (obj->line).release ();
311 }
312
313 /* Implementation of gdb.LineTableEntry.pc (self) -> Long. Returns a
314 a long integer associated with the PC of the line table entry. */
315
316 static PyObject *
317 ltpy_entry_get_pc (PyObject *self, void *closure)
318 {
319 linetable_entry_object *obj = (linetable_entry_object *) self;
320
321 return gdb_py_object_from_ulongest (obj->pc).release ();
322 }
323
324 /* LineTable iterator functions. */
325
326 /* Return a new line table iterator. */
327
328 static PyObject *
329 ltpy_iter (PyObject *self)
330 {
331 ltpy_iterator_object *ltpy_iter_obj;
332 struct symtab *symtab = NULL;
333
334 LTPY_REQUIRE_VALID (self, symtab);
335
336 ltpy_iter_obj = PyObject_New (ltpy_iterator_object,
337 &ltpy_iterator_object_type);
338 if (ltpy_iter_obj == NULL)
339 return NULL;
340
341 ltpy_iter_obj->current_index = 0;
342 ltpy_iter_obj->source = self;
343
344 Py_INCREF (self);
345 return (PyObject *) ltpy_iter_obj;
346 }
347
348 static void
349 ltpy_iterator_dealloc (PyObject *obj)
350 {
351 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) obj;
352
353 Py_DECREF (iter_obj->source);
354 Py_TYPE (obj)->tp_free (obj);
355 }
356
357 /* Return a reference to the line table iterator. */
358
359 static PyObject *
360 ltpy_iterator (PyObject *self)
361 {
362 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
363 struct symtab *symtab;
364
365 LTPY_REQUIRE_VALID (iter_obj->source, symtab);
366
367 Py_INCREF (self);
368 return self;
369 }
370
371 /* Return the next line table entry in the iteration through the line
372 table data structure. */
373
374 static PyObject *
375 ltpy_iternext (PyObject *self)
376 {
377 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
378 struct symtab *symtab;
379 PyObject *obj;
380
381 LTPY_REQUIRE_VALID (iter_obj->source, symtab);
382
383 if (symtab->linetable () == nullptr
384 || iter_obj->current_index >= symtab->linetable ()->nitems)
385 {
386 PyErr_SetNone (PyExc_StopIteration);
387 return NULL;
388 }
389
390 const linetable_entry *item
391 = &(symtab->linetable ()->item[iter_obj->current_index]);
392
393 /* Skip over internal entries such as 0. 0 signifies the end of
394 line table data and is not useful to the API user. */
395 while (item->line < 1)
396 {
397 iter_obj->current_index++;
398
399 /* Exit if the internal value is the last item in the line table. */
400 if (iter_obj->current_index >= symtab->linetable ()->nitems)
401 {
402 PyErr_SetNone (PyExc_StopIteration);
403 return NULL;
404 }
405 item = &(symtab->linetable ()->item[iter_obj->current_index]);
406 }
407
408 struct objfile *objfile = symtab->compunit ()->objfile ();
409 obj = build_linetable_entry (item->line, item->pc (objfile));
410 iter_obj->current_index++;
411
412 return obj;
413 }
414
415 /* Implementation of gdb.LineTableIterator.is_valid (self) -> Boolean.
416 Returns True if this line table iterator object still exists in
417 GDB. */
418
419 static PyObject *
420 ltpy_iter_is_valid (PyObject *self, PyObject *args)
421 {
422 struct symtab *symtab = NULL;
423 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
424
425 symtab = symtab_object_to_symtab (get_symtab (iter_obj->source));
426
427 if (symtab == NULL)
428 Py_RETURN_FALSE;
429
430 Py_RETURN_TRUE;
431 }
432
433 GDBPY_INITIALIZE_FILE (gdbpy_initialize_linetable);
434
435 \f
436
437 static PyMethodDef linetable_object_methods[] = {
438 { "line", ltpy_get_pcs_for_line, METH_VARARGS,
439 "line (lineno) -> Tuple\n\
440 Return executable locations for a given source line." },
441 { "has_line", ltpy_has_line, METH_VARARGS,
442 "has_line (lineno) -> Boolean\n\
443 Return TRUE if this line has executable information, FALSE if not." },
444 { "source_lines", ltpy_get_all_source_lines, METH_NOARGS,
445 "source_lines () -> List\n\
446 Return a list of all executable source lines." },
447 { "is_valid", ltpy_is_valid, METH_NOARGS,
448 "is_valid () -> Boolean.\n\
449 Return True if this LineTable is valid, False if not." },
450 {NULL} /* Sentinel */
451 };
452
453 PyTypeObject linetable_object_type = {
454 PyVarObject_HEAD_INIT (NULL, 0)
455 "gdb.LineTable", /*tp_name*/
456 sizeof (linetable_object), /*tp_basicsize*/
457 0, /*tp_itemsize*/
458 ltpy_dealloc, /*tp_dealloc*/
459 0, /*tp_print*/
460 0, /*tp_getattr*/
461 0, /*tp_setattr*/
462 0, /*tp_compare*/
463 0, /*tp_repr*/
464 0, /*tp_as_number*/
465 0, /*tp_as_sequence*/
466 0, /*tp_as_mapping*/
467 0, /*tp_hash */
468 0, /*tp_call*/
469 0, /*tp_str*/
470 0, /*tp_getattro*/
471 0, /*tp_setattro*/
472 0, /*tp_as_buffer*/
473 Py_TPFLAGS_DEFAULT, /*tp_flags*/
474 "GDB line table object", /* tp_doc */
475 0, /* tp_traverse */
476 0, /* tp_clear */
477 0, /* tp_richcompare */
478 0, /* tp_weaklistoffset */
479 ltpy_iter, /* tp_iter */
480 0, /* tp_iternext */
481 linetable_object_methods, /* tp_methods */
482 0, /* tp_members */
483 0, /* tp_getset */
484 0, /* tp_base */
485 0, /* tp_dict */
486 0, /* tp_descr_get */
487 0, /* tp_descr_set */
488 0, /* tp_dictoffset */
489 0, /* tp_init */
490 0, /* tp_alloc */
491 };
492
493 static PyMethodDef ltpy_iterator_methods[] = {
494 { "is_valid", ltpy_iter_is_valid, METH_NOARGS,
495 "is_valid () -> Boolean.\n\
496 Return True if this LineTable iterator is valid, False if not." },
497 {NULL} /* Sentinel */
498 };
499
500 PyTypeObject ltpy_iterator_object_type = {
501 PyVarObject_HEAD_INIT (NULL, 0)
502 "gdb.LineTableIterator", /*tp_name*/
503 sizeof (ltpy_iterator_object), /*tp_basicsize*/
504 0, /*tp_itemsize*/
505 ltpy_iterator_dealloc, /*tp_dealloc*/
506 0, /*tp_print*/
507 0, /*tp_getattr*/
508 0, /*tp_setattr*/
509 0, /*tp_compare*/
510 0, /*tp_repr*/
511 0, /*tp_as_number*/
512 0, /*tp_as_sequence*/
513 0, /*tp_as_mapping*/
514 0, /*tp_hash */
515 0, /*tp_call*/
516 0, /*tp_str*/
517 0, /*tp_getattro*/
518 0, /*tp_setattro*/
519 0, /*tp_as_buffer*/
520 Py_TPFLAGS_DEFAULT, /*tp_flags*/
521 "GDB line table iterator object", /*tp_doc */
522 0, /*tp_traverse */
523 0, /*tp_clear */
524 0, /*tp_richcompare */
525 0, /*tp_weaklistoffset */
526 ltpy_iterator, /*tp_iter */
527 ltpy_iternext, /*tp_iternext */
528 ltpy_iterator_methods /*tp_methods */
529 };
530
531
532 static gdb_PyGetSetDef linetable_entry_object_getset[] = {
533 { "line", ltpy_entry_get_line, NULL,
534 "The line number in the source file.", NULL },
535 { "pc", ltpy_entry_get_pc, NULL,
536 "The memory address for this line number.", NULL },
537 { NULL } /* Sentinel */
538 };
539
540 PyTypeObject linetable_entry_object_type = {
541 PyVarObject_HEAD_INIT (NULL, 0)
542 "gdb.LineTableEntry", /*tp_name*/
543 sizeof (linetable_entry_object), /*tp_basicsize*/
544 0, /*tp_itemsize*/
545 0, /*tp_dealloc*/
546 0, /*tp_print*/
547 0, /*tp_getattr*/
548 0, /*tp_setattr*/
549 0, /*tp_compare*/
550 0, /*tp_repr*/
551 0, /*tp_as_number*/
552 0, /*tp_as_sequence*/
553 0, /*tp_as_mapping*/
554 0, /*tp_hash */
555 0, /*tp_call*/
556 0, /*tp_str*/
557 0, /*tp_getattro*/
558 0, /*tp_setattro*/
559 0, /*tp_as_buffer*/
560 Py_TPFLAGS_DEFAULT, /*tp_flags*/
561 "GDB line table entry object", /* tp_doc */
562 0, /* tp_traverse */
563 0, /* tp_clear */
564 0, /* tp_richcompare */
565 0, /* tp_weaklistoffset */
566 0, /* tp_iter */
567 0, /* tp_iternext */
568 0, /* tp_methods */
569 0, /* tp_members */
570 linetable_entry_object_getset, /* tp_getset */
571 0, /* tp_base */
572 0, /* tp_dict */
573 0, /* tp_descr_get */
574 0, /* tp_descr_set */
575 0, /* tp_dictoffset */
576 0, /* tp_init */
577 0, /* tp_alloc */
578 };