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