gdb/python/py-linetable.c - gdb

Global variables defined

Data types defined

Functions defined

Macros defined

Source code

  1. /* Python interface to line tables.

  2.    Copyright (C) 2013-2015 Free Software Foundation, Inc.

  3.    This file is part of GDB.

  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 3 of the License, or
  7.    (at your option) any later version.

  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.

  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  14. #include "defs.h"
  15. #include "python-internal.h"

  16. typedef struct {
  17.   PyObject_HEAD
  18.   /* The line table source line.  */
  19.   int line;
  20.   /* The pc associated with the source line.  */
  21.   CORE_ADDR pc;
  22. } linetable_entry_object;

  23. static PyTypeObject linetable_entry_object_type
  24.     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("linetable_entry_object");

  25. typedef struct {
  26.   PyObject_HEAD
  27.   /* The symtab python object.  We store the Python object here as the
  28.      underlying symtab can become invalid, and we have to run validity
  29.      checks on it.  */
  30.   PyObject *symtab;
  31. } linetable_object;

  32. static PyTypeObject linetable_object_type
  33.     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("linetable_object");

  34. typedef struct {
  35.   PyObject_HEAD
  36.   /* The current entry in the line table for the iterator  */
  37.   int current_index;
  38.   /* Pointer back to the original source line table object.  Needed to
  39.      check if the line table is still valid, and has not been invalidated
  40.      when an object file has been freed.  */
  41.   PyObject *source;
  42. } ltpy_iterator_object;

  43. static PyTypeObject ltpy_iterator_object_type
  44.     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("ltpy_iterator_object");

  45. /* Internal helper function to extract gdb.Symtab from a gdb.Linetable
  46.    object.  */

  47. static PyObject *
  48. get_symtab (PyObject *linetable)
  49. {
  50.   linetable_object *lt = (linetable_object *) linetable;

  51.   return lt->symtab;
  52. }

  53. #define LTPY_REQUIRE_VALID(lt_obj, symtab)                                \
  54.   do {                                                                        \
  55.     symtab = symtab_object_to_symtab (get_symtab (lt_obj));                \
  56.     if (symtab == NULL)                                                        \
  57.       {                                                                        \
  58.           PyErr_SetString (PyExc_RuntimeError,                                \
  59.                            _("Symbol Table in line table is invalid."));\
  60.           return NULL;                                                        \
  61.         }                                                                \
  62.   } while (0)


  63. /* Helper function to create a line table object that wraps a
  64.    gdb.Symtab object.  */

  65. PyObject *
  66. symtab_to_linetable_object (PyObject *symtab)
  67. {
  68.   linetable_object *ltable;

  69.   ltable = PyObject_New (linetable_object, &linetable_object_type);
  70.   if (ltable != NULL)
  71.     {
  72.       ltable->symtab = symtab;
  73.       Py_INCREF (symtab);
  74.     }
  75.   return (PyObject *) ltable;
  76. }

  77. /* Internal helper function to build a line table object from a line
  78.    and an address.  */

  79. static PyObject *
  80. build_linetable_entry (int line, CORE_ADDR address)
  81. {
  82.   linetable_entry_object *obj;

  83.   obj = PyObject_New (linetable_entry_object,
  84.                       &linetable_entry_object_type);
  85.   if (obj != NULL)
  86.     {
  87.       obj->line = line;
  88.       obj->pc = address;
  89.     }

  90.   return (PyObject *) obj;
  91. }

  92. /* Internal helper function to build a Python Tuple from a GDB Vector.
  93.    A line table entry can have multiple PCs for a given source line.
  94.    Construct a Tuple of all entries for the given source line, LINE
  95.    from the line table VEC.  Construct one line table entry object per
  96.    address.  */

  97. static PyObject *
  98. build_line_table_tuple_from_pcs (int line, VEC (CORE_ADDR) *vec)
  99. {
  100.   int vec_len = 0;
  101.   PyObject *tuple;
  102.   CORE_ADDR pc;
  103.   int i;

  104.   vec_len = VEC_length (CORE_ADDR, vec);
  105.   if (vec_len < 1)
  106.     Py_RETURN_NONE;

  107.   tuple = PyTuple_New (vec_len);

  108.   if (tuple == NULL)
  109.     return NULL;

  110.   for (i = 0; VEC_iterate (CORE_ADDR, vec, i, pc); ++i)
  111.     {
  112.       PyObject *obj = build_linetable_entry (line, pc);

  113.       if (obj == NULL)
  114.         {
  115.           Py_DECREF (tuple);
  116.           tuple = NULL;
  117.           break;
  118.         }
  119.       else if (PyTuple_SetItem (tuple, i, obj) != 0)
  120.         {
  121.           Py_DECREF (obj);
  122.           Py_DECREF (tuple);
  123.           tuple = NULL;
  124.           break;
  125.         }
  126.     }

  127.   return tuple;
  128. }

  129. /* Implementation of gdb.LineTable.line (self) -> Tuple.  Returns a
  130.    tuple of LineTableEntry objects associated with this line from the
  131.    in the line table.  */

  132. static PyObject *
  133. ltpy_get_pcs_for_line (PyObject *self, PyObject *args)
  134. {
  135.   struct symtab *symtab;
  136.   gdb_py_longest py_line;
  137.   struct linetable_entry *best_entry = NULL;
  138.   linetable_entry_object *result;
  139.   VEC (CORE_ADDR) *pcs = NULL;
  140.   PyObject *tuple;
  141.   volatile struct gdb_exception except;

  142.   LTPY_REQUIRE_VALID (self, symtab);

  143.   if (! PyArg_ParseTuple (args, GDB_PY_LL_ARG, &py_line))
  144.     return NULL;

  145.   TRY_CATCH (except, RETURN_MASK_ALL)
  146.     {
  147.       pcs = find_pcs_for_symtab_line (symtab, py_line, &best_entry);
  148.     }
  149.   GDB_PY_HANDLE_EXCEPTION (except);

  150.   tuple = build_line_table_tuple_from_pcs (py_line, pcs);
  151.   VEC_free (CORE_ADDR, pcs);

  152.   return tuple;
  153. }

  154. /* Implementation of gdb.LineTable.has_line (self, line) -> Boolean.
  155.    Returns a Python Boolean indicating whether a source line has any
  156.    line table entries corresponding to it.  */

  157. static PyObject *
  158. ltpy_has_line (PyObject *self, PyObject *args)
  159. {
  160.   struct symtab *symtab;
  161.   gdb_py_longest py_line;
  162.   int index;

  163.   LTPY_REQUIRE_VALID (self, symtab);

  164.   if (! PyArg_ParseTuple (args, GDB_PY_LL_ARG, &py_line))
  165.     return NULL;

  166.   if (SYMTAB_LINETABLE (symtab) == NULL)
  167.     {
  168.       PyErr_SetString (PyExc_RuntimeError,
  169.                        _("Linetable information not found in symbol table"));
  170.       return NULL;
  171.     }

  172.   for (index = 0; index < SYMTAB_LINETABLE (symtab)->nitems; index++)
  173.     {
  174.       struct linetable_entry *item = &(SYMTAB_LINETABLE (symtab)->item[index]);
  175.       if (item->line == py_line)
  176.           Py_RETURN_TRUE;
  177.     }

  178.   Py_RETURN_FALSE;
  179. }

  180. /* Implementation of gdb.LineTable.source_lines (self) -> FrozenSet.
  181.    Returns a Python FrozenSet that contains source line entries in the
  182.    line table.  This function will just return the source lines
  183.    without corresponding addresses.  */

  184. static PyObject *
  185. ltpy_get_all_source_lines (PyObject *self, PyObject *args)
  186. {
  187.   struct symtab *symtab;
  188.   Py_ssize_t index;
  189.   PyObject *source_list, *source_dict, *line;
  190.   struct linetable_entry *item;
  191.   Py_ssize_t list_size;

  192.   LTPY_REQUIRE_VALID (self, symtab);

  193.   if (SYMTAB_LINETABLE (symtab) == NULL)
  194.     {
  195.       PyErr_SetString (PyExc_RuntimeError,
  196.                        _("Linetable information not found in symbol table"));
  197.       return NULL;
  198.     }

  199.   source_dict = PyDict_New ();
  200.   if (source_dict == NULL)
  201.     return NULL;

  202.   for (index = 0; index < SYMTAB_LINETABLE (symtab)->nitems; index++)
  203.     {
  204.       item = &(SYMTAB_LINETABLE (symtab)->item[index]);

  205.       /* 0 is used to signify end of line table information.  Do not
  206.          include in the source set. */
  207.       if (item->line > 0)
  208.         {
  209.           line = gdb_py_object_from_longest (item->line);

  210.           if (line == NULL)
  211.             {
  212.               Py_DECREF (source_dict);
  213.               return NULL;
  214.             }

  215.           if (PyDict_SetItem (source_dict, line, Py_None) == -1)
  216.             {
  217.               Py_DECREF (line);
  218.               Py_DECREF (source_dict);
  219.               return NULL;
  220.             }

  221.           Py_DECREF (line);
  222.         }
  223.     }


  224.   source_list = PyDict_Keys (source_dict);
  225.   Py_DECREF (source_dict);

  226.   return source_list;
  227. }

  228. /* Implementation of gdb.Linetable.is_valid (self) -> Boolean.
  229.    Returns True if this line table object still exists in GDB.  */

  230. static PyObject *
  231. ltpy_is_valid (PyObject *self, PyObject *args)
  232. {
  233.   struct symtab *symtab = NULL;
  234.   linetable_object *obj = (linetable_object *) self;

  235.   symtab = symtab_object_to_symtab (get_symtab (self));

  236.   if (symtab == NULL)
  237.     Py_RETURN_FALSE;

  238.   Py_RETURN_TRUE;
  239. }

  240. /* Deconstructor for the line table object.  Decrement the reference
  241.    to the symbol table object before calling the default free.  */

  242. static void
  243. ltpy_dealloc (PyObject *self)
  244. {
  245.   linetable_object *obj = (linetable_object *) self;

  246.   Py_DECREF (obj->symtab);
  247.   Py_TYPE (self)->tp_free (self);
  248. }

  249. /* Initialize LineTable, LineTableEntry and LineTableIterator
  250.    objects.  */

  251. int
  252. gdbpy_initialize_linetable (void)
  253. {
  254.   if (PyType_Ready (&linetable_object_type) < 0)
  255.     return -1;
  256.   if (PyType_Ready (&linetable_entry_object_type) < 0)
  257.     return -1;
  258.   if (PyType_Ready (&ltpy_iterator_object_type) < 0)
  259.     return -1;

  260.   Py_INCREF (&linetable_object_type);
  261.   Py_INCREF (&linetable_entry_object_type);
  262.   Py_INCREF (&ltpy_iterator_object_type);

  263.   if (gdb_pymodule_addobject (gdb_module, "LineTable",
  264.                               (PyObject *) &linetable_object_type) < 0)
  265.     return -1;

  266.   if (gdb_pymodule_addobject (gdb_module, "LineTableEntry",
  267.                               (PyObject *) &linetable_entry_object_type) < 0)
  268.     return -1;

  269.   if (gdb_pymodule_addobject (gdb_module, "LineTableIterator",
  270.                               (PyObject *) &ltpy_iterator_object_type) < 0)
  271.     return -1;

  272.   return 0;
  273. }

  274. /* Linetable entry object get functions.  */

  275. /* Implementation of gdb.LineTableEntry.line (self) -> Long.  Returns
  276.    a long integer associated with the line table entry.  */

  277. static PyObject *
  278. ltpy_entry_get_line (PyObject *self, void *closure)
  279. {
  280.   linetable_entry_object *obj = (linetable_entry_object *) self;

  281.   return gdb_py_object_from_longest (obj->line);
  282. }

  283. /* Implementation of gdb.LineTableEntry.pc (self) -> Long.  Returns a
  284.    a long integer associated with the PC of the line table entry.  */

  285. static PyObject *
  286. ltpy_entry_get_pc (PyObject *self, void *closure)
  287. {
  288.   linetable_entry_object *obj = (linetable_entry_object *) self;

  289.   return  gdb_py_object_from_longest (obj->pc);
  290. }

  291. /* Linetable iterator functions.  */

  292. /* Return a new line table iterator.  */

  293. static PyObject *
  294. ltpy_iter (PyObject *self)
  295. {
  296.   ltpy_iterator_object *ltpy_iter_obj;
  297.   struct symtab *symtab = NULL;

  298.   LTPY_REQUIRE_VALID (self, symtab);

  299.   ltpy_iter_obj = PyObject_New (ltpy_iterator_object,
  300.                                 &ltpy_iterator_object_type);
  301.   if (ltpy_iter_obj == NULL)
  302.     return NULL;

  303.   ltpy_iter_obj->current_index = 0;
  304.   ltpy_iter_obj->source = self;

  305.   Py_INCREF (self);
  306.   return (PyObject *) ltpy_iter_obj;
  307. }

  308. static void
  309. ltpy_iterator_dealloc (PyObject *obj)
  310. {
  311.   ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) obj;

  312.   Py_DECREF (iter_obj->source);
  313. }

  314. /* Return a reference to the line table iterator.  */

  315. static PyObject *
  316. ltpy_iterator (PyObject *self)
  317. {
  318.   ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
  319.   struct symtab *symtab;

  320.   LTPY_REQUIRE_VALID (iter_obj->source, symtab);

  321.   Py_INCREF (self);
  322.   return self;
  323. }

  324. /* Return the next line table entry in the iteration through the line
  325.    table data structure.  */

  326. static PyObject *
  327. ltpy_iternext (PyObject *self)
  328. {
  329.   ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
  330.   struct symtab *symtab;
  331.   int index;
  332.   PyObject *obj;
  333.   struct linetable_entry *item;

  334.   LTPY_REQUIRE_VALID (iter_obj->source, symtab);

  335.   if (iter_obj->current_index >= SYMTAB_LINETABLE (symtab)->nitems)
  336.     goto stop_iteration;

  337.   item = &(SYMTAB_LINETABLE (symtab)->item[iter_obj->current_index]);

  338.   /* Skip over internal entries such as 0.  0 signifies the end of
  339.      line table data and is not useful to the API user.  */
  340.   while (item->line < 1)
  341.     {
  342.       iter_obj->current_index++;

  343.       /* Exit if the internal value is the last item in the line table.  */
  344.       if (iter_obj->current_index >= SYMTAB_LINETABLE (symtab)->nitems)
  345.         goto stop_iteration;
  346.       item = &(SYMTAB_LINETABLE (symtab)->item[iter_obj->current_index]);
  347.     }

  348.   obj = build_linetable_entry (item->line, item->pc);
  349.   iter_obj->current_index++;

  350.   return obj;

  351. stop_iteration:
  352.   PyErr_SetNone (PyExc_StopIteration);
  353.   return NULL;
  354. }

  355. /* Implementation of gdb.LinetableIterator.is_valid (self) -> Boolean.
  356.    Returns True if this line table iterator object still exists in
  357.    GDB.  */

  358. static PyObject *
  359. ltpy_iter_is_valid (PyObject *self, PyObject *args)
  360. {
  361.   struct symtab *symtab = NULL;
  362.   ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;

  363.   symtab = symtab_object_to_symtab (get_symtab (iter_obj->source));

  364.   if (symtab == NULL)
  365.     Py_RETURN_FALSE;

  366.   Py_RETURN_TRUE;
  367. }



  368. static PyMethodDef linetable_object_methods[] = {
  369.   { "line", ltpy_get_pcs_for_line, METH_VARARGS,
  370.     "line (lineno) -> Tuple\n\
  371. Return executable locations for a given source line." },
  372.   { "has_line", ltpy_has_line, METH_VARARGS,
  373.     "has_line (lineno) -> Boolean\n\
  374. Return TRUE if this line has executable information, FALSE if not." },
  375.   { "source_lines", ltpy_get_all_source_lines, METH_NOARGS,
  376.     "source_lines () -> FrozenSet\n\
  377. Return a frozen set of all executable source lines." },
  378.   { "is_valid", ltpy_is_valid, METH_NOARGS,
  379.     "is_valid () -> Boolean.\n\
  380. Return True if this Linetable is valid, False if not." },
  381.   {NULL/* Sentinel */
  382. };

  383. static PyTypeObject linetable_object_type = {
  384.   PyVarObject_HEAD_INIT (NULL, 0)
  385.   "gdb.LineTable",                  /*tp_name*/
  386.   sizeof (linetable_object),          /*tp_basicsize*/
  387.   0,                                  /*tp_itemsize*/
  388.   ltpy_dealloc,                   /*tp_dealloc*/
  389.   0,                                  /*tp_print*/
  390.   0,                                  /*tp_getattr*/
  391.   0,                                  /*tp_setattr*/
  392.   0,                                  /*tp_compare*/
  393.   0,                                  /*tp_repr*/
  394.   0,                                  /*tp_as_number*/
  395.   0,                                  /*tp_as_sequence*/
  396.   0,                                  /*tp_as_mapping*/
  397.   0,                                  /*tp_hash */
  398.   0,                                  /*tp_call*/
  399.   0,                                  /*tp_str*/
  400.   0,                                  /*tp_getattro*/
  401.   0,                                  /*tp_setattro*/
  402.   0,                                  /*tp_as_buffer*/
  403.   Py_TPFLAGS_DEFAULT,             /*tp_flags*/
  404.   "GDB line table object",          /* tp_doc */
  405.   0,                                  /* tp_traverse */
  406.   0,                                  /* tp_clear */
  407.   0,                                  /* tp_richcompare */
  408.   0,                                  /* tp_weaklistoffset */
  409.   ltpy_iter,                          /* tp_iter */
  410.   0,                                  /* tp_iternext */
  411.   linetable_object_methods,          /* tp_methods */
  412.   0,                                  /* tp_members */
  413.   0,                                  /* tp_getset */
  414.   0,                                  /* tp_base */
  415.   0,                                  /* tp_dict */
  416.   0,                                  /* tp_descr_get */
  417.   0,                                  /* tp_descr_set */
  418.   0,                                  /* tp_dictoffset */
  419.   0,                              /* tp_init */
  420.   0,                                  /* tp_alloc */
  421. };

  422. static PyMethodDef ltpy_iterator_methods[] = {
  423.   { "is_valid", ltpy_iter_is_valid, METH_NOARGS,
  424.     "is_valid () -> Boolean.\n\
  425. Return True if this Linetable iterator is valid, False if not." },
  426.   {NULL/* Sentinel */
  427. };

  428. static PyTypeObject ltpy_iterator_object_type = {
  429.   PyVarObject_HEAD_INIT (NULL, 0)
  430.   "gdb.LineTableIterator",                  /*tp_name*/
  431.   sizeof (ltpy_iterator_object),  /*tp_basicsize*/
  432.   0,                                  /*tp_itemsize*/
  433.   ltpy_iterator_dealloc,          /*tp_dealloc*/
  434.   0,                                  /*tp_print*/
  435.   0,                                  /*tp_getattr*/
  436.   0,                                  /*tp_setattr*/
  437.   0,                                  /*tp_compare*/
  438.   0,                                  /*tp_repr*/
  439.   0,                                  /*tp_as_number*/
  440.   0,                                  /*tp_as_sequence*/
  441.   0,                                  /*tp_as_mapping*/
  442.   0,                                  /*tp_hash */
  443.   0,                                  /*tp_call*/
  444.   0,                                  /*tp_str*/
  445.   0,                                  /*tp_getattro*/
  446.   0,                                  /*tp_setattro*/
  447.   0,                                  /*tp_as_buffer*/
  448.   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER/*tp_flags*/
  449.   "GDB line table iterator object",              /*tp_doc */
  450.   0,                                  /*tp_traverse */
  451.   0,                                  /*tp_clear */
  452.   0,                                  /*tp_richcompare */
  453.   0,                                  /*tp_weaklistoffset */
  454.   ltpy_iterator,                  /*tp_iter */
  455.   ltpy_iternext,                  /*tp_iternext */
  456.   ltpy_iterator_methods           /*tp_methods */
  457. };


  458. static PyGetSetDef linetable_entry_object_getset[] = {
  459.   { "line", ltpy_entry_get_line, NULL,
  460.     "The line number in the source file.", NULL },
  461.   { "pc", ltpy_entry_get_pc, NULL,
  462.     "The memory address for this line number.", NULL },
  463.   { NULL/* Sentinel */
  464. };

  465. static PyTypeObject linetable_entry_object_type = {
  466.   PyVarObject_HEAD_INIT (NULL, 0)
  467.   "gdb.LineTableEntry",                  /*tp_name*/
  468.   sizeof (linetable_entry_object), /*tp_basicsize*/
  469.   0,                                  /*tp_itemsize*/
  470.   0,                              /*tp_dealloc*/
  471.   0,                                  /*tp_print*/
  472.   0,                                  /*tp_getattr*/
  473.   0,                                  /*tp_setattr*/
  474.   0,                                  /*tp_compare*/
  475.   0,                                  /*tp_repr*/
  476.   0,                                  /*tp_as_number*/
  477.   0,                                  /*tp_as_sequence*/
  478.   0,                                  /*tp_as_mapping*/
  479.   0,                                  /*tp_hash */
  480.   0,                                  /*tp_call*/
  481.   0,                                  /*tp_str*/
  482.   0,                                  /*tp_getattro*/
  483.   0,                                  /*tp_setattro*/
  484.   0,                                  /*tp_as_buffer*/
  485.   Py_TPFLAGS_DEFAULT,             /*tp_flags*/
  486.   "GDB line table entry object"/* tp_doc */
  487.   0,                                  /* tp_traverse */
  488.   0,                                  /* tp_clear */
  489.   0,                                  /* tp_richcompare */
  490.   0,                                  /* tp_weaklistoffset */
  491.   0,                                  /* tp_iter */
  492.   0,                                  /* tp_iternext */
  493.   0,                              /* tp_methods */
  494.   0,                                  /* tp_members */
  495.   linetable_entry_object_getset/* tp_getset */
  496.   0,                                  /* tp_base */
  497.   0,                                  /* tp_dict */
  498.   0,                                  /* tp_descr_get */
  499.   0,                                  /* tp_descr_set */
  500.   0,                                  /* tp_dictoffset */
  501.   0,                                  /* tp_init */
  502.   0,                                  /* tp_alloc */
  503. };