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