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