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