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