Home | History | Annotate | Line # | Download | only in python
py-linetable.c revision 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 static 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 static 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 static 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   volatile struct gdb_exception except;
    176 
    177   LTPY_REQUIRE_VALID (self, symtab);
    178 
    179   if (! PyArg_ParseTuple (args, GDB_PY_LL_ARG, &py_line))
    180     return NULL;
    181 
    182   TRY_CATCH (except, RETURN_MASK_ALL)
    183     {
    184       pcs = find_pcs_for_symtab_line (symtab, py_line, &best_entry);
    185     }
    186   GDB_PY_HANDLE_EXCEPTION (except);
    187 
    188   tuple = build_line_table_tuple_from_pcs (py_line, pcs);
    189   VEC_free (CORE_ADDR, pcs);
    190 
    191   return tuple;
    192 }
    193 
    194 /* Implementation of gdb.LineTable.has_line (self, line) -> Boolean.
    195    Returns a Python Boolean indicating whether a source line has any
    196    line table entries corresponding to it.  */
    197 
    198 static PyObject *
    199 ltpy_has_line (PyObject *self, PyObject *args)
    200 {
    201   struct symtab *symtab;
    202   gdb_py_longest py_line;
    203   int index;
    204 
    205   LTPY_REQUIRE_VALID (self, symtab);
    206 
    207   if (! PyArg_ParseTuple (args, GDB_PY_LL_ARG, &py_line))
    208     return NULL;
    209 
    210   if (SYMTAB_LINETABLE (symtab) == NULL)
    211     {
    212       PyErr_SetString (PyExc_RuntimeError,
    213 		       _("Linetable information not found in symbol table"));
    214       return NULL;
    215     }
    216 
    217   for (index = 0; index < SYMTAB_LINETABLE (symtab)->nitems; index++)
    218     {
    219       struct linetable_entry *item = &(SYMTAB_LINETABLE (symtab)->item[index]);
    220       if (item->line == py_line)
    221 	  Py_RETURN_TRUE;
    222     }
    223 
    224   Py_RETURN_FALSE;
    225 }
    226 
    227 /* Implementation of gdb.LineTable.source_lines (self) -> FrozenSet.
    228    Returns a Python FrozenSet that contains source line entries in the
    229    line table.  This function will just return the source lines
    230    without corresponding addresses.  */
    231 
    232 static PyObject *
    233 ltpy_get_all_source_lines (PyObject *self, PyObject *args)
    234 {
    235   struct symtab *symtab;
    236   Py_ssize_t index;
    237   PyObject *source_list, *source_dict, *line;
    238   struct linetable_entry *item;
    239   Py_ssize_t list_size;
    240 
    241   LTPY_REQUIRE_VALID (self, symtab);
    242 
    243   if (SYMTAB_LINETABLE (symtab) == NULL)
    244     {
    245       PyErr_SetString (PyExc_RuntimeError,
    246 		       _("Linetable information not found in symbol table"));
    247       return NULL;
    248     }
    249 
    250   source_dict = PyDict_New ();
    251   if (source_dict == NULL)
    252     return NULL;
    253 
    254   for (index = 0; index < SYMTAB_LINETABLE (symtab)->nitems; index++)
    255     {
    256       item = &(SYMTAB_LINETABLE (symtab)->item[index]);
    257 
    258       /* 0 is used to signify end of line table information.  Do not
    259 	 include in the source set. */
    260       if (item->line > 0)
    261 	{
    262 	  line = gdb_py_object_from_longest (item->line);
    263 
    264 	  if (line == NULL)
    265 	    {
    266 	      Py_DECREF (source_dict);
    267 	      return NULL;
    268 	    }
    269 
    270 	  if (PyDict_SetItem (source_dict, line, Py_None) == -1)
    271 	    {
    272 	      Py_DECREF (line);
    273 	      Py_DECREF (source_dict);
    274 	      return NULL;
    275 	    }
    276 
    277 	  Py_DECREF (line);
    278 	}
    279     }
    280 
    281 
    282   source_list = PyDict_Keys (source_dict);
    283   Py_DECREF (source_dict);
    284 
    285   return source_list;
    286 }
    287 
    288 /* Implementation of gdb.Linetable.is_valid (self) -> Boolean.
    289    Returns True if this line table object still exists in GDB.  */
    290 
    291 static PyObject *
    292 ltpy_is_valid (PyObject *self, PyObject *args)
    293 {
    294   struct symtab *symtab = NULL;
    295   linetable_object *obj = (linetable_object *) self;
    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   int index;
    428   PyObject *obj;
    429   struct linetable_entry *item;
    430 
    431   LTPY_REQUIRE_VALID (iter_obj->source, symtab);
    432 
    433   if (iter_obj->current_index >= SYMTAB_LINETABLE (symtab)->nitems)
    434     goto stop_iteration;
    435 
    436   item = &(SYMTAB_LINETABLE (symtab)->item[iter_obj->current_index]);
    437 
    438   /* Skip over internal entries such as 0.  0 signifies the end of
    439      line table data and is not useful to the API user.  */
    440   while (item->line < 1)
    441     {
    442       iter_obj->current_index++;
    443 
    444       /* Exit if the internal value is the last item in the line table.  */
    445       if (iter_obj->current_index >= SYMTAB_LINETABLE (symtab)->nitems)
    446 	goto stop_iteration;
    447       item = &(SYMTAB_LINETABLE (symtab)->item[iter_obj->current_index]);
    448     }
    449 
    450   obj = build_linetable_entry (item->line, item->pc);
    451   iter_obj->current_index++;
    452 
    453   return obj;
    454 
    455  stop_iteration:
    456   PyErr_SetNone (PyExc_StopIteration);
    457   return NULL;
    458 }
    459 
    460 /* Implementation of gdb.LinetableIterator.is_valid (self) -> Boolean.
    461    Returns True if this line table iterator object still exists in
    462    GDB.  */
    463 
    464 static PyObject *
    465 ltpy_iter_is_valid (PyObject *self, PyObject *args)
    466 {
    467   struct symtab *symtab = NULL;
    468   ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
    469 
    470   symtab = symtab_object_to_symtab (get_symtab (iter_obj->source));
    471 
    472   if (symtab == NULL)
    473     Py_RETURN_FALSE;
    474 
    475   Py_RETURN_TRUE;
    476 }
    477 
    478 
    479 
    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