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