public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* Re: How to setup a breakpoint on constructor
@ 2004-07-16 19:59 Michael Elizabeth Chastain
  2004-07-16 22:15 ` Jim Blandy
  2004-07-17 14:30 ` Eli Zaretskii
  0 siblings, 2 replies; 21+ messages in thread
From: Michael Elizabeth Chastain @ 2004-07-16 19:59 UTC (permalink / raw)
  To: drow, eliz; +Cc: gdb, mec.gnu, rolandz

To take the points in reverse order,

> (B) It exposes the difference between complete and base constructors,
> which is an implementation detail of the C++ ABI that most users don't
> understand.

That is reality.  The reality is that g++ emits two functions in the
object code.  In my opinion, if we try to gloss over that, then we'll
just create more confusion for commands such as 'disassemble' and
'tbreak'.

> (A) It was an ugly interface change to work around an internal
> limitation, and they needed to retrain users to it.

I agree with this part, to an extent.  However, the gdb group
has no control over the fact that there are two object code
functions.

I like the way it worked in gcc 2.95.3.  With gcc 2.95.3,
gcc emits one function with a hidden parameter.  c++ programmers
and gdb are both familiar with hidden parameters ('this').
If I recall correctly, Apple modified gcc 3.X to do something
similar.

Michael C

^ permalink raw reply	[flat|nested] 21+ messages in thread
* Re: How to setup a breakpoint on constructor
@ 2004-07-18 19:29 Michael Elizabeth Chastain
  2004-07-19  3:58 ` Eli Zaretskii
  0 siblings, 1 reply; 21+ messages in thread
From: Michael Elizabeth Chastain @ 2004-07-18 19:29 UTC (permalink / raw)
  To: drow, eliz; +Cc: gdb

eliz> Sorry, I must be missing something: if we put the breakpoint on all
eliz> the instances of the constructor's code, and do that without asking
eliz> the user anything, what UI aspects need to be figured out and
eliz> designed?

What does 'print &A::A()' print?

What does 'disassemble A::A()' print?

There's an assumption in some of gdb's commands that one source code
address maps to one object code address.  The UI has to acknowledge
that some source code addresses map to multiple object code addresses.

Michael C

^ permalink raw reply	[flat|nested] 21+ messages in thread
* Re: How to setup a breakpoint on constructor
@ 2004-07-17 23:17 Michael Elizabeth Chastain
  2004-07-18  5:05 ` Eli Zaretskii
  0 siblings, 1 reply; 21+ messages in thread
From: Michael Elizabeth Chastain @ 2004-07-17 23:17 UTC (permalink / raw)
  To: drow, eliz; +Cc: gdb, mec.gnu, rolandz

> Coincidentally that's what the entire discussion of 1:N breakpoints
> last year was about but no one has had time to implement it.

Right.

1:N breakpoints are better than A::A$base(), but it's been 3 years since
the ctor-breakpoint issue came up, and we don't have anything at all
yet.

> The reason this is hard is that breakpoints by line number inside the
> constructor will still get randomly set on one copy.  Many IDEs will set
> breakpoints in this fashion.

With A::A$base(), the breakpoints will always get set in the complete
object constructor, because that is the only function named A::A().
People will still get only one breakpoint, but it's deterministic, not
random.

But if someone breaks in A::A$base() and then says 'break 1000' to get
into the middle of the function (which I do a lot), then they would get
the breakpoint in the wrong copy!  So even if we disambiguate the
names, the 1:N nature of multiple ctors shines through.

I wish we could persuade gcc to generate a unified ctor.

Michael C

^ permalink raw reply	[flat|nested] 21+ messages in thread
* Re: How to setup a breakpoint on constructor
@ 2004-07-17 10:09 Michael Elizabeth Chastain
  0 siblings, 0 replies; 21+ messages in thread
From: Michael Elizabeth Chastain @ 2004-07-17 10:09 UTC (permalink / raw)
  To: jimb, mec.gnu; +Cc: drow, eliz, gdb, rolandz

jimb> If I remember right, the use of separate complete and base
jimb> constructors is an ABI requirement; the compiler doesn't have the
jimb> option of just generating whatever code it likes.

The ABI does require separate names.

If I recall correctly, Apple implemented this by having separate names
for base ctor and complete ctor (as required by the ABI) and then having
them call a unified constructor.

Gcc optimization can reduce calls from {base,complete}-ctor to
unified-ctor, from call instructions to jump instructions.

Then the debugger just puts ctor breakpoints on the
unified-ctor.

  http://gcc.gnu.org/ml/gcc-patches/2002-08/msg00354.html

Apple folks, have I got that right?

Michael C

^ permalink raw reply	[flat|nested] 21+ messages in thread
* Re: How to setup a breakpoint on constructor
@ 2004-07-15 13:55 Michael Elizabeth Chastain
  2004-07-15 14:09 ` Daniel Jacobowitz
  0 siblings, 1 reply; 21+ messages in thread
From: Michael Elizabeth Chastain @ 2004-07-15 13:55 UTC (permalink / raw)
  To: gdb, rolandz

Hi Roland,

Would you like to try a makeshift and experimental patch?

  ftp://ftp.shout.net/pub/users/mec/ctor-dtor-base.patch

(Patch attached to this message too).

You have to apply this to the libiberty/ subdirectory of a
recent gdb, such as gdb 6.1.1, and then rebuild gdb.

There's a lot of doco in the patch but it rambles.
The basic idea is that I patched the demangler so that
it demangles the different ctor's with different names:

  A::A()
  A::A$base()
  A::A$allocate()

I don't know if it's a good idea for gdb to work this way,
but I think it's worth getting some user feedback.

Testing: I haven't run the test suite with this.
I did test a small program (testsuite/gdb.cp/derivation.cc)
and it works the way I think it should.

Michael C

===

gdb has a problem with g++ constructors and destructors.
This patch resolves the problem in a simple but crude way.

The problem is described in the gdb PROBLEMS file:

  gdb/1091: Constructor breakpoints ignored
  gdb/1193: g++ 3.3 creates multiple constructors: gdb 5.3 can't set breakpoints

  When gcc 3.x compiles a C++ constructor or C++ destructor, it generates
  2 or 3 different versions of the object code.  These versions have
  unique mangled names (they have to, in order for linking to work), but
  they have identical source code names, which leads to a great deal of
  confusion.  Specifically, if you set a breakpoint in a constructor or a
  destructor, gdb will put a breakpoint in one of the versions, but your
  program may execute the other version.  This makes it impossible to set
  breakpoints reliably in constructors or destructors.

  gcc 3.x generates these multiple object code functions in order to
  implement virtual base classes.  gcc 2.x generated just one object code
  function with a hidden parameter, but gcc 3.x conforms to a multi-vendor
  ABI for C++ which requires multiple object code functions.

This patch changes the demangler so that it demangles different
linkage names back to different source code names, so that gdb and
gdb users are no longer confused by several object code functions
with identical source code names.

Before this patch:

  08048544   _ZN1AC1Ev   A::A()
  080486e2   _ZN1AC2Ev   A::A()

After this patch:

  08048544   _ZN1AC1Ev   A::A()
  080486e2   _ZN1AC2Ev   A::A$base()

You still have to understand that g++ emits two (sometimes three)
copies of each constructor.

The constructor with "C1" in the linkage name is the complete
object constructor.  Your program calls this constructor when it
creates an object whose complete type is A, such as "new A".

The constructor with "C2" in the linkage name is the base object
constructor.  Your program calls this constructor when it creates
an object derived from A, such as "new B".  Your program does *not*
call the base object constructor for "new A".

The difference between type "C1" and type "C2" has to do with
virtual base classes.  In C++, the constructor for the complete
object initializes all the virtual bases, and constructors for
base classes do not initialize any virtual bases.

Here is an example:

  class A { ... };
  class B1 : virtual public A { ... };
  class B2 : virtual public A { ... };
  class C  : public B1, public B2 { ... };

When your program creates a C with "new C", your program calls the type
C1 constructor for C::C.  C::C (type C1) calls A::A (type C2) to
initialize the virtual base.  Then C::C (type C1) calls B1::B1 (type C2)
and B2::B2 (type C2) to initialize the normal bases.

If you understand virtual bases, all this should make sense.
If you don't understand virtual bases, just remember the simple rule:
"new Foo" calls Foo::Foo (type C1), and everything that Foo::Foo
for all its bases is of type C2.

There is also a constructor of type "C3".  I have never actually
seen one of these, but it would be marked "Foo::Foo$allocate".

After you apply this patch and rebuild gdb, all the constructors
with names 'Foo::Foo' are the complete object constructors.
'Foo::Foo$base' are the base object constructors, and
'Foo::Foo$allocate' are the allocating object constructors.

All three constructors are compiled from the same source code.
To set a breakpoint on the constructor, you actually have to set
two or three breakpoints (usually just two).  If you take the
short-cut and just break on 'Foo::Foo', you will get breakpoints
whenever 'new Foo' happens, but not when 'new Bar' happens if
Bar is derived from Foo.  You need to break on 'Foo::Foo$base'
to get breakpoints for that.

Michael C

===

Here is a typescript of a gdb session with this patch.
Note how 'A::A()' is called for an object of type A,
and 'A::A$base()' is called for objects of types D, E, F, and G,
which have A as a base class.

Script started on Thu Jul 15 07:14:52 2004

[mec.gnu@berman HEAD]$ ./gdb/gdb ~/tmp/a.out
GNU gdb 2004-07-14-cvs
Copyright 2004 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 "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) break 'A::A^G
A::A$base()  A::A()       

(gdb) break 'A::A()'
Breakpoint 1 at 0x8048547: file derivation.cc, line 7.

(gdb) break 'A::A$base()' 
Breakpoint 2 at 0x80486e5: file derivation.cc, line 7.

(gdb) run
Starting program: /berman/home/mec.gnu/tmp/a.out 

Breakpoint 1, A (this=0xbffff888) at derivation.cc:8
8	        a=1;

(gdb) backtrace
#0  A (this=0xbffff888) at derivation.cc:8
#1  0x08048481 in main () at derivation.cc:203

(gdb) list 203
198	
199	
200	int main(void)
201	{
202	
203	    A a_instance;
204	    B b_instance;
205	    C c_instance;
206	    D d_instance;
207	    E e_instance;

(gdb) cont
Continuing.

Breakpoint 2, A (this=0xbffff850) at derivation.cc:8
8	        a=1;

(gdb) backtrace
#0  A (this=0xbffff850) at derivation.cc:8
#1  0x0804859d in D (this=0xbffff850) at derivation.cc:58
#2  0x080484ae in main () at derivation.cc:206

(gdb) cont
Continuing.

Breakpoint 2, A (this=0xbffff830) at derivation.cc:8
8	        a=1;

(gdb) backtrace
#0  A (this=0xbffff830) at derivation.cc:8
#1  0x080485eb in E (this=0xbffff830) at derivation.cc:74
#2  0x080484bd in main () at derivation.cc:207

(gdb) cont
Continuing.

Breakpoint 2, A (this=0xbffff810) at derivation.cc:8
8	        a=1;

(gdb) backtrace
#0  A (this=0xbffff810) at derivation.cc:8
#1  0x08048639 in F (this=0xbffff810) at derivation.cc:90
#2  0x080484cf in main () at derivation.cc:208

(gdb) cont
Continuing.

Breakpoint 2, A (this=0xbffff7e0) at derivation.cc:8
8	        a=1;

(gdb) backtrace
#0  A (this=0xbffff7e0) at derivation.cc:8
#1  0x08048687 in G (this=0xbffff7e0) at derivation.cc:108
#2  0x080484e1 in main () at derivation.cc:209

(gdb) cont
Continuing.

Program exited normally.

(gdb) quit
[mec.gnu@berman HEAD]$ exit

Script done on Thu Jul 15 07:15:50 2004
===

2004-07-15  Michael Chastain  <mec.gnu@mindspring.com>

	* cp-demangle.c (d_print_comp) Return unique names for
	ctor and dtor names by decorating them with "$base",
	"$allocate", and "$delete".

Index: cp-demangle.c
===================================================================
RCS file: /cvs/src/src/libiberty/cp-demangle.c,v
retrieving revision 1.51
diff -c -3 -p -r1.51 cp-demangle.c
*** cp-demangle.c	28 Jun 2004 18:01:41 -0000	1.51
--- cp-demangle.c	15 Jul 2004 10:53:01 -0000
*************** d_print_comp (dpi, dc)
*** 2978,2988 ****
--- 2978,3012 ----
  
      case DEMANGLE_COMPONENT_CTOR:
        d_print_comp (dpi, dc->u.s_ctor.name);
+       switch (dc->u.s_ctor.kind)
+ 	{
+ 	case gnu_v3_complete_object_ctor:
+ 	  /* no decoration */
+ 	  break;
+ 	case gnu_v3_base_object_ctor:
+ 	  d_append_string_constant (dpi, "$base");
+ 	  break;
+ 	case gnu_v3_complete_object_allocating_ctor:
+ 	  d_append_string_constant (dpi, "$allocate");
+ 	  break;
+ 	}
        return;
  
      case DEMANGLE_COMPONENT_DTOR:
        d_append_char (dpi, '~');
        d_print_comp (dpi, dc->u.s_dtor.name);
+       switch (dc->u.s_dtor.kind)
+ 	{
+ 	case gnu_v3_deleting_dtor:
+ 	  d_append_string_constant (dpi, "$delete");
+ 	  break;
+ 	case gnu_v3_complete_object_dtor:
+ 	  /* no decoration */
+ 	  break;
+ 	case gnu_v3_base_object_dtor:
+ 	  d_append_string_constant (dpi, "$base");
+ 	  break;
+ 	}
        return;
  
      case DEMANGLE_COMPONENT_VTABLE:

^ permalink raw reply	[flat|nested] 21+ messages in thread
* Re: How to setup a breakpoint on constructor
@ 2004-07-15 11:31 Michael Elizabeth Chastain
  2004-07-16 13:17 ` Roland Zerek
  0 siblings, 1 reply; 21+ messages in thread
From: Michael Elizabeth Chastain @ 2004-07-15 11:31 UTC (permalink / raw)
  To: gdb, rolandz

> Is there anything different in the constructor in comparision to normal 
> function since I cannot break the program in there?

Yes, this is a long-standing problem with gdb and gcc 3.X.

See the PROBLEMS file:

  gdb/1091: Constructor breakpoints ignored
  gdb/1193: g++ 3.3 creates multiple constructors: gdb 5.3 can't set breakpoints

  When gcc 3.x compiles a C++ constructor or C++ destructor, it generates
  2 or 3 different versions of the object code.  These versions have
  unique mangled names (they have to, in order for linking to work), but
  they have identical source code names, which leads to a great deal of
  confusion.  Specifically, if you set a breakpoint in a constructor or a
  destructor, gdb will put a breakpoint in one of the versions, but your
  program may execute the other version.  This makes it impossible to set
  breakpoints reliably in constructors or destructors.

  gcc 3.x generates these multiple object code functions in order to
  implement virtual base classes.  gcc 2.x generated just one object code
  function with a hidden parameter, but gcc 3.x conforms to a multi-vendor
  ABI for C++ which requires multiple object code functions.

Things you can try:

. modify your program so that the constructors that you want to
  breakpoint call some function that is not a constructor, and break
  on that.

. run 'nm a.out | c++filt' to find the symbols in your program.
  break on the absolute address: "break *0x01234567".  this is
  very crude (1960's technique) but it does work.

. use nm, c++filt, and 'strip -N' to strip out symbols for
  not-in-charge constructors.  This is scriptable, if someone
  wants to write a little script.

It's a hard problem.

Michael C

^ permalink raw reply	[flat|nested] 21+ messages in thread
* How to setup a breakpoint on constructor
@ 2004-07-15 10:30 Roland Zerek
  0 siblings, 0 replies; 21+ messages in thread
From: Roland Zerek @ 2004-07-15 10:30 UTC (permalink / raw)
  To: gdb

Hi,

Is there anything different in the constructor in comparision to normal 
function since I cannot break the program in there?

I am able to set the breakpoint but it never stops there. I am working with 
mingw (gcc-3.4.0) and gdb-6.0 (from mingw page).

I would appreciate any hints. TIA.

-- 
Roland
r o l a n d z (at) poczta fm

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

end of thread, other threads:[~2004-07-19  3:58 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-07-16 19:59 How to setup a breakpoint on constructor Michael Elizabeth Chastain
2004-07-16 22:15 ` Jim Blandy
2004-07-17 14:30 ` Eli Zaretskii
2004-07-17 14:54   ` Daniel Jacobowitz
  -- strict thread matches above, loose matches on Subject: below --
2004-07-18 19:29 Michael Elizabeth Chastain
2004-07-19  3:58 ` Eli Zaretskii
2004-07-17 23:17 Michael Elizabeth Chastain
2004-07-18  5:05 ` Eli Zaretskii
2004-07-18 18:44   ` Daniel Jacobowitz
2004-07-18 19:03     ` Eli Zaretskii
2004-07-19  3:22       ` Daniel Jacobowitz
2004-07-19 14:51         ` Eli Zaretskii
2004-07-17 10:09 Michael Elizabeth Chastain
2004-07-15 13:55 Michael Elizabeth Chastain
2004-07-15 14:09 ` Daniel Jacobowitz
2004-07-16 11:11   ` Eli Zaretskii
2004-07-16 14:27     ` Daniel Jacobowitz
2004-07-17 10:30       ` Eli Zaretskii
2004-07-15 11:31 Michael Elizabeth Chastain
2004-07-16 13:17 ` Roland Zerek
2004-07-15 10:30 Roland Zerek

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