This is the mail archive of the
gdb@sourceware.cygnus.com
mailing list for the GDB project.
Re: RTTI working for G++
- To: Jimmy Guo <guo at cup dot hp dot com>
- Subject: Re: RTTI working for G++
- From: dan at cgsoftware dot com (Daniel Berlin+mail.gdb)
- Date: 15 Mar 2000 23:30:49 -0500
- Cc: Daniel Berlin <dan at cgsoftware dot com>, gdb at sourceware dot cygnus dot com
- References: <Pine.LNX.4.10.10003151311450.9713-100000@hpcll168.cup.hp.com>
- Reply-To: dan at cgsoftware dot com
Jimmy Guo <guo@cup.hp.com> writes:
> Daniel,
>
> I recently looked into rtti print support and fixed several bugs in that
> area.
As have I.
> Also I've created a test case under gdb.hp/gdb.aCC/. Looks like
> what I changed might work with G++ as well now that you're adding
> support to it.
Possibly, i have a feeling we fixed the same bugs.
> The fix is against HP WDB source, which is based on
> sourceware's as of 1/10/00, so I'm not ready to submit against
> sourceware's tree yet. However, one of the fixes was that when print
> object is on, and one wants to print member / methods of the derived
> type, you can now do so.
See, i didn't consider that a bug, i considered it a lacking
feature. It just wasn't doing the lookup it would need to do, and i've
been too busy to fix it.
> Besides, there're some fixes to handle pointer
> to a derived type and explicit casting of a pointer to a base to a
> derived type.
This i ran up against. I also handled reference types (By pretending
they were pointers).
> I feel that these fixes will complement yours.
Most likely you are correct.
I wasn't ready to go all out and make all the symbol readers fill in
the vtable stuff like it does for HP (it's on my list for sometime).
Seeing as how i would have had to do that, as well as differentiate
between HP aCC debug symbols and other forms of debug symbols, with
another flag, i decided for right now to just put the RTTI stuff for
G++ where it was already, the else block of all the "HAS_VTABLE" if
blocks.
I only actually added one more if, in value_rtti_type, right before
the HP specific stuff starts, that says
"if(TYPE_HAS_VTABLE(known_type)) { do hp stuff } else { do g++ stuff}"
That way, i didn't break any of your HP specific stuff.
Did you notice that it's not really fun to use value_nid (damn
flyspell keeps "correcting" the IND to nid, as if "nid" was really a word
either.) in value_rtti_type? value_nid will call the RTTI routine
during it's lazy evaluation, which gets you into a recursive nightmare
if you aren't careful.
> If
> possible I want to send the diffs of the fixes to you to see if that
> would make it into your patch. Also I can look at your patches as
> well.
I'd be glad to incorporate your fixes into my patch, and i'd
appreciate it if you'd look at mine.
I'll post it to gdb-patches in a few days.
I'm a little confused about the semantics of using_enc/full/top in value_rtti_type.
It seems if i set full to 0, on multiple inheritance, it gets the name
right, but the offset wrong, so you have the right name, and the wrong
values.
If i set full to 1, it gets the name wrong ("suspicious *", which
means it couldn't look it up right), but the values right.
Example of what i mean (when i have bar multiple inheriting
class foo
{
public:
int a;
};
class foo2
{
public:
int b;
};
class bar:public foo1, public foo2
{
public:
int c;
};
foo *foo1=new bar();
print foo1 (full==1 will give "suspicious *", full==0 will give "bar
*")
print *foo1 (full==1 will give the proper values, full==0 gets the
offset wrong, and thus, prints the wrong values)
Even more convoluted,
print foo1->a (with full==1) will access the wrong memory, even though it had it
right 2 seconds before when it printed the full object.
I know i'm setting top properly in all cases.
I have a feeling i'm not quite grasping the way it lays out in memory
yet.
--Dan
>
> - Jimmy Guo, guo@cup.hp.com
>
> On Mon, 13 Mar 2000, Daniel Berlin wrote:
>
> >Okay, i have RTTI working for g++.
> >Well, all except for multiple inheritance.
> >
> >Scratch that last part, i just made it offset properly if you have >1
> >baseclass, so al is good.
> >
> >If i could have one or two volunteers to make sure it's not just my setup,
> >and that all is well, before i post the patches asking for comments, i'd
> >appreciate it.
> >In any case, let me know what you guys think of it so far.
> >If you look at the output, you'll notice that while for printing, it will
> >print the object as if it was it's derived type, when it comes to
> >accessing members/methods, just like in C++, you can't access the members,
> >unless you specifically cast it to that derived type.
> >
> > For those wondering what the patch will do, check this out:
> >
> >The inheritance on these classes in the example looks like this
> >
> >fred is a base
> >dan and bob both inherit directly from fred.
> >george is another base.
> >george2 inherits from george and bob (public george, public bob)
> >
> >I'll rename them so they make more sense as i work up testcases.
> >
> >But anyway, here's some output:
> >
> >GNU gdb 20000204
> >Copyright 1998 Free Software Foundation, Inc.
> >GDB is free software, covered by the GNU General Public License, and you are
> >welcome to change it and/or distribute copies of it under certain conditions.
> >Type "show copying" to see the conditions.
> >There is absolutely no warranty for GDB. Type "show warranty" for details.
> >This GDB was configured as "i386-unknown-freebsdelf4.0".
> >Setting up the environment for debugging gdb.
> >.gdbinit:5: Error in sourced command file:
> >No symbol table is loaded. Use the "file" command.
> >(gdb) file a.out
> >Reading symbols from a.out...done.
> >(gdb) b main
> >Breakpoint 1 at 0x8048918: file a.cc, line 29.
> >(gdb) set print object on
> >(gdb) set print pretty on
> >(gdb) set print vtbl on
> >(gdb) set print array on
> >(gdb) r
> >Starting program: /usr/local/gdb/src/gdb/a.out
> >
> >Breakpoint 1, 0x8048918 in main () at a.cc:29
> >
> >29 {
> >(gdb) n
> >31 dan=new daniel();
> >(gdb) n
> >32 cout <<typeid(*dan).name()<<endl;
> >(gdb) p dan
> >$1 = (daniel *) 0x8051030
> >(gdb) p dan[0]
> >$2 = (daniel) {
> > <fred> = {
> > a = 0,
> > _vptr$ = 0x804f390
> > },
> > members of daniel:
> > b = 0
> >}
> >(gdb) ptype dan
> >type = class fred {
> > public:
> > int a;
> >
> > fred & operator=(fred const &);
> > fred(fred const &);
> > fred(void);
> > virtual int ab(void);
> >} *
> >(gdb) p dan[0]->b
> >There is no member or method named b.
> >(gdb) n
> >6daniel
> >33 dan=new bob();
> >(gdb)
> >34 dan=new george2();
> >(gdb) p dan
> >$3 = (bob *) 0x8051040
> >(gdb) p dan[0]
> >$4 = (bob) {
> > <fred> = {
> > a = 0,
> > _vptr$ = 0x804f378
> > },
> > members of bob:
> > c = 0
> >}
> >(gdb) p dan[0].c
> >There is no member or method named c.
> >(gdb) n
> >35 dan->a=55;
> >(gdb) p dan[0]
> >$5 = (george2 [incomplete object]) {
> > <george> = {
> > d = 0
> > },
> > <bob> = {
> > <fred> = {
> > a = 0,
> > _vptr$ = 0x804f360
> > },
> > members of bob:
> > c = 0
> > },
> > members of george2:
> > e = 0
> >}
> >(gdb) l
> >30 fred *dan;
> >31 dan=new daniel();
> >32 cout <<typeid(*dan).name()<<endl;
> >33 dan=new bob();
> >34 dan=new george2();
> >35 dan->a=55;
> >36 cout <<typeid(*dan).name()<<endl;
> >37 }
> >38
> >(gdb) n
> >36 cout <<typeid(*dan).name()<<endl;
> >(gdb) p dan
> >$7 = (suspicious *) 0x8050064
> >(gdb) p dan[0]
> >$8 = (george2 [incomplete object]) {
> > <george> = {
> > d = 0
> > },
> > <bob> = {
> > <fred> = {
> > a = 55,
> > _vptr$ = 0x804f360
> > },
> > members of bob:
> > c = 0
> > },
> > members of george2:
> > e = 0
> >}
> >(gdb) c
> >Continuing.
> >7george2
> >
> >Program exited normally.
> >(gdb) q
> >
> >Script done on Mon Mar 13 19:34:51 2000