Home | History | Annotate | Line # | Download | only in python
py-linetable.c revision 1.1.1.1
      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 
    482 static PyMethodDef linetable_object_methods[] = {
    483   { "line", ltpy_get_pcs_for_line, METH_VARARGS,
    484     "line (lineno) -> Tuple\n\
    485 Return executable locations for a given source line." },
    486   { "has_line", ltpy_has_line, METH_VARARGS,
    487     "has_line (lineno) -> Boolean\n\
    488 Return TRUE if this line has executable information, FALSE if not." },
    489   { "source_lines", ltpy_get_all_source_lines, METH_NOARGS,
    490     "source_lines () -> FrozenSet\n\
    491 Return a frozen set of all executable source lines." },
    492   { "is_valid", ltpy_is_valid, METH_NOARGS,
    493     "is_valid () -> Boolean.\n\
    494 Return True if this Linetable is valid, False if not." },
    495   {NULL}  /* Sentinel */
    496 };
    497 
    498 static PyTypeObject linetable_object_type = {
    499   PyVarObject_HEAD_INIT (NULL, 0)
    500   "gdb.LineTable",	          /*tp_name*/
    501   sizeof (linetable_object),	  /*tp_basicsize*/
    502   0,				  /*tp_itemsize*/
    503   ltpy_dealloc,                   /*tp_dealloc*/
    504   0,				  /*tp_print*/
    505   0,				  /*tp_getattr*/
    506   0,				  /*tp_setattr*/
    507   0,				  /*tp_compare*/
    508   0,				  /*tp_repr*/
    509   0,				  /*tp_as_number*/
    510   0,				  /*tp_as_sequence*/
    511   0,				  /*tp_as_mapping*/
    512   0,				  /*tp_hash */
    513   0,				  /*tp_call*/
    514   0,				  /*tp_str*/
    515   0,				  /*tp_getattro*/
    516   0,				  /*tp_setattro*/
    517   0,				  /*tp_as_buffer*/
    518   Py_TPFLAGS_DEFAULT,             /*tp_flags*/
    519   "GDB line table object",	  /* tp_doc */
    520   0,				  /* tp_traverse */
    521   0,				  /* tp_clear */
    522   0,				  /* tp_richcompare */
    523   0,				  /* tp_weaklistoffset */
    524   ltpy_iter,			  /* tp_iter */
    525   0,				  /* tp_iternext */
    526   linetable_object_methods,	  /* tp_methods */
    527   0,				  /* tp_members */
    528   0,	                          /* tp_getset */
    529   0,				  /* tp_base */
    530   0,				  /* tp_dict */
    531   0,				  /* tp_descr_get */
    532   0,				  /* tp_descr_set */
    533   0,				  /* tp_dictoffset */
    534   0,    			  /* tp_init */
    535   0,				  /* tp_alloc */
    536 };
    537 
    538 static PyMethodDef ltpy_iterator_methods[] = {
    539   { "is_valid", ltpy_iter_is_valid, METH_NOARGS,
    540     "is_valid () -> Boolean.\n\
    541 Return True if this Linetable iterator is valid, False if not." },
    542   {NULL}  /* Sentinel */
    543 };
    544 
    545 static PyTypeObject ltpy_iterator_object_type = {
    546   PyVarObject_HEAD_INIT (NULL, 0)
    547   "gdb.LineTableIterator",		  /*tp_name*/
    548   sizeof (ltpy_iterator_object),  /*tp_basicsize*/
    549   0,				  /*tp_itemsize*/
    550   ltpy_iterator_dealloc,	  /*tp_dealloc*/
    551   0,				  /*tp_print*/
    552   0,				  /*tp_getattr*/
    553   0,				  /*tp_setattr*/
    554   0,				  /*tp_compare*/
    555   0,				  /*tp_repr*/
    556   0,				  /*tp_as_number*/
    557   0,				  /*tp_as_sequence*/
    558   0,				  /*tp_as_mapping*/
    559   0,				  /*tp_hash */
    560   0,				  /*tp_call*/
    561   0,				  /*tp_str*/
    562   0,				  /*tp_getattro*/
    563   0,				  /*tp_setattro*/
    564   0,				  /*tp_as_buffer*/
    565   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,  /*tp_flags*/
    566   "GDB line table iterator object",	      /*tp_doc */
    567   0,				  /*tp_traverse */
    568   0,				  /*tp_clear */
    569   0,				  /*tp_richcompare */
    570   0,				  /*tp_weaklistoffset */
    571   ltpy_iterator,                  /*tp_iter */
    572   ltpy_iternext,	          /*tp_iternext */
    573   ltpy_iterator_methods           /*tp_methods */
    574 };
    575 
    576 
    577 static PyGetSetDef linetable_entry_object_getset[] = {
    578   { "line", ltpy_entry_get_line, NULL,
    579     "The line number in the source file.", NULL },
    580   { "pc", ltpy_entry_get_pc, NULL,
    581     "The memory address for this line number.", NULL },
    582   { NULL }  /* Sentinel */
    583 };
    584 
    585 static PyTypeObject linetable_entry_object_type = {
    586   PyVarObject_HEAD_INIT (NULL, 0)
    587   "gdb.LineTableEntry",	          /*tp_name*/
    588   sizeof (linetable_entry_object), /*tp_basicsize*/
    589   0,				  /*tp_itemsize*/
    590   0,                              /*tp_dealloc*/
    591   0,				  /*tp_print*/
    592   0,				  /*tp_getattr*/
    593   0,				  /*tp_setattr*/
    594   0,				  /*tp_compare*/
    595   0,				  /*tp_repr*/
    596   0,				  /*tp_as_number*/
    597   0,				  /*tp_as_sequence*/
    598   0,				  /*tp_as_mapping*/
    599   0,				  /*tp_hash */
    600   0,				  /*tp_call*/
    601   0,				  /*tp_str*/
    602   0,				  /*tp_getattro*/
    603   0,				  /*tp_setattro*/
    604   0,				  /*tp_as_buffer*/
    605   Py_TPFLAGS_DEFAULT,             /*tp_flags*/
    606   "GDB line table entry object",  /* tp_doc */
    607   0,				  /* tp_traverse */
    608   0,				  /* tp_clear */
    609   0,				  /* tp_richcompare */
    610   0,				  /* tp_weaklistoffset */
    611   0,			          /* tp_iter */
    612   0,				  /* tp_iternext */
    613   0,                              /* tp_methods */
    614   0,				  /* tp_members */
    615   linetable_entry_object_getset,  /* tp_getset */
    616   0,				  /* tp_base */
    617   0,				  /* tp_dict */
    618   0,				  /* tp_descr_get */
    619   0,				  /* tp_descr_set */
    620   0,				  /* tp_dictoffset */
    621   0,	                          /* tp_init */
    622   0,				  /* tp_alloc */
    623 };
    624