[doc,RFA] Add ability to set random attributes in python objfiles,progspaces

Message ID yjt27g09qcx2.fsf@ruffy.mtv.corp.google.com
State New, archived
Headers

Commit Message

Doug Evans Oct. 9, 2014, 7:08 p.m. UTC
  Hi.

I have a need to do some extra record keeping in progspaces and
objfiles.  This patch adds the ability to add random attributes
to objfile and progspace objects using the same mechanism used
for gdb.Fields.

Regression tested on amd64-linux.

2014-10-09  Doug Evans  <dje@google.com>

	* NEWS: Mention ability add attributes to gdb.Objfile and
	gdb.Progspace objects.
	* python/py-objfile.c (objfile_object): New member dict.
	(objfpy_dealloc): Py_XDECREF dict.
	(objfpy_initialize): Initialize dict.
	(objfile_getset): Add __dict__.
	(objfile_object_type): Set tp_dictoffset member.
	* python/py-progspace.c (progspace_object): New member dict.
	(pspy_dealloc): Py_XDECREF dict.
	(pspy_initialize): Initialize dict.
	(pspace_getset): Add __dict__.
	(pspace_object_type): Set tp_dictoffset member.

	doc/
	* gdb.texinfo (Progspaces In Python): Document ability to add
	random attributes to gdb.Progspace objects.
	(Objfiles In Python): Document ability to add random attributes to
	gdb.objfile objects.

	testsuite/
	* gdb.python/py-objfile.exp: Add tests for setting random attributes
	in objfiles.
	* gdb.python/py-progspace.exp: Add tests for setting random attributes
	in progspaces.
  

Comments

Doug Evans Oct. 9, 2014, 7:09 p.m. UTC | #1
On Thu, Oct 9, 2014 at 12:08 PM, Doug Evans <dje@google.com> wrote:
> Hi.
>
> I have a need to do some extra record keeping in progspaces and
> objfiles.  This patch adds the ability to add random attributes
> to objfile and progspace objects using the same mechanism used
> for gdb.Fields.
>
> Regression tested on amd64-linux.
>
> 2014-10-09  Doug Evans  <dje@google.com>
>
>         * NEWS: Mention ability add attributes to gdb.Objfile and
>         gdb.Progspace objects.
>         * python/py-objfile.c (objfile_object): New member dict.
>         (objfpy_dealloc): Py_XDECREF dict.
>         (objfpy_initialize): Initialize dict.
>         (objfile_getset): Add __dict__.
>         (objfile_object_type): Set tp_dictoffset member.
>         * python/py-progspace.c (progspace_object): New member dict.
>         (pspy_dealloc): Py_XDECREF dict.
>         (pspy_initialize): Initialize dict.
>         (pspace_getset): Add __dict__.
>         (pspace_object_type): Set tp_dictoffset member.
>
>         doc/
>         * gdb.texinfo (Progspaces In Python): Document ability to add
>         random attributes to gdb.Progspace objects.
>         (Objfiles In Python): Document ability to add random attributes to
>         gdb.objfile objects.
>
>         testsuite/
>         * gdb.python/py-objfile.exp: Add tests for setting random attributes
>         in objfiles.
>         * gdb.python/py-progspace.exp: Add tests for setting random attributes
>         in progspaces.

Oh, btw, if you're going to try this patch,
it depends on
https://sourceware.org/ml/gdb-patches/2014-10/msg00206.html
  
Eli Zaretskii Oct. 10, 2014, 7:58 a.m. UTC | #2
> From: Doug Evans <dje@google.com>
> Date: Thu, 09 Oct 2014 12:08:09 -0700
> 
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -9,6 +9,7 @@
>  
>    ** You can now access frame registers from Python scripts.
>    ** New attribute 'producer' for gdb.Symtab objects.
> +  ** You can now add attributes to gdb.Objfile and gdb.Progspace objects.

This part is OK.

> --- a/gdb/doc/python.texi
> +++ b/gdb/doc/python.texi
> @@ -3356,6 +3356,10 @@ The @code{frame_filters} attribute is a dictionary of frame filter
>  objects.  @xref{Frame Filter API}, for more information.
>  @end defvar
>  
> +One may add arbitrary attributes to @code{gdb.Progspace} objects.

Add how?  If this is done by "usual" Python ways, please say so.

> +This is useful if for example one needs to do some extra record keeping
> +associated with the progspace.

Please add commas where they are needed in this sentence.

> +One may add arbitrary attributes to @code{gdb.Objfile} objects.
> +This is useful if for example one needs to do some extra record keeping
> +associated with the objfile.

Same comments here.

> +In this contrived example we record the time when @value{GDBN}
> +loaded the objfile.
> +
> +@smallexample
> +(gdb) python
> +import datetime
> +def new_objfile_handler (event):
> +    event.new_objfile.time_loaded = datetime.datetime.today ()
> +gdb.events.new_objfile.connect (new_objfile_handler)
> +end
> +(gdb) file ./hello
> +Reading symbols from ./hello...done.
> +(gdb) python print gdb.objfiles()[0].time_loaded
> +2014-10-09 11:41:36.770345
> +@end smallexample

If this is related to adding attributes, then I'd like the text say
that more explicitly.  Alternatively, some comment in the example that
mentions "attributes" could do.

Btw, why do we only support adding attributes for these 2 types of
objects?  Why not for any object?

Thanks.
  
Phil Muldoon Oct. 10, 2014, 8 a.m. UTC | #3
On 09/10/14 20:08, Doug Evans wrote:
> Hi.
>
> I have a need to do some extra record keeping in progspaces and
> objfiles.  This patch adds the ability to add random attributes
> to objfile and progspace objects using the same mechanism used
> for gdb.Fields.
>
> Regression tested on amd64-linux.
>
> 2014-10-09  Doug Evans  <dje@google.com>
>
>     * NEWS: Mention ability add attributes to gdb.Objfile and
>     gdb.Progspace objects.
>     * python/py-objfile.c (objfile_object): New member dict.
>     (objfpy_dealloc): Py_XDECREF dict.
>     (objfpy_initialize): Initialize dict.
>     (objfile_getset): Add __dict__.
>     (objfile_object_type): Set tp_dictoffset member.
>     * python/py-progspace.c (progspace_object): New member dict.
>     (pspy_dealloc): Py_XDECREF dict.
>     (pspy_initialize): Initialize dict.
>     (pspace_getset): Add __dict__.
>     (pspace_object_type): Set tp_dictoffset member.
>
>     doc/
>     * gdb.texinfo (Progspaces In Python): Document ability to add
>     random attributes to gdb.Progspace objects.
>     (Objfiles In Python): Document ability to add random attributes to
>     gdb.objfile objects.
>
>     testsuite/
>     * gdb.python/py-objfile.exp: Add tests for setting random attributes
>     in objfiles.
>     * gdb.python/py-progspace.exp: Add tests for setting random attributes
>     in progspaces.
>
> diff --git a/gdb/NEWS b/gdb/NEWS
> index b56fe8e..ec43a22 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -9,6 +9,7 @@
> 
>    ** You can now access frame registers from Python scripts.
>    ** New attribute 'producer' for gdb.Symtab objects.
> +  ** You can now add attributes to gdb.Objfile and gdb.Progspace objects.
> 
>  * New Python-based convenience functions:
> 
> diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
> index 81ec11b..14a2181 100644
> --- a/gdb/doc/python.texi
> +++ b/gdb/doc/python.texi
> @@ -3356,6 +3356,10 @@ The @code{frame_filters} attribute is a dictionary of frame filter
>  objects.  @xref{Frame Filter API}, for more information.
>  @end defvar
> 
> +One may add arbitrary attributes to @code{gdb.Progspace} objects.
> +This is useful if for example one needs to do some extra record keeping
> +associated with the progspace.

Maybe add a small example here as you did with gdb.Objfile?  Or maybe
an xref.  One of my goals in the next year is to add (and backfill in
existing documentation) more example led documentation for Python.
Sometimes an example speaks (ten) thousand words!


> +@smallexample
> +(gdb) python
> +import datetime
> +def new_objfile_handler (event):
> +    event.new_objfile.time_loaded = datetime.datetime.today ()
> +gdb.events.new_objfile.connect (new_objfile_handler)
> +end
> +(gdb) file ./hello
> +Reading symbols from ./hello...done.
> +(gdb) python print gdb.objfiles()[0].time_loaded
> +2014-10-09 11:41:36.770345
> +@end smallexample

This is really awesome example. (Linking in from comment above).
Thanks for taking the time out to provide a "useful" example that is
also simple.


>  A @code{gdb.Objfile} object has the following methods:
> 
>  @defun Objfile.is_valid ()
> diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
> index df29691..32bceee 100644
> --- a/gdb/python/py-objfile.c
> +++ b/gdb/python/py-objfile.c
> @@ -30,6 +30,9 @@ typedef struct
>    /* The corresponding objfile.  */
>    struct objfile *objfile;
> 
> +  /* Dictionary holding user-added attributes.  */
> +  PyObject *dict;
> +

My only nit here is the naming.  dict is kind of generic.  I know it
follows on from the fields code :( Even though you wrote a comment,
later use in the code means (say a year from now), I have to
remember what this mysterious "dict" is.  I'll volunteer to fix up the
fields code. Lately I have been writing variable names that at least
have an indication of actual usage in GDB beyond a description of what
the variable is.  So I would write that to be something like,
attribute_dict or something along those lines.  Anyway just a nit.  If
you decide not to pursue my comments, it is no show-stopper.

> --- a/gdb/python/py-progspace.c
> +++ b/gdb/python/py-progspace.c
> @@ -32,6 +32,9 @@ typedef struct
>    /* The corresponding pspace.  */
>    struct program_space *pspace;
> 
> +  /* Dictionary holding user-added attributes.  */
> +  PyObject *dict;
> +
>    /* The pretty-printer list of functions.  */
>    PyObject *printers;

Same comments as above with the dict name.

Thanks for this patch.  It seems really useful (and in implementation
fairly simple to implement).  I wonder if there are other objects in
Python that could benefit from the ability to arbitrarily record
keep?

Cheers

Phil
  
Doug Evans Oct. 10, 2014, 5:21 p.m. UTC | #4
Eli Zaretskii writes:
 > Btw, why do we only support adding attributes for these 2 types of
 > objects?  Why not for any object?

Like most/all things in gdb/python, things get added by demand.
  
Doug Evans Oct. 10, 2014, 5:35 p.m. UTC | #5
Phil Muldoon writes:
 > Maybe add a small example here as you did with gdb.Objfile?  Or maybe
 > an xref.  One of my goals in the next year is to add (and backfill in
 > existing documentation) more example led documentation for Python.
 > Sometimes an example speaks (ten) thousand words!

I couldn't think of a simple one.

 > > +@smallexample
 > > +(gdb) python
 > > +import datetime
 > > +def new_objfile_handler (event):
 > > +    event.new_objfile.time_loaded = datetime.datetime.today ()
 > > +gdb.events.new_objfile.connect (new_objfile_handler)
 > > +end
 > > +(gdb) file ./hello
 > > +Reading symbols from ./hello...done.
 > > +(gdb) python print gdb.objfiles()[0].time_loaded
 > > +2014-10-09 11:41:36.770345
 > > +@end smallexample
 > 
 > This is really awesome example. (Linking in from comment above).
 > Thanks for taking the time out to provide a "useful" example that is
 > also simple.

Yeah, this one was simple enough and educational enough
that it was worth the time and effort.

 > >  A @code{gdb.Objfile} object has the following methods:
 > > 
 > >  @defun Objfile.is_valid ()
 > > diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
 > > index df29691..32bceee 100644
 > > --- a/gdb/python/py-objfile.c
 > > +++ b/gdb/python/py-objfile.c
 > > @@ -30,6 +30,9 @@ typedef struct
 > >    /* The corresponding objfile.  */
 > >    struct objfile *objfile;
 > > 
 > > +  /* Dictionary holding user-added attributes.  */
 > > +  PyObject *dict;
 > > +
 > 
 > My only nit here is the naming.  dict is kind of generic.  I know it
 > follows on from the fields code :( Even though you wrote a comment,
 > later use in the code means (say a year from now), I have to
 > remember what this mysterious "dict" is.

Note that this is also __dict__ from the Python side.
I'd use the name __dict__ here for clarity, but I can't. :-)
[compiler's namespace]

I can certainly add __dict__ to the comment though.

 > Thanks for this patch.  It seems really useful (and in implementation
 > fairly simple to implement).  I wonder if there are other objects in
 > Python that could benefit from the ability to arbitrarily record
 > keep?

Like all things in gdb/python, things get added on a demand basis.
[This observation extends to more pieces of gdb than just gdb/python.
I'm happy to change the rules, but I do insist on there being
no double standards. :-)]
  
Phil Muldoon Oct. 10, 2014, 6:25 p.m. UTC | #6
On 10/10/14 18:35, Doug Evans wrote:
> Phil Muldoon writes:
>  > Maybe add a small example here as you did with gdb.Objfile?  Or maybe
>  > an xref.  One of my goals in the next year is to add (and backfill in
>  > existing documentation) more example led documentation for Python.
>  > Sometimes an example speaks (ten) thousand words!
>
> I couldn't think of a simple one.

Maybe document (as in describe) a more complex one? 

>  > Thanks for this patch.  It seems really useful (and in implementation
>  > fairly simple to implement).  I wonder if there are other objects in
>  > Python that could benefit from the ability to arbitrarily record
>  > keep?
>
> Like all things in gdb/python, things get added on a demand basis.
> [This observation extends to more pieces of gdb than just gdb/python.
> I'm happy to change the rules, but I do insist on there being
> no double standards. :-)]

Yes, I think this approach is the only way forward with Python, apart
from big feature patch-sets.  I wasn't trying to sideline you into
providing this support for other objects btw! More a thinking "out
loud" where this functionality would be useful.  So yeah, we'll add it
when we find we need it.

Cheers

Phil
  

Patch

diff --git a/gdb/NEWS b/gdb/NEWS
index b56fe8e..ec43a22 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -9,6 +9,7 @@ 
 
   ** You can now access frame registers from Python scripts.
   ** New attribute 'producer' for gdb.Symtab objects.
+  ** You can now add attributes to gdb.Objfile and gdb.Progspace objects.
 
 * New Python-based convenience functions:
 
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 81ec11b..14a2181 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -3356,6 +3356,10 @@  The @code{frame_filters} attribute is a dictionary of frame filter
 objects.  @xref{Frame Filter API}, for more information.
 @end defvar
 
+One may add arbitrary attributes to @code{gdb.Progspace} objects.
+This is useful if for example one needs to do some extra record keeping
+associated with the progspace.
+
 @node Objfiles In Python
 @subsubsection Objfiles In Python
 
@@ -3411,6 +3415,26 @@  The @code{frame_filters} attribute is a dictionary of frame filter
 objects.  @xref{Frame Filter API}, for more information.
 @end defvar
 
+One may add arbitrary attributes to @code{gdb.Objfile} objects.
+This is useful if for example one needs to do some extra record keeping
+associated with the objfile.
+
+In this contrived example we record the time when @value{GDBN}
+loaded the objfile.
+
+@smallexample
+(gdb) python
+import datetime
+def new_objfile_handler (event):
+    event.new_objfile.time_loaded = datetime.datetime.today ()
+gdb.events.new_objfile.connect (new_objfile_handler)
+end
+(gdb) file ./hello
+Reading symbols from ./hello...done.
+(gdb) python print gdb.objfiles()[0].time_loaded
+2014-10-09 11:41:36.770345
+@end smallexample
+
 A @code{gdb.Objfile} object has the following methods:
 
 @defun Objfile.is_valid ()
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index df29691..32bceee 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -30,6 +30,9 @@  typedef struct
   /* The corresponding objfile.  */
   struct objfile *objfile;
 
+  /* Dictionary holding user-added attributes.  */
+  PyObject *dict;
+
   /* The pretty-printer list of functions.  */
   PyObject *printers;
 
@@ -67,6 +70,7 @@  objfpy_dealloc (PyObject *o)
 {
   objfile_object *self = (objfile_object *) o;
 
+  Py_XDECREF (self->dict);
   Py_XDECREF (self->printers);
   Py_XDECREF (self->frame_filters);
   Py_XDECREF (self->type_printers);
@@ -81,6 +85,7 @@  static int
 objfpy_initialize (objfile_object *self)
 {
   self->objfile = NULL;
+  self->dict = NULL;
 
   self->printers = PyList_New (0);
   if (self->printers == NULL)
@@ -336,6 +341,8 @@  Return true if this object file is valid, false if not." },
 
 static PyGetSetDef objfile_getset[] =
 {
+  { "__dict__", gdb_py_generic_dict, NULL,
+    "The __dict__ for this objfile.", &objfile_object_type },
   { "filename", objfpy_get_filename, NULL,
     "The objfile's filename, or None.", NULL },
   { "pretty_printers", objfpy_get_printers, objfpy_set_printers,
@@ -385,7 +392,7 @@  static PyTypeObject objfile_object_type =
   0,				  /* tp_dict */
   0,				  /* tp_descr_get */
   0,				  /* tp_descr_set */
-  0,				  /* tp_dictoffset */
+  offsetof (objfile_object, dict), /* tp_dictoffset */
   0,				  /* tp_init */
   0,				  /* tp_alloc */
   objfpy_new,			  /* tp_new */
diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c
index 4280032..72ed353 100644
--- a/gdb/python/py-progspace.c
+++ b/gdb/python/py-progspace.c
@@ -32,6 +32,9 @@  typedef struct
   /* The corresponding pspace.  */
   struct program_space *pspace;
 
+  /* Dictionary holding user-added attributes.  */
+  PyObject *dict;
+
   /* The pretty-printer list of functions.  */
   PyObject *printers;
 
@@ -75,6 +78,7 @@  pspy_dealloc (PyObject *self)
 {
   pspace_object *ps_self = (pspace_object *) self;
 
+  Py_XDECREF (ps_self->dict);
   Py_XDECREF (ps_self->printers);
   Py_XDECREF (ps_self->frame_filters);
   Py_XDECREF (ps_self->type_printers);
@@ -89,6 +93,7 @@  static int
 pspy_initialize (pspace_object *self)
 {
   self->pspace = NULL;
+  self->dict = NULL;
 
   self->printers = PyList_New (0);
   if (self->printers == NULL)
@@ -331,6 +336,8 @@  gdbpy_initialize_pspace (void)
 
 static PyGetSetDef pspace_getset[] =
 {
+  { "__dict__", gdb_py_generic_dict, NULL,
+    "The __dict__ for this progspace.", &pspace_object_type },
   { "filename", pspy_get_filename, NULL,
     "The progspace's main filename, or None.", NULL },
   { "pretty_printers", pspy_get_printers, pspy_set_printers,
@@ -380,7 +387,7 @@  static PyTypeObject pspace_object_type =
   0,				  /* tp_dict */
   0,				  /* tp_descr_get */
   0,				  /* tp_descr_set */
-  0,				  /* tp_dictoffset */
+  offsetof (pspace_object, dict), /* tp_dictoffset */
   0,				  /* tp_init */
   0,				  /* tp_alloc */
   pspy_new,			  /* tp_new */
diff --git a/gdb/testsuite/gdb.python/py-objfile.exp b/gdb/testsuite/gdb.python/py-objfile.exp
index 56f99f8..d880da3 100644
--- a/gdb/testsuite/gdb.python/py-objfile.exp
+++ b/gdb/testsuite/gdb.python/py-objfile.exp
@@ -44,3 +44,8 @@  gdb_test "python print (objfile.is_valid())" "True" \
 gdb_unload
 gdb_test "python print (objfile.is_valid())" "False" \
   "Get objfile validity after unload"
+
+gdb_py_test_silent_cmd "python objfile.random_attribute = 42" \
+    "Set random attribute in objfile" 1
+gdb_test "python print (objfile.random_attribute)" "42" \
+    "Verify set of random attribute in objfile"
diff --git a/gdb/testsuite/gdb.python/py-progspace.exp b/gdb/testsuite/gdb.python/py-progspace.exp
index 2fcfdb9..a47fae6 100644
--- a/gdb/testsuite/gdb.python/py-progspace.exp
+++ b/gdb/testsuite/gdb.python/py-progspace.exp
@@ -16,6 +16,8 @@ 
 # This file is part of the GDB testsuite.  It tests the program space
 # support in Python.
 
+load_lib gdb-python.exp
+
 standard_testfile
 
 if {[build_executable $testfile.exp $testfile $srcfile debug] == -1} {
@@ -37,5 +39,13 @@  gdb_test "python print (gdb.progspaces())" "\\\[<gdb.Progspace object at $hex>\\
 
 gdb_load ${binfile}
 
-gdb_test "python print (gdb.current_progspace().filename)" "py-progspace" \
+gdb_py_test_silent_cmd "python progspace = gdb.current_progspace()" \
+    "Get current progspace" 1
+
+gdb_test "python print (progspace.filename)" "py-progspace" \
   "current progspace filename (py-progspace)"
+
+gdb_py_test_silent_cmd "python progspace.random_attribute = 42" \
+    "Set random attribute in progspace" 1
+gdb_test "python print (progspace.random_attribute)" "42" \
+    "Verify set of random attribute in progspace"