[RFC - Python Scripting] New method gdb.Symtab.blocks_iterator - docs included

Siva Chandra sivachandra@google.com
Mon Apr 9 18:34:00 GMT 2012


Hello,

While the work on Objfile.symtabs (or Objfile.iterator) is pending, I
want to complete the API for the exploratory path Objfile => Symtabs
=> Blocks => Symbols.  This patch adds the missing link Symtabs =>
Blocks.  The method Symtab.blocks_iterator returns an iterator to
iterate over the scope blocks of a symtab.  The patch is attached and
the ChangeLog is as follows:

Code -
2012-04-09  Siva Chandra Reddy  <sivachandra@google.com>

        Add a new method gdb.Symtab.blocks_iterator to iterate
        over the scope blocks of a symbol table.
        * NEWS (Python scripting): Add entry about the new method.
        * python/py-symtab.c (symtab_blocks_iterator_object): New
        iterator type to iterate over the scope blocks of a symtab.
        (stpy_blocks_iterator): New function which implements the
        new method.
        (symtab_blocks_iterator_dealloc): New function which serves
        as the tp_dealloc function for symtab_blocks_iterator_object.
        (symtab_blocks_iterator_iter): New function which serves as
        the tp_iter function for symtab_blocks_iterator_object.
        (symtab_blocks_iterator_iternext): New function which serves as
        the tp_iternext function for symtab_blocks_iterator_object.
        (gdbpy_initialize_symtabs): Add initializations for the new
        iterator type.

Docs -
2012-04-09  Siva Chandra Reddy  <sivachandra@google.com>

        * gdb.texinfo (Symbol Tables In Python): Add description about
        the new method gdb.Symtab.blocks_iterator.

Tests -
2012-04-09  Siva Chandra Reddy  <sivachandra@google.com>

        * gdb.python/py-symtab.exp: Add tests to test the new method
        gdb.Symtab.blocks_iterator.

Thanks,
Siva Chandra
-------------- next part --------------
Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.506
diff -c -p -r1.506 NEWS
*** NEWS	2 Apr 2012 07:32:31 -0000	1.506
--- NEWS	9 Apr 2012 17:59:49 -0000
***************
*** 32,37 ****
--- 32,41 ----
    ** A new method 'referenced_value' on gdb.Value objects which can
       dereference pointer as well as C++ reference values.
  
+   ** A new method 'blocks_iterator' on gdb.Symtab objects which returns
+      an iterator to iterate over the scope blocks (gdb.Block objects) of
+      the symbol table (gdb.Symtab object).
+ 
  * GDBserver now supports stdio connections.
    E.g. (gdb) target remote | ssh myhost gdbserver - hello
  
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.939
diff -c -p -r1.939 gdb.texinfo
*** doc/gdb.texinfo	28 Mar 2012 21:31:46 -0000	1.939
--- doc/gdb.texinfo	9 Apr 2012 18:00:12 -0000
*************** if it is invalid at the time the method 
*** 24392,24397 ****
--- 24392,24403 ----
  @defun Symtab.fullname ()
  Return the symbol table's source absolute file name.
  @end defun
+ 
+ @defun Symtab.blocks_iterator ()
+ Return an iterator with which the user can iterate over the symbol
+ scope blocks (@code{gdb.Block} objects) of the symbol table
+ (@code{gdb.Symtab} object).  @xref{Blocks In Python}.
+ @end defun
  @end table
  
  @node Breakpoints In Python
Index: python/py-symtab.c
===================================================================
RCS file: /cvs/src/src/gdb/python/py-symtab.c,v
retrieving revision 1.8
diff -c -p -r1.8 py-symtab.c
*** python/py-symtab.c	4 Jan 2012 08:17:25 -0000	1.8
--- python/py-symtab.c	9 Apr 2012 18:00:13 -0000
***************
*** 20,25 ****
--- 20,26 ----
  #include "defs.h"
  #include "charset.h"
  #include "symtab.h"
+ #include "block.h"
  #include "source.h"
  #include "python-internal.h"
  #include "objfiles.h"
*************** typedef struct stpy_symtab_object {
*** 36,42 ****
--- 37,63 ----
    struct stpy_symtab_object *next;
  } symtab_object;
  
+ /* Iterator object type whose instance serves as an iterator over the
+    scope blocks in the underlying symtab of a symtab_object.  */
+ 
+ typedef struct stpy_blocks_iterator_object
+ {
+   PyObject_HEAD
+ 
+   /* A reference to the symtab_object from which this iterator was
+      created.  */
+ 
+   symtab_object *symtab_obj;
+ 
+   /* Index of the block object currently pointed to by the
+      iterator.  */
+ 
+   int iter_index;
+ } symtab_blocks_iterator_object;
+ 
  static PyTypeObject symtab_object_type;
+ static PyTypeObject symtab_blocks_iterator_object_type;
+ 
  static const struct objfile_data *stpy_objfile_data_key;
  
  /* Require a valid symbol table.  All access to symtab_object->symtab
*************** stpy_is_valid (PyObject *self, PyObject 
*** 153,158 ****
--- 174,205 ----
    Py_RETURN_TRUE;
  }
  
+ /* Implementation of gdb.Symtab.blocks_iterator (self) -> iterator.
+    Returns an iterator with which a user can iterator over the scope
+    blocks (gdb.Block objects) of the underlying symtab.  */
+ 
+ static PyObject *
+ stpy_blocks_iterator (PyObject *self, PyObject *args)
+ {
+   struct symtab *symtab = NULL;
+   symtab_blocks_iterator_object *iter = NULL;
+   symtab_object *symtab_obj = (symtab_object *) self;
+ 
+   STPY_REQUIRE_VALID (self, symtab);
+   /* The iterator holds a reference to the symtab_object.  */
+   Py_INCREF (self);
+ 
+   iter = PyObject_New (symtab_blocks_iterator_object,
+                        &symtab_blocks_iterator_object_type);
+   if (iter)
+     {
+       iter->symtab_obj = symtab_obj;
+       iter->iter_index = 0;
+     }
+ 
+   return (PyObject *) iter;
+ }
+ 
  static PyObject *
  salpy_str (PyObject *self)
  {
*************** stpy_dealloc (PyObject *obj)
*** 193,199 ****
    symtab->symtab = NULL;
  }
  
- 
  static PyObject *
  salpy_get_pc (PyObject *self, void *closure)
  {
--- 240,245 ----
*************** del_objfile_sal (struct objfile *objfile
*** 431,436 ****
--- 477,540 ----
      }
  }
  
+ /* The tp_dealloc function of symtab_blocks_iterator_object_type.  */
+ 
+ static void
+ symtab_blocks_iterator_dealloc (PyObject *self)
+ {
+   symtab_blocks_iterator_object *iter;
+ 
+   /* Decrement the reference to the symtab_object.  */
+   if (self)
+     {
+       iter = (symtab_blocks_iterator_object *) self;
+       Py_DECREF ((PyObject *) iter->symtab_obj);
+     }
+ }
+ 
+ /* The tp_iter function of symtab_blocks_iterator_object_type.  */
+ 
+ static PyObject *
+ symtab_blocks_iterator_iter (PyObject *self)
+ {
+   Py_INCREF (self);
+   return self;
+ }
+ 
+ /* The tp_iternext function of symtab_blocks_iterator_object_type.  */
+ 
+ static PyObject *
+ symtab_blocks_iterator_iternext (PyObject *self)
+ {
+   PyObject *block_object;
+   symtab_blocks_iterator_object *iter;
+   symtab_object *symtab_obj;
+   struct symtab *symtab;
+   struct block *block;
+ 
+   if (! self)
+     return NULL;
+ 
+   iter = (symtab_blocks_iterator_object *) self;
+   symtab_obj = iter->symtab_obj;
+   STPY_REQUIRE_VALID ((PyObject *) symtab_obj, symtab); 
+ 
+   if (iter->iter_index >= symtab->blockvector->nblocks)
+     return NULL;
+ 
+   block = symtab->blockvector->block[iter->iter_index];
+   block_object = block_to_block_object (block, symtab->objfile);
+   if (! block_object)
+     {
+       PyErr_SetString (PyExc_RuntimeError,
+                        _("Unable to get the next gdb.Block object."));
+       return NULL;
+     }
+ 
+   (iter->iter_index)++;
+   return block_object;
+ }
+ 
  void
  gdbpy_initialize_symtabs (void)
  {
*************** gdbpy_initialize_symtabs (void)
*** 442,447 ****
--- 546,555 ----
    if (PyType_Ready (&sal_object_type) < 0)
      return;
  
+   symtab_blocks_iterator_object_type.tp_new = PyType_GenericNew;
+   if (PyType_Ready (&symtab_blocks_iterator_object_type) < 0)
+     return;
+ 
    /* Register an objfile "free" callback so we can properly
       invalidate symbol tables, and symbol table and line data
       structures when an object file that is about to be
*************** gdbpy_initialize_symtabs (void)
*** 458,463 ****
--- 566,575 ----
    Py_INCREF (&sal_object_type);
    PyModule_AddObject (gdb_module, "Symtab_and_line",
  		      (PyObject *) &sal_object_type);
+ 
+   Py_INCREF (&symtab_blocks_iterator_object_type);
+   PyModule_AddObject (gdb_module, "BlockIterator",
+ 		      (PyObject *) &symtab_blocks_iterator_object_type);
  }
  
  

*************** Return true if this symbol table is vali
*** 477,482 ****
--- 589,598 ----
    { "fullname", stpy_fullname, METH_NOARGS,
      "fullname () -> String.\n\
  Return the symtab's full source filename." },
+   { "blocks_iterator", stpy_blocks_iterator, METH_NOARGS,
+     "blocks_iterator () -> iterator.\n\
+ Return an iterator over the scope blocks (gdb.Block objects) of the\n\
+ underlying Symtab." },
    {NULL}  /* Sentinel */
  };
  
*************** static PyTypeObject sal_object_type = {
*** 562,564 ****
--- 678,711 ----
    0,				  /*tp_members */
    sal_object_getset		  /*tp_getset */
  };
+ 
+ static PyTypeObject symtab_blocks_iterator_object_type = {
+   PyObject_HEAD_INIT (NULL)
+   0,                              /*ob_size*/
+   "gdb.BlockIterator",            /*tp_name*/
+   sizeof (symtab_blocks_iterator_object),  /*tp_basicsize*/
+   0,                              /*tp_itemsize*/
+   symtab_blocks_iterator_dealloc, /*tp_dealloc*/
+   0,                              /*tp_print*/
+   0,                              /*tp_getattr*/
+   0,                              /*tp_setattr*/
+   0,                              /*tp_compare*/
+   0,                              /*tp_repr*/
+   0,                              /*tp_as_number*/
+   0,                              /*tp_as_sequence*/
+   0,                              /*tp_as_mapping*/
+   0,                              /*tp_hash */
+   0,                              /*tp_call*/
+   0,                              /*tp_str*/
+   0,                              /*tp_getattro*/
+   0,                              /*tp_setattro*/
+   0,                              /*tp_as_buffer*/
+   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,  /*tp_flags*/
+   "Iterator over GDB blocks",     /*tp_doc */
+   0,                              /*tp_traverse */
+   0,                              /*tp_clear */
+   0,                              /*tp_richcompare */
+   0,                              /*tp_weaklistoffset */
+   symtab_blocks_iterator_iter,    /*tp_iter */
+   symtab_blocks_iterator_iternext,  /*tp_iternext */
+ };
Index: testsuite/gdb.python/py-symtab.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-symtab.exp,v
retrieving revision 1.8
diff -c -p -r1.8 py-symtab.exp
*** testsuite/gdb.python/py-symtab.exp	7 Feb 2012 19:42:27 -0000	1.8
--- testsuite/gdb.python/py-symtab.exp	9 Apr 2012 18:00:14 -0000
*************** load_lib gdb-python.exp
*** 21,37 ****
  set testfile "py-symbol"
  set srcfile ${testfile}.c
  set binfile ${objdir}/${subdir}/${testfile}
! if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
!     untested "Couldn't compile ${srcfile}"
      return -1
  }
  
- # Start with a fresh gdb.
- gdb_exit
- gdb_start
- gdb_reinitialize_dir $srcdir/$subdir
- gdb_load ${binfile}
- 
  # Skip all tests if Python scripting is not enabled.
  if { [skip_python_tests] } { continue }
  
--- 21,31 ----
  set testfile "py-symbol"
  set srcfile ${testfile}.c
  set binfile ${objdir}/${subdir}/${testfile}
! 
! if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
      return -1
  }
  
  # Skip all tests if Python scripting is not enabled.
  if { [skip_python_tests] } { continue }
  
*************** if ![runto_main] then {
*** 41,54 ****
  }
  
  global hex decimal
- 
- # Setup and get the symbol table.
  set line_no [gdb_get_line_number "Block break here."]
! gdb_breakpoint $line_no
! gdb_continue_to_breakpoint "Block break here."
! gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0
! gdb_py_test_silent_cmd "python sal = frame.find_sal()" "Get block" 0
! gdb_py_test_silent_cmd "python symtab = sal.symtab" "Get block" 0
  
  # Test sal.
  gdb_test "python print sal.symtab" ".*gdb.python/py-symbol.c.*" "Test symtab"
--- 35,56 ----
  }
  
  global hex decimal
  set line_no [gdb_get_line_number "Block break here."]
! 
! # Proc to setup and get the symbol table in the Python environment.
! proc setup_python_env { line_no } {
!     gdb_breakpoint $line_no
!     gdb_continue_to_breakpoint "Block break here."
!     gdb_py_test_silent_cmd "python def func_symbol(block): return block.function" "Define a func to get the function symbols" "0"
!     gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0
!     gdb_py_test_silent_cmd "python sal = frame.find_sal()" "Get block" 0
!     gdb_py_test_silent_cmd "python symtab = sal.symtab" "Get block" 0
!     gdb_py_test_silent_cmd "python block_list = list(symtab.blocks_iterator())" "Create a list of blocks" 0
!     gdb_py_test_silent_cmd "python func_symbols = map(func_symbol, block_list)" "Create a list of function symbols" 0
!     gdb_py_test_silent_cmd "python func_names = map(str, func_symbols)" "Create a list of function names" 0
! }
! 
! setup_python_env $line_no
  
  # Test sal.
  gdb_test "python print sal.symtab" ".*gdb.python/py-symbol.c.*" "Test symtab"
*************** gdb_test "python print symtab.filename" 
*** 61,69 ****
--- 63,90 ----
  gdb_test "python print symtab.objfile" "<gdb.Objfile object at ${hex}>" "Test symtab.objfile"
  gdb_test "python print symtab.fullname()" "testsuite/gdb.python/py-symbol.c.*" "Test symtab.fullname"
  gdb_test "python print symtab.is_valid()" "True" "Test symtab.is_valid()"
+ gdb_test "python print 'func' in func_names" "True" "Test that there is a symbol for the function func"
+ gdb_test "python print 'main' in func_names" "True" "Test that there is a symbol for the function main"
+   
  
  # Test is_valid when the objfile is unloaded.  This must be the last
  # test as it unloads the object file in GDB.
  gdb_unload
  gdb_test "python print sal.is_valid()" "False" "Test sal.is_valid"
  gdb_test "python print symtab.is_valid()" "False" "Test symtab.is_valid()"
+ 
+ # Compile the source file as a C++ file and test again.
+ if { [prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}] } {
+     return -1
+ }
+ 
+ if ![runto_main] {
+    return -1
+ }
+ 
+ setup_python_env $line_no
+ 
+ gdb_test "python print 'func(int)' in func_names" "True" "Test that there is a symbol for the function func"
+ gdb_test "python print 'main(int, char**)' in func_names" "True" "Test that there is a symbol for the function main"
+ gdb_test "python print 'SimpleClass::seti(int)' in func_names" "True" "Test that the function SimpleClass::seti(int) is present"
+ gdb_test "python print 'SimpleClass::valueofi()' in func_names" "True" "Test that the function SimpleClass::valueofi() is present"


More information about the Gdb-patches mailing list