public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Determining type of an object at debug time.
@ 2000-03-13  9:45 Daniel Berlin
  2000-03-13 16:35 ` Martin v. Loewis
  0 siblings, 1 reply; 6+ messages in thread
From: Daniel Berlin @ 2000-03-13  9:45 UTC (permalink / raw)
  To: gcc

As the new C++ support maintainer for GDB, one of the things i'm working
on is determining the type of an object at debug time, so we can print out
the type properly without the user having to cast it, and so we can call
the right functions if the user wanted to.
For those who don't udnerstand what i mean, consider the following:
class foo1
{
public:
virtual int ab(){};
int a;
};
class foo2:public foo1
{
public:
virtual int ab(){};
int b;
};

foo1 *dan=new foo2();


if you print dan in GDB, it'll think it's a foo1 *, and if you want to see
the foo2 members, you have to print (foo2 *)dan.
If you called ab, it would call the wrong function, because it has no idea
it's really not a foo1.
Their is already support for doing this with HP aCC compiled objects. The
code works by reading the type name out of the vtable.
Obviously, this is very compiler specific, but it's always going to be, so
i have no problem with having to hard code offsets or something.
I'm just trying to figure out how to get the same info, at debug time, on
g++ compiled objects.
Is this even possible with g++ compiled objects?
I could call the __tf functions, but that would require knowing the type
in the first place.

--Dan

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

* Re: Determining type of an object at debug time.
  2000-03-13  9:45 Determining type of an object at debug time Daniel Berlin
@ 2000-03-13 16:35 ` Martin v. Loewis
  2000-03-13 17:02   ` Daniel Berlin
  0 siblings, 1 reply; 6+ messages in thread
From: Martin v. Loewis @ 2000-03-13 16:35 UTC (permalink / raw)
  To: dan; +Cc: gcc

> Obviously, this is very compiler specific, but it's always going to be, so
> i have no problem with having to hard code offsets or something.
> I'm just trying to figure out how to get the same info, at debug time, on
> g++ compiled objects.
> Is this even possible with g++ compiled objects?

If all you have is a void*, then no, it is not possible in the general
case. Consider

struct timespec
  {
    long int tv_sec;		/* Seconds.  */
    long int tv_nsec;		/* Nanoseconds.  */
  };

I very much doubt that given a void* to a struct timespec, HP aCC will
find out that this is a struct timespec*; that sounds just not
possible.

If you know the base type already, and you know that the base type has
a virtual function table, then you can use the virtual table to find
out the dynamic type. Rather than calling the type info function, I'd
recommend to find out the external symbol name, and use that to infer
the type (perhaps doing a consistency check whether it is really
derived from the base type).

In the new C++ ABI, the vtable will always be at offset 0, so you get
the dynamic type as long as you know you have a polymorphic pointer -
but that is not implemented, yet.

So if you only have a void*, you could do some guess-work to find out
what the dynamic type is. You could scan the fields of the object to
find something that looks like a vtable pointer. On most systems, you
can tell whether it is a vtable pointer if it has an external symbol.
In case they are stripped, it should live in the text segment, and so
on.

I feel that it would pay-off to try to be smart, as long as nothings
breaks in case you guess wrong.

I think this would be a very important feature, so let me know if you
have further questions.

Regards,
Martin

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

* Re: Determining type of an object at debug time.
  2000-03-13 16:35 ` Martin v. Loewis
@ 2000-03-13 17:02   ` Daniel Berlin
  2000-03-13 17:14     ` Martin v. Loewis
  0 siblings, 1 reply; 6+ messages in thread
From: Daniel Berlin @ 2000-03-13 17:02 UTC (permalink / raw)
  To: Martin v. Loewis; +Cc: gcc

<SNIP>
> So if you only have a void*, you could do some guess-work to find
out
> what the dynamic type is. You could scan the fields of the object to
> find something that looks like a vtable pointer. On most systems, you
> can tell whether it is a vtable pointer if it has an external symbol.
> In case they are stripped, it should live in the text segment, and so
> on.
>

Finding the vpointer is easy, we always know where it is.
Given that, i realized i could do just what you described a few hours ago 
during class, and implemented it.
> I feel that it would pay-off to try to be smart, as long as nothings
> breaks in case you guess wrong.
> 
> I think this would be a very important feature, so let me know if you
> have further questions.
> 

Well, then, i have some good news.
I have it working.
Even with multiple inheritance (It figures out the offset properly)
It'll determine the type, and print it (IE print foo2), as if it was that
type, but just as in C++, you won't be able to directly access the
members without explicitly casting it to the derived type.
Although it's a little odd to see:
31              dan=new daniel();
(gdb) p dan
$6 = (daniel *) 0x8051030
(gdb) n
33              dan=new bob();
(gdb)
34              dan=new george2();
(gdb) p dan
$7 = (bob *) 0x8051040
(gdb) n
35 }
(gdb) p dan
$8 = (george2 *) 0x8050064
(gdb)
(notice dan keeps changing type. ALl those classes are inherited from dan,
george2 is multiple inherited from another class and a subclass of dan,
just for corner case sake)
If you want to see what printing those pointers looks like, i just sent
the output to the gdb mailing list, so i don't clutter up this one.

Thanks for all your help,
Dan
>
Regards, > Martin
> 

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

* Re: Determining type of an object at debug time.
  2000-03-13 17:02   ` Daniel Berlin
@ 2000-03-13 17:14     ` Martin v. Loewis
  2000-03-13 17:49       ` Daniel Berlin
  0 siblings, 1 reply; 6+ messages in thread
From: Martin v. Loewis @ 2000-03-13 17:14 UTC (permalink / raw)
  To: dan; +Cc: gcc

> Finding the vpointer is easy, we always know where it is.

How exactly do you do that? There might not even be a vpointer in the
struct... Consider

struct Base{
  char buf[1000];
  int i;
};

struct Derived:virtual Base{
  virtual ~Derived();
};

Given a Base*, how exactly do you find out that the complete object is
a Derived*? Or, worse, what if it is

void foo(void*x){
 ...
}

foo(new Derived);

How do you know x is a Derived* inside foo?

> I have it working.

Very good!

Martin

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

* Re: Determining type of an object at debug time.
  2000-03-13 17:14     ` Martin v. Loewis
@ 2000-03-13 17:49       ` Daniel Berlin
  0 siblings, 0 replies; 6+ messages in thread
From: Daniel Berlin @ 2000-03-13 17:49 UTC (permalink / raw)
  To: Martin v. Loewis; +Cc: gcc

On Tue, 14 Mar 2000, Martin v. Loewis wrote:

> > Finding the vpointer is easy, we always know where it is.
> 
> How exactly do you do that? There might not even be a vpointer in the
> struct... Consider
> 
> struct Base{
>   char buf[1000];
>   int i;
> };
> 
> struct Derived:virtual Base{
>   virtual ~Derived();
> };
> 
> Given a Base*, how exactly do you find out that the complete object is
> a Derived*? Or, worse, what if it is

You can't, in that case.

> 
> void foo(void*x){
>  ...
> }
> 
> foo(new Derived);
> 
> How do you know x is a Derived* inside foo?

Can't.

Then again, RTTI doesn't get it right either:
void foo(void *x)
{
        cout<<typeid(*x).name()<<endl;
        cout<<typeid(x).name()<<endl;
}

when you pass new Derived, it'll print
v
Pv

However, to be fair, if you also add a

Base *bob=(Derived *)x;
and print bob, it'll tell you it's a Base *.
If you try
print (Derived *)bob
It'll tell you it's a "suspicious *", and if you deref it, it'll print 
(gdb) p ((Derived *)bob)[0]
$8 = {
  <Base> = <invalid address>,
  members of Derived:
  _vb$Base = 0x0,
  _vptr$ = 0x0
}
(gdb)

However, if you try the most intuitive thing:
(gdb) p ((Derived *)x)[0]
$7 = (Derived) {
  <Base> = {
    buf =       '\000' <repeats 999 times>,
    i = 0
  },
  members of Derived:
  _vb$Base = 0x8051008,
  _vptr$ = 0x804f020
}
, it works still.
So while it's not perfect, it's almost the best we can do, given the info
we have.
Personally, i'm happy saying "If RTTI can't figure it outat runtime, we
can't figure it out at runtime", on the pathological cases.
But, i'll still make it work as best it can.


> 
> > I have it working.
> 
> Very good!
> 
Thanks,
Dan

> Martin
> 

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

* Re: Determining type of an object at debug time.
@ 2000-03-13 18:30 Mike Stump
  0 siblings, 0 replies; 6+ messages in thread
From: Mike Stump @ 2000-03-13 18:30 UTC (permalink / raw)
  To: dan, gcc

> Date: Mon, 13 Mar 2000 09:45:42 -0800 (PST)
> From: Daniel Berlin <dan@cgsoftware.com>
> To: gcc@gcc.gnu.org

> one of the things i'm working on is determining the type of an
> object at debug time

> Is this even possible with g++ compiled objects?

Yes.

> I could call the __tf functions, but that would require knowing the
> type in the first place.

No.  See type_info::name() and see how the compiler generates code for
it:

#include <stdio.h>
#include <typeinfo>

struct A {
  virtual void foo() { }
} *a;

main() {
  printf("", typeid(*a).name());
}


Doing a call at debug time to get the name is a bit unfortunate (what
if it dumps or changes the program state?)...  Another way, would be
to see what name the __tf function name has, as it does have the name
of the type in it!  For example if the slot has a pointer to __tf1A,
then the dynamic type is in fact 1A, or demangled, A.  We know that
from the name of the __tf function alone without the actual need to
call it.

Hope this helps.

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

end of thread, other threads:[~2000-03-13 18:30 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-03-13  9:45 Determining type of an object at debug time Daniel Berlin
2000-03-13 16:35 ` Martin v. Loewis
2000-03-13 17:02   ` Daniel Berlin
2000-03-13 17:14     ` Martin v. Loewis
2000-03-13 17:49       ` Daniel Berlin
2000-03-13 18:30 Mike Stump

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).