public inbox for archer@sourceware.org
 help / color / mirror / Atom feed
* Patch to add rtti_type member to gdb.Value
@ 2009-09-23 18:37 Richard Ward
  2009-09-25 19:03 ` Tom Tromey
  0 siblings, 1 reply; 5+ messages in thread
From: Richard Ward @ 2009-09-23 18:37 UTC (permalink / raw)
  To: archer

[-- Attachment #1: Type: text/plain, Size: 2107 bytes --]

This patch adds value gdb.Value.rtti_type to go along side 
gdb.Value.type. the type represents the type of the value determined by 
rtti. Luckily it turns out that the info is already available in gdb's 
value struct, where it has already been properly determined, so there is 
no need to call any real gdb code. This just exposes it. It is very 
similar to valpy_get_type (without what appears to be an unnecessary 
Py_INCREF).

If the value is not one where rtti makes sense, the value is just equal 
to the value's type. The same applies if for example the vtable pointer 
is garbage.

Sample gdb session follows. class Sub is derived from Base (and they 
have vtables). broken1 and broken2 have their vtable pointers 
overwritten by silly values.
Breakpoint 1, main (argc=<value optimised out>, argv=<value optimised 
out>) at test.cpp:26
26		Base * actually_a_base=new Base();
(gdb) n
27		Base * actually_a_sub=new Sub();
(gdb)
28		ClassWithNoVtable *no_vtable=new ClassWithNoVtable;
(gdb)
29		Base * broken1=new Sub();
(gdb)
30		((void**)broken1)[0]=0x0;
(gdb)
31		Base * broken2=new Sub();
(gdb)
32		((void**)broken2)[0]=&no_vtable;
(gdb)
33	}
(gdb) python v=gdb.parse_and_eval("*actually_a_base")
(gdb) python print v.type
Base
(gdb) python print v.rtti_type
Base
(gdb) python v=gdb.parse_and_eval("*actually_a_sub")
(gdb) python print v.type
Base
(gdb) python print v.rtti_type
Sub
(gdb) python print v
{_vptr.Base = 0x8048858, some_val_in_base = 1}
(gdb) python print v.cast(v.rtti_type)
{<Base> = {_vptr.Base = 0x8048858, some_val_in_base = 1}, 
some_val_in_sub = 2}
(gdb) python v=gdb.parse_and_eval("*no_vtable")
(gdb) python print v.type
ClassWithNoVtable
(gdb) python print v.rtti_type
ClassWithNoVtable
(gdb) python v=gdb.parse_and_eval("*broken1")
(gdb) python print v.rtti_type
Base
(gdb) python v=gdb.parse_and_eval("*broken2")
(gdb) python print v.rtti_type
Base
(gdb) quit

Meant to submit this ages ago (and said in the list that I would), got 
caught up with other things, sorry. Someone mailed me off list to ask If 
I could submit it, so here it is. Docs/Changelogs updated also.


[-- Attachment #2: rtti_type.patch --]
[-- Type: text/x-patch, Size: 4002 bytes --]

From b7dd5dfc090c6ebd30ac34544c8a044aebba8e1a Mon Sep 17 00:00:00 2001
From: Richard Ward <richard@elemental-lin.(none)>
Date: Wed, 23 Sep 2009 19:21:36 +0100
Subject: [PATCH] 2009-09-23  Richard Ward  <richard.j.ward1@googlemail.com>

	add attribute rtti_type to gdb.Value
	* gdb/python/py-value.c:
		new function valpy_get_rtti_type to get and return the real type
		of a value from the gdb value struct, and store it as a
		type_object in value_object.
	* gdb/doc/gdb.texinfo
		updated to refelect the above.
---
 gdb/ChangeLog         |    6 ++++++
 gdb/doc/ChangeLog     |    4 ++++
 gdb/doc/gdb.texinfo   |    8 ++++++++
 gdb/python/py-value.c |   21 +++++++++++++++++++++
 4 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e7b2748..f50b737 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2009-09-23  Richard Ward  <richard.j.ward1@googlemail.com>
+
+	* py-value.c: Added an attribute called rtti_type
+	denoting the actual run time type of an object where
+	rtti is applicable.
+
 2009-09-10  Joel Brobecker  <brobecker@adacore.com>
 
 	* top.c (interactive_mode): New static variable.
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index b3f8fc7..22c80ac 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,7 @@
+2009-09-23  Richard Ward  <richard.j.ward1@googlemail.com>
+
+	* gdb.texinfo: Document new attribute rtti_type in gdb.Value
+
 2009-09-10  Joel Brobecker  <brobecker@adacore.com>
 
 	Add documentation for set/show interactive-mode.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 18ffb09..597757f 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -19104,6 +19104,14 @@ this value, thus it is not available for fetching from the inferior.
 The type of this @code{gdb.Value}.  The value of this attribute is a
 @code{gdb.Type} object.
 @end defivar
+
+@defivar Value rtti_type
+A @code{gdb.Type} object representing the actual type of this
+@code{gdb.Value} determined using Run Time Type Information where
+applicable.  If the value has no RTTI associated with it or if the type
+could not be determined then this attribute will be identical to the
+@code{type} attribute.
+@end defivar
 @end table
 
 The following methods are provided:
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 14efd79..f5a04f6 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -60,6 +60,7 @@ typedef struct value_object {
   struct value *value;
   PyObject *address;
   PyObject *type;
+  PyObject *rtti_type;
 } value_object;
 
 /* List of all values which are currently exposed to Python. It is
@@ -224,6 +225,24 @@ valpy_get_type (PyObject *self, void *closure)
   return obj->type;
 }
 
+/* Return the real type of the value determined using rtti */
+static PyObject *
+valpy_get_rtti_type (PyObject *self, void *closure)
+{
+  value_object *obj = (value_object *) self;
+  if (!obj->rtti_type)
+    {
+      struct type * rtti_type=value_enclosing_type(obj->value);
+      obj->rtti_type = type_to_type_object (rtti_type);
+      if (!obj->rtti_type)
+	{
+	  obj->rtti_type = Py_None;
+	}
+    }
+  Py_INCREF (obj->rtti_type);
+  return obj->rtti_type;
+}
+
 /* Implementation of gdb.Value.string ([encoding] [, errors]
    [, length]) -> string.  Return Unicode string with value contents.
    If ENCODING is not given, the string is assumed to be encoded in
@@ -854,6 +873,7 @@ value_to_value_object (struct value *val)
       value_incref (val);
       val_obj->address = NULL;
       val_obj->type = NULL;
+      val_obj->rtti_type = NULL;
       note_value (val_obj);
     }
 
@@ -1021,6 +1041,7 @@ static PyGetSetDef value_object_getset[] = {
     "Boolean telling whether the value is optimized out (i.e., not available).",
     NULL },
   { "type", valpy_get_type, NULL, "Type of the value.", NULL },
+  { "rtti_type", valpy_get_rtti_type, NULL, "Actual type of the value determined using rtti.", NULL },
   {NULL}  /* Sentinel */
 };
 
-- 
1.6.0.4


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Patch to add rtti_type member to gdb.Value
  2009-09-23 18:37 Patch to add rtti_type member to gdb.Value Richard Ward
@ 2009-09-25 19:03 ` Tom Tromey
  2009-09-25 19:19   ` Richard Ward
  0 siblings, 1 reply; 5+ messages in thread
From: Tom Tromey @ 2009-09-25 19:03 UTC (permalink / raw)
  To: Richard Ward; +Cc: archer

>>>>> "Richard" == Richard Ward <richard.j.ward1@googlemail.com> writes:

Richard> This patch adds value gdb.Value.rtti_type to go along side
Richard> gdb.Value.type. the type represents the type of the value determined
Richard> by rtti. Luckily it turns out that the info is already available in
Richard> gdb's value struct, where it has already been properly determined, so
Richard> there is no need to call any real gdb code. This just exposes
Richard> it.

Is that always the case?  I ask because other code, like the code
implementing "set print object on", uses value_rtti_type and/or
value_rtti_target_type.

The patch also has some non-GNU-formatted code; no big deal, just a
bunch of nits to clean up.

Richard> It is very similar to valpy_get_type (without what appears to
Richard> be an unnecessary Py_INCREF).

The code:

  value_object *obj = (value_object *) self;
  if (!obj->type)
    {
      obj->type = type_to_type_object (value_type (obj->value));
      if (!obj->type)
	{
	  obj->type = Py_None;
	  Py_INCREF (obj->type);
	}
    }
  Py_INCREF (obj->type);
  return obj->type;

The first Py_INCREF is there because obj->type must be a new reference
to an object.  That lets us pair with the decre at object destruction.
It looks weird, being on Py_None, but I think that is still correct.

The second Py_INCREF is so that we always return a new reference to our
caller.

So, I think they are both needed.  But if not, I definitely want to know
about it, and why :-)

Tom

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Patch to add rtti_type member to gdb.Value
  2009-09-25 19:03 ` Tom Tromey
@ 2009-09-25 19:19   ` Richard Ward
  2009-09-25 20:43     ` Tom Tromey
  0 siblings, 1 reply; 5+ messages in thread
From: Richard Ward @ 2009-09-25 19:19 UTC (permalink / raw)
  To: Tom Tromey; +Cc: archer

Tom Tromey wrote:
>>>>>> "Richard" == Richard Ward <richard.j.ward1@googlemail.com> writes:
> 
> Richard> This patch adds value gdb.Value.rtti_type to go along side
> Richard> gdb.Value.type. the type represents the type of the value determined
> Richard> by rtti. Luckily it turns out that the info is already available in
> Richard> gdb's value struct, where it has already been properly determined, so
> Richard> there is no need to call any real gdb code. This just exposes
> Richard> it.
> 
> Is that always the case?  I ask because other code, like the code
> implementing "set print object on", uses value_rtti_type and/or
> value_rtti_target_type.
> 
> The patch also has some non-GNU-formatted code; no big deal, just a
> bunch of nits to clean up.
> 
> Richard> It is very similar to valpy_get_type (without what appears to
> Richard> be an unnecessary Py_INCREF).
> 
> The code:
> 
>   value_object *obj = (value_object *) self;
>   if (!obj->type)
>     {
>       obj->type = type_to_type_object (value_type (obj->value));
>       if (!obj->type)
> 	{
> 	  obj->type = Py_None;
> 	  Py_INCREF (obj->type);
> 	}
>     }
>   Py_INCREF (obj->type);
>   return obj->type;
> 
> The first Py_INCREF is there because obj->type must be a new reference
> to an object.  That lets us pair with the decre at object destruction.
> It looks weird, being on Py_None, but I think that is still correct.
> 
> The second Py_INCREF is so that we always return a new reference to our
> caller.
> 
> So, I think they are both needed.  But if not, I definitely want to know
> about it, and why :-)
> 
> Tom
I'll look at the other points later when I have time, but In this case 
if Py_None is used it will be incremented twice before being handed back 
to the caller.

Richard.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Patch to add rtti_type member to gdb.Value
  2009-09-25 19:19   ` Richard Ward
@ 2009-09-25 20:43     ` Tom Tromey
  0 siblings, 0 replies; 5+ messages in thread
From: Tom Tromey @ 2009-09-25 20:43 UTC (permalink / raw)
  To: Richard Ward; +Cc: archer

>>>>> "Richard" == Richard Ward <richard.j.ward1@googlemail.com> writes:

Richard> I'll look at the other points later when I have time, but In this case
Richard> if Py_None is used it will be incremented twice before being handed
Richard> back to the caller.

Yeah -- once for the store to obj->type, and once for the caller.
The caller needs a new reference, always.
For obj->type, this lets us call Py_DECREF without checking whether
obj->type is None.

Tom

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Patch to add rtti_type member to gdb.Value
@ 2009-09-28  9:55 Richard Ward
  0 siblings, 0 replies; 5+ messages in thread
From: Richard Ward @ 2009-09-28  9:55 UTC (permalink / raw)
  To: archer

[-- Attachment #1: Type: text/plain, Size: 1970 bytes --]

Tom Tromey wrote:
>>>>>> "Richard" == Richard Ward <richard.j.ward1@googlemail.com> writes:
> 
> Richard> I'll look at the other points later when I have time, but In this case
> Richard> if Py_None is used it will be incremented twice before being handed
> Richard> back to the caller.
> 
> Yeah -- once for the store to obj->type, and once for the caller.
> The caller needs a new reference, always.
> For obj->type, this lets us call Py_DECREF without checking whether
> obj->type is None.
> 
> Tom

Ah, I missed the inc for the store. Thanks for explaining.

As for if it is always the case that the run time type is stored in the
value struct, the comments say it is (gdb/value.c:140 or there abouts).
The value seems to be determined in valops.c, in value_ind (actually in
the call to value_full_type). So as soon as a pointer is dereferenced
its run time type is stored.

Originally I was calling value_rtti_type in valpy_get_rtti_type but it
seemed sensible to use enclosing_type seeing as it was there. The fact
that you don't know the run time type until a pointer is dereferenced
seemed sensible to me (as the type of a Base* is always a Base*, even if
the thing it points to is actually a Sub). If the value in question is a
reference, the only way I see in python of getting a gdb.Value object
representing the value being referred to by the reference is to take the
address of the reference, and then dereference that (so we still
dereference a pointer and value_rtti_type is still called).

It seems that print object looks at the type before the dereference. I
guess the question is whether the rtti_type attribute of a
pointer/reference gdb.Value should be a pointer/reference to the
rtti_type of the dereferenced object, or the compile time pointer type.
IMO it should be the compile time pointer type, it seems to make more
sense that way.

As for the non GNU coding standards, I think I've fixed that (and the
python inc) in the attached.

Richard.


[-- Attachment #2: rtti_type.patch --]
[-- Type: text/x-patch, Size: 4044 bytes --]

From 07e2b27c05579d02bc6ccde77b6e06e34b161d30 Mon Sep 17 00:00:00 2001
From: Richard Ward <richard@elemental-lin.(none)>
Date: Mon, 28 Sep 2009 10:43:36 +0100
Subject: [PATCH] 2009-09-28  Richard Ward  <richard.j.ward1@googlemail.com>

add attribute rtti_type to gdb.Value
* gdb/python/py-value.c:
	new function valpy_get_rtti_type to get and return the
	real type of a value from the gdb value struct, and store
	it as a type_object in value_object.
* gdb/doc/gdb.texinfo
	updated to refelect the above.
---
 gdb/ChangeLog         |    6 ++++++
 gdb/doc/ChangeLog     |    4 ++++
 gdb/doc/gdb.texinfo   |    8 ++++++++
 gdb/python/py-value.c |   23 +++++++++++++++++++++++
 4 files changed, 41 insertions(+), 0 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e7b2748..f50b737 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2009-09-23  Richard Ward  <richard.j.ward1@googlemail.com>
+
+	* py-value.c: Added an attribute called rtti_type
+	denoting the actual run time type of an object where
+	rtti is applicable.
+
 2009-09-10  Joel Brobecker  <brobecker@adacore.com>
 
 	* top.c (interactive_mode): New static variable.
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index b3f8fc7..22c80ac 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,7 @@
+2009-09-23  Richard Ward  <richard.j.ward1@googlemail.com>
+
+	* gdb.texinfo: Document new attribute rtti_type in gdb.Value
+
 2009-09-10  Joel Brobecker  <brobecker@adacore.com>
 
 	Add documentation for set/show interactive-mode.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 18ffb09..597757f 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -19104,6 +19104,14 @@ this value, thus it is not available for fetching from the inferior.
 The type of this @code{gdb.Value}.  The value of this attribute is a
 @code{gdb.Type} object.
 @end defivar
+
+@defivar Value rtti_type
+A @code{gdb.Type} object representing the actual type of this
+@code{gdb.Value} determined using Run Time Type Information where
+applicable.  If the value has no RTTI associated with it or if the type
+could not be determined then this attribute will be identical to the
+@code{type} attribute.
+@end defivar
 @end table
 
 The following methods are provided:
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 14efd79..3c0deb2 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -60,6 +60,7 @@ typedef struct value_object {
   struct value *value;
   PyObject *address;
   PyObject *type;
+  PyObject *rtti_type;
 } value_object;
 
 /* List of all values which are currently exposed to Python. It is
@@ -224,6 +225,26 @@ valpy_get_type (PyObject *self, void *closure)
   return obj->type;
 }
 
+/* Return the real type of the value determined using rtti */
+static PyObject *
+valpy_get_rtti_type (PyObject *self, void *closure)
+{
+  value_object *obj = (value_object *) self;
+  struct type * rtti_type;
+  if (!obj->rtti_type)
+    {
+      rtti_type=value_enclosing_type(obj->value);
+      obj->rtti_type = type_to_type_object (rtti_type);
+      if (!obj->rtti_type)
+	{
+	  obj->rtti_type = Py_None;
+	  Py_INCREF (obj->rtti_type);
+	}
+    }
+  Py_INCREF (obj->rtti_type);
+  return obj->rtti_type;
+}
+
 /* Implementation of gdb.Value.string ([encoding] [, errors]
    [, length]) -> string.  Return Unicode string with value contents.
    If ENCODING is not given, the string is assumed to be encoded in
@@ -854,6 +875,7 @@ value_to_value_object (struct value *val)
       value_incref (val);
       val_obj->address = NULL;
       val_obj->type = NULL;
+      val_obj->rtti_type = NULL;
       note_value (val_obj);
     }
 
@@ -1021,6 +1043,7 @@ static PyGetSetDef value_object_getset[] = {
     "Boolean telling whether the value is optimized out (i.e., not available).",
     NULL },
   { "type", valpy_get_type, NULL, "Type of the value.", NULL },
+  { "rtti_type", valpy_get_rtti_type, NULL, "Actual type of the value determined using rtti.", NULL },
   {NULL}  /* Sentinel */
 };
 
-- 
1.6.0.4



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2009-09-28  9:55 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-23 18:37 Patch to add rtti_type member to gdb.Value Richard Ward
2009-09-25 19:03 ` Tom Tromey
2009-09-25 19:19   ` Richard Ward
2009-09-25 20:43     ` Tom Tromey
2009-09-28  9:55 Richard Ward

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).