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