public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* breakpoints in constructors
@ 2003-04-18 20:04 David Carlton
  2003-04-24 14:50 ` Daniel Jacobowitz
  0 siblings, 1 reply; 16+ messages in thread
From: David Carlton @ 2003-04-18 20:04 UTC (permalink / raw)
  To: gdb; +Cc: Daniel Jacobowitz

I might have some time over the next few weeks (/months) to work on
the "breakpoints in constructors" issue.  Daniel: clearly you've
thought about this already, so if you happen to have time to do a bit
of a brain dump on the issue at some point, I'd appreciate it.

David Carlton
carlton@bactrian.org

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

* Re: breakpoints in constructors
  2003-04-18 20:04 breakpoints in constructors David Carlton
@ 2003-04-24 14:50 ` Daniel Jacobowitz
  2003-04-24 22:02   ` Paul Koning
  2003-04-29 20:45   ` Paul Koning
  0 siblings, 2 replies; 16+ messages in thread
From: Daniel Jacobowitz @ 2003-04-24 14:50 UTC (permalink / raw)
  To: David Carlton; +Cc: gdb

On Fri, Apr 18, 2003 at 01:04:46PM -0700, David Carlton wrote:
> I might have some time over the next few weeks (/months) to work on
> the "breakpoints in constructors" issue.  Daniel: clearly you've
> thought about this already, so if you happen to have time to do a bit
> of a brain dump on the issue at some point, I'd appreciate it.

Sure.  First of all, a rough overview of the problem; might as well
keep everything in one place.

With the new GCC 3.x multi-vendor C++ ABI, constructors are implemented
as multiple functions:
  C1, the complete object constructor [in-charge]
  C2, the base object constructor [not-in-charge]
  C3, the allocating constructor [not currently used]

Similarly for destructors - most of the rest of this message applies to
destructors too.  The base constructor is generally called for the base
objects of a derived class, esp. with virtual inheritance; it's been a
while since I looked at exactly when.

GCC has chosen to implement this by duplicating the function, including
any user-provided code and any compiler-added code.  A better
implementation would have one copy and labels for multiple entry
points, on systems where that is supported; that's temporarily tabled
pending a better description of the GCC tree structure to describe
multiple entry points.

So the end result is that we start with:
class C {
  public: C();
};

C::C()
{
  // do stuff
}

And there are two copies of that function.  If we use the demangler in
non-verbose mode, we get the same demangled name for both of them:
C::C().  If we use it in verbose mode we get C::C[in-charge]() and
C::C[not-in-charge](), but using verbose mode has other issues for GDB;
it's too verbose/obscure in some places.

So there are two interesting problems:
  - What happens when I say "break C::C"?
  - What happens when I say "break <line>", pointing at the "do stuff"?

So that's the general problem.


Ideally, when we say "break C::C" we will get multiple breakpoints
automatically.  Not to be confused with find_methods/decode_line_2!
We'd still get a menu with two choices if there was a copy constructor
and a default constructor; but choosing either one would place two
breakpoints.

What would this mean for "info breakpoints"?  Would they be one
breakpoint with multiple addresses or visible to the user as two
breakpoints?  I'd prefer the former but I believe there was some
disagreement.  I don't know what current art in other debuggers is;
does anybody?

Similarly when we say "break line", IMO, there should be multiple
breakpoints.  This is even harder; in optimized code we may have
multiple ranges of PC for a particular line even in the same function
(and IMO we should be placing more than one breakpoint in that case);
here we have multiple ranges across different functions.  Placing one
user-visible breakpoint per range would get out of hand pretty fast. 
With the current breakpoint implementation even placing all the
breakpoints would get out of hand pretty fast, since we remove all
breakpoints from memory at each stop.  I think that's fixable.

[Assuming an improved breakpoint layer, can we place a breakpoint on
every possible instruction in a line?  With variable-length
instructions this is very hard; with jump tables in text sections it
might be downright impossible, since we don't know what is code and
what isn't.  Placing a breakpoint at the beginning of every distinct
range, while not perfect, is still an improvement.

However, it's kind of confusing.  Stepping through optimized code you
might hit the "one" breakpoint multiple times.  Bears some thinking
about.]

All of this eventually ties in to debugging inlined functions and
templated functions, which are harder versions of the same thing.

Can't think of anything else at the moment...

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

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

* Re: breakpoints in constructors
  2003-04-24 14:50 ` Daniel Jacobowitz
@ 2003-04-24 22:02   ` Paul Koning
  2003-04-25  0:30     ` Daniel Jacobowitz
  2003-04-29 20:45   ` Paul Koning
  1 sibling, 1 reply; 16+ messages in thread
From: Paul Koning @ 2003-04-24 22:02 UTC (permalink / raw)
  To: drow; +Cc: carlton, gdb

>>>>> "Daniel" == Daniel Jacobowitz <drow@mvista.com> writes:

 Daniel> On Fri, Apr 18, 2003 at 01:04:46PM -0700, David Carlton
 Daniel> wrote:
 >> I might have some time over the next few weeks (/months) to work
 >> on the "breakpoints in constructors" issue.  Daniel: clearly
 >> you've thought about this already, so if you happen to have time
 >> to do a bit of a brain dump on the issue at some point, I'd
 >> appreciate it.

 Daniel> Sure.  First of all, a rough overview of the problem; might
 Daniel> as well keep everything in one place.

 Daniel> With the new GCC 3.x multi-vendor C++ ABI, constructors are
 Daniel> implemented as multiple functions: C1, the complete object
 Daniel> constructor [in-charge] C2, the base object constructor
 Daniel> [not-in-charge] C3, the allocating constructor [not currently
 Daniel> used]

 Daniel> Similarly for destructors - most of the rest of this message
 Daniel> applies to destructors too.  The base constructor is
 Daniel> generally called for the base objects of a derived class,
 Daniel> esp. with virtual inheritance; it's been a while since I
 Daniel> looked at exactly when.

 Daniel> GCC has chosen to implement this by duplicating the function,
 Daniel> including any user-provided code and any compiler-added code.
 Daniel> A better implementation would have one copy and labels for
 Daniel> multiple entry points, on systems where that is supported;
 Daniel> that's temporarily tabled pending a better description of the
 Daniel> GCC tree structure to describe multiple entry points.

Maybe this is off base, but Fortran has always had multiple entry
points, and GCC supports Fortran (g77), so presumably there is a way
to represent this in the tree structure already.

   paul

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

* Re: breakpoints in constructors
  2003-04-24 22:02   ` Paul Koning
@ 2003-04-25  0:30     ` Daniel Jacobowitz
  0 siblings, 0 replies; 16+ messages in thread
From: Daniel Jacobowitz @ 2003-04-25  0:30 UTC (permalink / raw)
  To: Paul Koning; +Cc: carlton, gdb

On Thu, Apr 24, 2003 at 06:02:24PM -0400, Paul Koning wrote:
> >>>>> "Daniel" == Daniel Jacobowitz <drow@mvista.com> writes:
> 
>  Daniel> On Fri, Apr 18, 2003 at 01:04:46PM -0700, David Carlton
>  Daniel> wrote:
>  >> I might have some time over the next few weeks (/months) to work
>  >> on the "breakpoints in constructors" issue.  Daniel: clearly
>  >> you've thought about this already, so if you happen to have time
>  >> to do a bit of a brain dump on the issue at some point, I'd
>  >> appreciate it.
> 
>  Daniel> Sure.  First of all, a rough overview of the problem; might
>  Daniel> as well keep everything in one place.
> 
>  Daniel> With the new GCC 3.x multi-vendor C++ ABI, constructors are
>  Daniel> implemented as multiple functions: C1, the complete object
>  Daniel> constructor [in-charge] C2, the base object constructor
>  Daniel> [not-in-charge] C3, the allocating constructor [not currently
>  Daniel> used]
> 
>  Daniel> Similarly for destructors - most of the rest of this message
>  Daniel> applies to destructors too.  The base constructor is
>  Daniel> generally called for the base objects of a derived class,
>  Daniel> esp. with virtual inheritance; it's been a while since I
>  Daniel> looked at exactly when.
> 
>  Daniel> GCC has chosen to implement this by duplicating the function,
>  Daniel> including any user-provided code and any compiler-added code.
>  Daniel> A better implementation would have one copy and labels for
>  Daniel> multiple entry points, on systems where that is supported;
>  Daniel> that's temporarily tabled pending a better description of the
>  Daniel> GCC tree structure to describe multiple entry points.
> 
> Maybe this is off base, but Fortran has always had multiple entry
> points, and GCC supports Fortran (g77), so presumably there is a way
> to represent this in the tree structure already.

I believe that by the time Fortran hands off, we're not in trees any
more - that's been a longstanding complaint about g77, it RTLs too
easy.  But I might be mistaken about that.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

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

* Re: breakpoints in constructors
  2003-04-24 14:50 ` Daniel Jacobowitz
  2003-04-24 22:02   ` Paul Koning
@ 2003-04-29 20:45   ` Paul Koning
  2003-04-29 21:24     ` Daniel Jacobowitz
  1 sibling, 1 reply; 16+ messages in thread
From: Paul Koning @ 2003-04-29 20:45 UTC (permalink / raw)
  To: drow; +Cc: carlton, gdb

>>>>> "Daniel" == Daniel Jacobowitz <drow@mvista.com> writes:

 Daniel> On Fri, Apr 18, 2003 at 01:04:46PM -0700, David Carlton
 Daniel> wrote:
 >> I might have some time over the next few weeks (/months) to work
 >> on the "breakpoints in constructors" issue.  Daniel: clearly
 >> you've thought about this already, so if you happen to have time
 >> to do a bit of a brain dump on the issue at some point, I'd
 >> appreciate it.

 Daniel> Sure.  First of all, a rough overview of the problem; might
 Daniel> as well keep everything in one place.

 Daniel> With the new GCC 3.x multi-vendor C++ ABI, constructors are
 Daniel> implemented as multiple functions: C1, the complete object
 Daniel> constructor [in-charge] C2, the base object constructor
 Daniel> [not-in-charge] C3, the allocating constructor [not currently
 Daniel> used]

 Daniel> Similarly for destructors - most of the rest of this message
 Daniel> applies to destructors too.  The base constructor is
 Daniel> generally called for the base objects of a derived class,
 Daniel> esp. with virtual inheritance; it's been a while since I
 Daniel> looked at exactly when.

 Daniel> GCC has chosen to implement this by duplicating the function,
 Daniel> including any user-provided code and any compiler-added code.
 Daniel> A better implementation would have one copy and labels for
 Daniel> multiple entry points, on systems where that is supported;
 Daniel> that's temporarily tabled pending a better description of the
 Daniel> GCC tree structure to describe multiple entry points.

I looked at a few examples to see how they differ.  Didn't see any
where the two constructors that gcc generates differ at all.  Ditto
for the two (in charge vs. not in charge) destructors.

The "deleting" constructor does what the name suggests, it frees the
item at the end.  Since the difference is at the end, that doesn't
sound like a case where multiple entry points can help.

Couldn't one constructor/destructor call another, so that there one
"bottom level" constructor or destructor where all three variants
eventually end up?  Then that would be the one you'd want to match
when you set a breakpoint by name or by line.

The only drawback I can see is that you'd see an extraneous frame in
the callstack.

    paul


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

* Re: breakpoints in constructors
  2003-04-29 20:45   ` Paul Koning
@ 2003-04-29 21:24     ` Daniel Jacobowitz
  2003-04-30 19:04       ` Michael Eager
  0 siblings, 1 reply; 16+ messages in thread
From: Daniel Jacobowitz @ 2003-04-29 21:24 UTC (permalink / raw)
  To: Paul Koning; +Cc: carlton, gdb

On Tue, Apr 29, 2003 at 04:45:06PM -0400, Paul Koning wrote:
> >>>>> "Daniel" == Daniel Jacobowitz <drow@mvista.com> writes:
> 
>  Daniel> On Fri, Apr 18, 2003 at 01:04:46PM -0700, David Carlton
>  Daniel> wrote:
>  >> I might have some time over the next few weeks (/months) to work
>  >> on the "breakpoints in constructors" issue.  Daniel: clearly
>  >> you've thought about this already, so if you happen to have time
>  >> to do a bit of a brain dump on the issue at some point, I'd
>  >> appreciate it.
> 
>  Daniel> Sure.  First of all, a rough overview of the problem; might
>  Daniel> as well keep everything in one place.
> 
>  Daniel> With the new GCC 3.x multi-vendor C++ ABI, constructors are
>  Daniel> implemented as multiple functions: C1, the complete object
>  Daniel> constructor [in-charge] C2, the base object constructor
>  Daniel> [not-in-charge] C3, the allocating constructor [not currently
>  Daniel> used]
> 
>  Daniel> Similarly for destructors - most of the rest of this message
>  Daniel> applies to destructors too.  The base constructor is
>  Daniel> generally called for the base objects of a derived class,
>  Daniel> esp. with virtual inheritance; it's been a while since I
>  Daniel> looked at exactly when.
> 
>  Daniel> GCC has chosen to implement this by duplicating the function,
>  Daniel> including any user-provided code and any compiler-added code.
>  Daniel> A better implementation would have one copy and labels for
>  Daniel> multiple entry points, on systems where that is supported;
>  Daniel> that's temporarily tabled pending a better description of the
>  Daniel> GCC tree structure to describe multiple entry points.
> 
> I looked at a few examples to see how they differ.  Didn't see any
> where the two constructors that gcc generates differ at all.  Ditto
> for the two (in charge vs. not in charge) destructors.
> 
> The "deleting" constructor does what the name suggests, it frees the
> item at the end.  Since the difference is at the end, that doesn't
> sound like a case where multiple entry points can help.
> 
> Couldn't one constructor/destructor call another, so that there one
> "bottom level" constructor or destructor where all three variants
> eventually end up?  Then that would be the one you'd want to match
> when you set a breakpoint by name or by line.
> 
> The only drawback I can see is that you'd see an extraneous frame in
> the callstack.

Wow, Paul, you're really on top of this one.  Yes, that's what Apple
implemented, and I'm looking over their patches right now :)  There are
some quirks in the implementation which are throwing me for a loop.

The constructors will differ in some cases involving virtual bases;
that's what they're for.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

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

* Re: breakpoints in constructors
  2003-04-29 21:24     ` Daniel Jacobowitz
@ 2003-04-30 19:04       ` Michael Eager
  2003-04-30 19:11         ` Paul Koning
  2003-04-30 19:19         ` Daniel Jacobowitz
  0 siblings, 2 replies; 16+ messages in thread
From: Michael Eager @ 2003-04-30 19:04 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: Paul Koning, carlton, gdb

Daniel Jacobowitz wrote:
> 
> On Tue, Apr 29, 2003 at 04:45:06PM -0400, Paul Koning wrote:
> > >>>>> "Daniel" == Daniel Jacobowitz <drow@mvista.com> writes:
> >
> >  Daniel> On Fri, Apr 18, 2003 at 01:04:46PM -0700, David Carlton
> >  Daniel> wrote:
> >  >> I might have some time over the next few weeks (/months) to work
> >  >> on the "breakpoints in constructors" issue.  Daniel: clearly
> >  >> you've thought about this already, so if you happen to have time
> >  >> to do a bit of a brain dump on the issue at some point, I'd
> >  >> appreciate it.
> >
> >  Daniel> Sure.  First of all, a rough overview of the problem; might
> >  Daniel> as well keep everything in one place.
> >
> >  Daniel> With the new GCC 3.x multi-vendor C++ ABI, constructors are
> >  Daniel> implemented as multiple functions: C1, the complete object
> >  Daniel> constructor [in-charge] C2, the base object constructor
> >  Daniel> [not-in-charge] C3, the allocating constructor [not currently
> >  Daniel> used]
> >
> >  Daniel> Similarly for destructors - most of the rest of this message
> >  Daniel> applies to destructors too.  The base constructor is
> >  Daniel> generally called for the base objects of a derived class,
> >  Daniel> esp. with virtual inheritance; it's been a while since I
> >  Daniel> looked at exactly when.
> >
> >  Daniel> GCC has chosen to implement this by duplicating the function,
> >  Daniel> including any user-provided code and any compiler-added code.
> >  Daniel> A better implementation would have one copy and labels for
> >  Daniel> multiple entry points, on systems where that is supported;
> >  Daniel> that's temporarily tabled pending a better description of the
> >  Daniel> GCC tree structure to describe multiple entry points.
> >
> > I looked at a few examples to see how they differ.  Didn't see any
> > where the two constructors that gcc generates differ at all.  Ditto
> > for the two (in charge vs. not in charge) destructors.
> >
> > The "deleting" constructor does what the name suggests, it frees the
> > item at the end.  Since the difference is at the end, that doesn't
> > sound like a case where multiple entry points can help.
> >
> > Couldn't one constructor/destructor call another, so that there one
> > "bottom level" constructor or destructor where all three variants
> > eventually end up?  Then that would be the one you'd want to match
> > when you set a breakpoint by name or by line.
> >
> > The only drawback I can see is that you'd see an extraneous frame in
> > the callstack.
> 
> Wow, Paul, you're really on top of this one.  Yes, that's what Apple
> implemented, and I'm looking over their patches right now :)  There are
> some quirks in the implementation which are throwing me for a loop.
> 
> The constructors will differ in some cases involving virtual bases;
> that's what they're for.

I think that you can generate a jump rather than a call, so there is no 
extraneous call frame on the stack.  (I think that's what the Apple patch
does, actually.)


-- 
Michael Eager    Eager Consulting     eager@eagercon.com
1960 Park Blvd., Palo Alto, CA 94306  650-325-8077

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

* Re: breakpoints in constructors
  2003-04-30 19:04       ` Michael Eager
@ 2003-04-30 19:11         ` Paul Koning
  2003-04-30 19:19         ` Daniel Jacobowitz
  1 sibling, 0 replies; 16+ messages in thread
From: Paul Koning @ 2003-04-30 19:11 UTC (permalink / raw)
  To: eager; +Cc: drow, carlton, gdb

>>>>> "Michael" == Michael Eager <eager@eagercon.com> writes:

 Michael> I think that you can generate a jump rather than a call, so
 Michael> there is no extraneous call frame on the stack.  (I think
 Michael> that's what the Apple patch does, actually.)

You can jump in the same cases where you can use multiple entry
points: function A does some stuff and then finishes by doing what B
does.  But if function A starts with what B does and then does
something else (e.g., the deleting constructor) then you can't jump.

Actually, if you pretend it's all calls, the optimizer will already
turn some of them into jumps ("tail call") automagically.

     paul

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

* Re: breakpoints in constructors
  2003-04-30 19:04       ` Michael Eager
  2003-04-30 19:11         ` Paul Koning
@ 2003-04-30 19:19         ` Daniel Jacobowitz
  1 sibling, 0 replies; 16+ messages in thread
From: Daniel Jacobowitz @ 2003-04-30 19:19 UTC (permalink / raw)
  To: Michael Eager; +Cc: Paul Koning, carlton, gdb

On Wed, Apr 30, 2003 at 11:58:16AM -0700, Michael Eager wrote:
> Daniel Jacobowitz wrote:
> > 
> > On Tue, Apr 29, 2003 at 04:45:06PM -0400, Paul Koning wrote:
> > > >>>>> "Daniel" == Daniel Jacobowitz <drow@mvista.com> writes:
> > >
> > >  Daniel> On Fri, Apr 18, 2003 at 01:04:46PM -0700, David Carlton
> > >  Daniel> wrote:
> > >  >> I might have some time over the next few weeks (/months) to work
> > >  >> on the "breakpoints in constructors" issue.  Daniel: clearly
> > >  >> you've thought about this already, so if you happen to have time
> > >  >> to do a bit of a brain dump on the issue at some point, I'd
> > >  >> appreciate it.
> > >
> > >  Daniel> Sure.  First of all, a rough overview of the problem; might
> > >  Daniel> as well keep everything in one place.
> > >
> > >  Daniel> With the new GCC 3.x multi-vendor C++ ABI, constructors are
> > >  Daniel> implemented as multiple functions: C1, the complete object
> > >  Daniel> constructor [in-charge] C2, the base object constructor
> > >  Daniel> [not-in-charge] C3, the allocating constructor [not currently
> > >  Daniel> used]
> > >
> > >  Daniel> Similarly for destructors - most of the rest of this message
> > >  Daniel> applies to destructors too.  The base constructor is
> > >  Daniel> generally called for the base objects of a derived class,
> > >  Daniel> esp. with virtual inheritance; it's been a while since I
> > >  Daniel> looked at exactly when.
> > >
> > >  Daniel> GCC has chosen to implement this by duplicating the function,
> > >  Daniel> including any user-provided code and any compiler-added code.
> > >  Daniel> A better implementation would have one copy and labels for
> > >  Daniel> multiple entry points, on systems where that is supported;
> > >  Daniel> that's temporarily tabled pending a better description of the
> > >  Daniel> GCC tree structure to describe multiple entry points.
> > >
> > > I looked at a few examples to see how they differ.  Didn't see any
> > > where the two constructors that gcc generates differ at all.  Ditto
> > > for the two (in charge vs. not in charge) destructors.
> > >
> > > The "deleting" constructor does what the name suggests, it frees the
> > > item at the end.  Since the difference is at the end, that doesn't
> > > sound like a case where multiple entry points can help.
> > >
> > > Couldn't one constructor/destructor call another, so that there one
> > > "bottom level" constructor or destructor where all three variants
> > > eventually end up?  Then that would be the one you'd want to match
> > > when you set a breakpoint by name or by line.
> > >
> > > The only drawback I can see is that you'd see an extraneous frame in
> > > the callstack.
> > 
> > Wow, Paul, you're really on top of this one.  Yes, that's what Apple
> > implemented, and I'm looking over their patches right now :)  There are
> > some quirks in the implementation which are throwing me for a loop.
> > 
> > The constructors will differ in some cases involving virtual bases;
> > that's what they're for.
> 
> I think that you can generate a jump rather than a call, so there is no 
> extraneous call frame on the stack.  (I think that's what the Apple patch
> does, actually.)

Ah, yes, you're right.  But you end up with the extra call if you
compile with -O0.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

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

* Re: Breakpoints in constructors
  2005-12-26  7:52 ` Amit Kale
@ 2005-12-27  4:07   ` Jim Blandy
  0 siblings, 0 replies; 16+ messages in thread
From: Jim Blandy @ 2005-12-27  4:07 UTC (permalink / raw)
  To: Amit Kale; +Cc: gdb

On 12/25/05, Amit Kale <amitkale@linsyssoft.com> wrote:
> Would you like us to rebase this patch to current cvs tree to make it easier
> to review it?

I can look over the original patch when I come back from vacation on Mon, Jan 2.

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

* Re: Breakpoints in constructors
  2005-12-15 14:06 Breakpoints " Amit Kale
@ 2005-12-26  7:52 ` Amit Kale
  2005-12-27  4:07   ` Jim Blandy
  0 siblings, 1 reply; 16+ messages in thread
From: Amit Kale @ 2005-12-26  7:52 UTC (permalink / raw)
  To: gdb

Would you like us to rebase this patch to current cvs tree to make it easier 
to review it?
-Amit

On Thursday 15 Dec 2005 7:35 pm, Amit Kale wrote:
> Hi,
>
> I am posting this on behalf of TimeSys Corporation. We had developed a fix
> (read hack) to enable gdb to place breakpoints in C++ constructors. This
> work was done on gdb 6.2 (patch attached).
>
> I was planning to post this patch after rebasing to current gdb, but then
> found that there was some communication on this earlier. I would like to
> know gdb guru's opinion on this patch. Does this appear to much of a hack?
> Someone else working on a better solution?
>
> Any help on this patch and/or directions for making this right will be
> highly appreciated.
> Thanks.
> -Amit

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

* Breakpoints in constructors
@ 2005-12-15 14:06 Amit Kale
  2005-12-26  7:52 ` Amit Kale
  0 siblings, 1 reply; 16+ messages in thread
From: Amit Kale @ 2005-12-15 14:06 UTC (permalink / raw)
  To: gdb

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

Hi,

I am posting this on behalf of TimeSys Corporation. We had developed a fix 
(read hack) to enable gdb to place breakpoints in C++ constructors. This work 
was done on gdb 6.2 (patch attached).

I was planning to post this patch after rebasing to current gdb, but then 
found that there was some communication on this earlier. I would like to know 
gdb guru's opinion on this patch. Does this appear to much of a hack? Someone 
else working on a better solution?

Any help on this patch and/or directions for making this right will be highly 
appreciated.
Thanks.
-Amit

[-- Attachment #2: gdb-6.2-brkconstr.patch --]
[-- Type: text/x-diff, Size: 22049 bytes --]

Index: gdb-6.2/gdb/breakpoint.c
===================================================================
--- gdb-6.2.orig/gdb/breakpoint.c	2004-09-21 16:12:25.000000000 +0530
+++ gdb-6.2/gdb/breakpoint.c	2004-09-21 19:05:52.000000000 +0530
@@ -4463,7 +4463,8 @@
 	make_cleanup (xfree, canonical[0]);
     }
 
-  resolve_sal_pc (&sals.sals[0]);
+  /* solib hook doesn't have multiple instances */
+  resolve_sal_pc (&sals, NULL, NULL);
 
   /* Remove the canonical strings from the cleanup, they are needed below.  */
   if (canonical != (char **) NULL)
@@ -5018,36 +5019,41 @@
 
 static void
 breakpoint_sals_to_pc (struct symtabs_and_lines *sals,
-		       char *address)
+                       char *address, char ***addr_string)
 {    
-  int i;
+  int i, j;
   for (i = 0; i < sals->nelts; i++)
     {
-      resolve_sal_pc (&sals->sals[i]);
-
-      /* It's possible for the PC to be nonzero, but still an illegal
-         value on some targets.
+      j = i;
+      resolve_sal_pc (sals, &i, addr_string);
 
-         For example, on HP-UX if you start gdb, and before running the
-         inferior you try to set a breakpoint on a shared library function
-         "foo" where the inferior doesn't call "foo" directly but does
-         pass its address to another function call, then we do find a
-         minimal symbol for the "foo", but it's address is invalid.
-         (Appears to be an index into a table that the loader sets up
-         when the inferior is run.)
+      while (j <= i)
+        {
+          /* It's possible for the PC to be nonzero, but still an illegal
+             value on some targets.
+
+             For example, on HP-UX if you start gdb, and before running the
+             inferior you try to set a breakpoint on a shared library function
+             "foo" where the inferior doesn't call "foo" directly but does
+             pass its address to another function call, then we do find a
+             minimal symbol for the "foo", but it's address is invalid.
+             (Appears to be an index into a table that the loader sets up
+             when the inferior is run.)
 
-         Give the target a chance to bless sals.sals[i].pc before we
-         try to make a breakpoint for it. */
+             Give the target a chance to bless sals.sals[i].pc before we
+             try to make a breakpoint for it. */
 #ifdef DEPRECATED_PC_REQUIRES_RUN_BEFORE_USE
-      if (DEPRECATED_PC_REQUIRES_RUN_BEFORE_USE (sals->sals[i].pc))
-	{
-	  if (address == NULL)
-	    error ("Cannot break without a running program.");
-	  else
-	    error ("Cannot break on %s without a running program.", 
-		   address);
-	}
+          if (DEPRECATED_PC_REQUIRES_RUN_BEFORE_USE (sals->sals[i].pc))
+	     {
+	       if (address == NULL)
+	         error ("Cannot break without a running program.");
+	       else
+	         error ("Cannot break on %s without a running program.", 
+		        address);
+	     }
 #endif
+          j++;
+        }
     }
 }
 
@@ -5148,6 +5154,12 @@
   else if (!sals.nelts)
     return GDB_RC_FAIL;
 
+  /* Resolve all line numbers to PC's and verify that the addresses
+     are ok for the target. This function call can result in an increase in
+     the number of nelts */
+  if (!pending)
+    breakpoint_sals_to_pc (&sals, addr_start, &addr_string);
+
   /* Create a chain of things that always need to be cleaned up. */
   old_chain = make_cleanup (null_cleanup, 0);
 
@@ -5183,11 +5195,6 @@
 	make_cleanup (xfree, addr_string[i]);
     }
 
-  /* Resolve all line numbers to PC's and verify that the addresses
-     are ok for the target.  */
-  if (!pending)
-    breakpoint_sals_to_pc (&sals, addr_start);
-
   /* Verify that condition can be parsed, before setting any
      breakpoints.  Allocate a separate condition expression for each
      breakpoint. */
@@ -5326,6 +5333,11 @@
   if (!sals.nelts)
     return GDB_RC_NONE;
 
+  /* Resolve all line numbers to PC's and verify that the addresses
+     are ok for the target. This function call can result in an increase in
+     the number of nelts */
+  breakpoint_sals_to_pc (&sals, args->address, &addr_string);
+
   /* Create a chain of things at always need to be cleaned up. */
   old_chain = make_cleanup (null_cleanup, 0);
 
@@ -5364,9 +5376,6 @@
   if (*address_end != '\0')
     error ("Garbage %s following breakpoint address", address_end);
 
-  /* Resolve all line numbers to PC's.  */
-  breakpoint_sals_to_pc (&sals, args->address);
-
   /* Verify that conditions can be parsed, before setting any
      breakpoints.  */
   for (i = 0; i < sals.nelts; i++)
@@ -5576,16 +5585,34 @@
 }
 
 
-/* Helper function for break_command_1 and disassemble_command.  */
+/* Helper function for break_command_1 and disassemble_command. 
+   If index is NULL doesn't extend sals. Assumes that there is only one sals
+   entry. Otherwise extends sals if more than one
+   entry is found for given line number.
+ */
 
 void
-resolve_sal_pc (struct symtab_and_line *sal)
+resolve_sal_pc (struct symtabs_and_lines *sals, int *index, char
+		***addr_string)
 {
   CORE_ADDR pc;
+  struct symtab_and_line *sal;
+  int ind = 0;
+  int i;
+  CORE_ADDR origpc;
+  extern int debugkernel;
+
+  /* Multiple breakpoints feature conflicts with assembly code in kernel */
+  if (debugkernel)
+    index = NULL;
+  if (index)
+    sal = &sals->sals[*index];
+  else
+    sal = &sals->sals[0];
 
   if (sal->pc == 0 && sal->symtab != NULL)
     {
-      if (!find_line_pc (sal->symtab, sal->line, &pc))
+      if ((ind = find_line_pc (sal->symtab, sal->line, &pc, ind)) == 0)
 	error ("No line %d in file \"%s\".",
 	       sal->line, sal->symtab->filename);
       sal->pc = pc;
@@ -5623,6 +5650,54 @@
 	    }
 	}
     }
+    if (index && sal->pc)
+      {
+        struct symbol *psym;
+        struct symbol *nsym;
+	struct block *bl;
+	origpc = sal->pc;
+	bl = block_for_pc(pc);
+	psym = bl ? block_function(bl): NULL;
+	while ((ind = find_line_pc (sal->symtab, sal->line, &pc, ind)) != 0)
+	  {
+	    /* Insert this entry into sals if it isn't the duplicate of the
+	     * first entry and if it doesn't appear in the same function as the
+	     * previous entry */
+	    bl = block_for_pc(pc);
+	    nsym = bl ? block_function(bl): NULL;
+	    if (pc != origpc && psym != nsym)
+	      {
+		psym = nsym;
+		sals->sals = xrealloc(sals->sals, sizeof (struct symtab_and_line) *
+				      (sals->nelts + 1));
+		if (addr_string)
+		  *addr_string = xrealloc(*addr_string, sizeof (char **) *
+					  (sals->nelts + 1));
+
+		for (i = sals->nelts; i > *index; i--)
+		  {
+		    sals->sals[i] = sals->sals[i - 1];
+		    if (addr_string)
+		      (*addr_string)[i] = (*addr_string)[i - 1];
+		  }
+		sals->nelts++;
+		(*index)++;
+		sals->sals[*index].pc = pc;
+		if (addr_string)
+		  {
+		    if ((*addr_string)[*index - 1])
+		      {
+			(*addr_string)[*index] =
+			      savestring((*addr_string)[*index - 1],
+					 strlen((*addr_string)[*index - 1]));
+		      }
+		    else
+		      (*addr_string)[*index] = NULL;
+		  }
+		sal = &sals->sals[*index];
+	      }
+	  }
+      }
 }
 
 void
@@ -6068,12 +6143,15 @@
     error ("Couldn't get information on specified line.");
 
   sal = sals.sals[0];
-  xfree (sals.sals);	/* malloc'd, so freed */
 
   if (*arg)
-    error ("Junk at end of arguments.");
+    {
+      xfree (sals.sals);	/* malloc'd, so freed */
+      error ("Junk at end of arguments.");
+    }
 
-  resolve_sal_pc (&sal);
+  resolve_sal_pc (&sals, NULL, NULL);
+  xfree (sals.sals);	/* malloc'd, so freed */
 
   if (anywhere)
     /* If the user told us to continue until a specified location,
@@ -7162,7 +7240,36 @@
       sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL, NULL);
       for (i = 0; i < sals.nelts; i++)
 	{
-	  resolve_sal_pc (&sals.sals[i]);
+	  int j = i;
+	  int thisbpt = i;
+	  struct breakpoint *bpt;
+
+	  resolve_sal_pc (&sals, &i, NULL);
+
+	  /* If there are multiple breakpoints for this address. We need to
+	   * find out which one of them corresponds to this breakpoint. If any
+	   * of them correspond to some other breakpoints, they'll be handled
+	   * later when we try to insert them. */
+
+	  while (j <= i)
+	    {
+	      ALL_BREAKPOINTS(bpt)
+		  if (bpt->loc->address == sals.sals[j].pc)
+		    break;
+	      if (!bpt)
+		{
+		  if (j < i)
+		    /* There is no breakpoint corresponding to this
+		     * address. We'll have to create one. FIXME: can't
+		     * handle that for multiple breakpoints yet */
+		    error("New breakpoint found while reserting "
+			  "breakpoints");
+		}
+	      else
+		if (bpt == b)
+		  thisbpt = j;
+	      j++;
+	    }
 
 	  /* Reparse conditions, they might contain references to the
 	     old symtab.  */
@@ -7176,33 +7283,33 @@
 		     to parse_exp_1.  */
 		  b->cond = NULL;
 		}
-	      b->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0);
+              b->cond = parse_exp_1 (&s, block_for_pc (sals.sals[thisbpt].pc), 0);
 	    }
 
 	  /* We need to re-set the breakpoint if the address changes... */
-	  if (b->loc->address != sals.sals[i].pc
+          if (b->loc->address != sals.sals[thisbpt].pc
 	  /* ...or new and old breakpoints both have source files, and
 	     the source file name or the line number changes...  */
 	      || (b->source_file != NULL
-		  && sals.sals[i].symtab != NULL
-		  && (strcmp (b->source_file, sals.sals[i].symtab->filename) != 0
-		      || b->line_number != sals.sals[i].line)
+		  && sals.sals[thisbpt].symtab != NULL
+		  && (strcmp (b->source_file, sals.sals[thisbpt].symtab->filename) != 0
+		      || b->line_number != sals.sals[thisbpt].line)
 	      )
 	  /* ...or we switch between having a source file and not having
 	     one.  */
-	      || ((b->source_file == NULL) != (sals.sals[i].symtab == NULL))
+	      || ((b->source_file == NULL) != (sals.sals[thisbpt].symtab == NULL))
 	    )
 	    {
 	      if (b->source_file != NULL)
 		xfree (b->source_file);
-	      if (sals.sals[i].symtab == NULL)
+	      if (sals.sals[thisbpt].symtab == NULL)
 		b->source_file = NULL;
 	      else
 		b->source_file =
-		  savestring (sals.sals[i].symtab->filename,
-			      strlen (sals.sals[i].symtab->filename));
-	      b->line_number = sals.sals[i].line;
-	      b->loc->requested_address = sals.sals[i].pc;
+		  savestring (sals.sals[thisbpt].symtab->filename,
+			      strlen (sals.sals[thisbpt].symtab->filename));
+	      b->line_number = sals.sals[thisbpt].line;
+	      b->loc->requested_address = sals.sals[thisbpt].pc;
 	      b->loc->address
 	        = adjust_breakpoint_address (b->loc->requested_address,
 		                             b->type);
@@ -7217,13 +7324,14 @@
 	         rather than once for every breakpoint.  */
 	      breakpoints_changed ();
 	    }
-	  b->loc->section = sals.sals[i].section;
+	  b->loc->section = sals.sals[thisbpt].section;
 	  b->enable_state = save_enable;	/* Restore it, this worked. */
 
 
 	  /* Now that this is re-enabled, check_duplicates
 	     can be used. */
 	  check_duplicates (b);
+          i = j;
 
 	}
       xfree (sals.sals);
Index: gdb-6.2/gdb/dwarf2read.c
===================================================================
--- gdb-6.2.orig/gdb/dwarf2read.c	2004-09-21 16:12:07.000000000 +0530
+++ gdb-6.2/gdb/dwarf2read.c	2004-09-21 19:05:52.000000000 +0530
@@ -3111,6 +3111,11 @@
   else
     return;
 
+  /* Check for artificial methods.  */
+  attr = dwarf2_attr (die, DW_AT_artificial, cu);
+  if (attr && DW_UNSND (attr) != 0)
+    return;
+
   /* Get the mangled name.  */
   physname = dwarf2_linkage_name (die, cu);
 
@@ -3204,11 +3209,6 @@
 	}
     }
 
-  /* Check for artificial methods.  */
-  attr = dwarf2_attr (die, DW_AT_artificial, cu);
-  if (attr && DW_UNSND (attr) != 0)
-    fnp->is_artificial = 1;
-
   /* Get index in virtual function table if it is a virtual member function.  */
   attr = dwarf2_attr (die, DW_AT_vtable_elem_location, cu);
   if (attr)
@@ -5610,25 +5610,25 @@
 {
   unsigned int i;
   struct attribute *spec = NULL;
+  unsigned int level = 0;
 
-  for (i = 0; i < die->num_attrs; ++i)
+  do
     {
-      if (die->attrs[i].name == name)
+      for (i = 0; i < die->num_attrs; ++i)
 	{
-	  return &die->attrs[i];
-	}
-      if (die->attrs[i].name == DW_AT_specification
-	  || die->attrs[i].name == DW_AT_abstract_origin)
-	spec = &die->attrs[i];
-    }
-  if (spec)
-    {
-      struct die_info *ref_die =
-      follow_die_ref (dwarf2_get_ref_die_offset (spec, cu));
-
-      if (ref_die)
-	return dwarf2_attr (ref_die, name, cu);
+          if (die->attrs[i].name == name)
+            {
+              return &die->attrs[i];
+            }
+          if (die->attrs[i].name == DW_AT_specification
+             || die->attrs[i].name == DW_AT_abstract_origin)
+            spec = &die->attrs[i];
+        }
+      if (spec)
+        die = follow_die_ref (dwarf2_get_ref_die_offset (spec, cu));
+      level++;
     }
+  while (die && level < 3);
 
   return NULL;
 }
Index: gdb-6.2/gdb/infcmd.c
===================================================================
--- gdb-6.2.orig/gdb/infcmd.c	2004-06-29 12:09:06.000000000 +0530
+++ gdb-6.2/gdb/infcmd.c	2004-09-21 19:05:52.000000000 +0530
@@ -849,12 +849,15 @@
     }
 
   sal = sals.sals[0];
-  xfree (sals.sals);
 
   if (sal.symtab == 0 && sal.pc == 0)
-    error ("No source file has been specified.");
+    {
+      xfree (sals.sals);
+      error ("No source file has been specified.");
+    }
 
-  resolve_sal_pc (&sal);	/* May error out */
+  resolve_sal_pc (&sals, NULL, NULL);	/* May error out */
+  xfree (sals.sals);
 
   /* See if we are trying to jump to another function. */
   fn = get_frame_function (get_current_frame ());
Index: gdb-6.2/gdb/symtab.c
===================================================================
--- gdb-6.2.orig/gdb/symtab.c	2004-07-08 16:48:27.000000000 +0530
+++ gdb-6.2/gdb/symtab.c	2004-09-21 19:05:52.000000000 +0530
@@ -71,7 +71,7 @@
 
 static void output_source_filename (char *, int *);
 
-static int find_line_common (struct linetable *, int, int *);
+static int find_line_common (struct linetable *, int, int *, int, int);
 
 /* This one is used by linespec.c */
 
@@ -2197,18 +2197,34 @@
 find_line_symtab (struct symtab *symtab, int line, int *index, int *exact_match)
 {
   int exact;
+  int find_exact = 0;
 
   /* BEST_INDEX and BEST_LINETABLE identify the smallest linenumber > LINE
      so far seen.  */
 
   int best_index;
+  int start_index = 0;
   struct linetable *best_linetable;
   struct symtab *best_symtab;
 
   /* First try looking it up in the given symtab.  */
   best_linetable = LINETABLE (symtab);
+  
+  /* Check whether we are continuing a previous search */
+  if (best_linetable && index && *index)
+    {
+      if (*index >= best_linetable->nitems)
+	return NULL;
+      if (best_linetable->item[(*index) - 1].line != line)
+	/* We are continuing an approximate search. Continue with the line
+	 * numbers that exactly match previous hit */
+	line = best_linetable->item[(*index) - 1].line;
+      find_exact = 1;
+      start_index = *index;
+    }
   best_symtab = symtab;
-  best_index = find_line_common (best_linetable, line, &exact);
+  best_index = find_line_common (best_linetable, line, &exact, find_exact,
+				 start_index);
   if (best_index < 0 || !exact)
     {
       /* Didn't find an exact match.  So we better keep looking for
@@ -2239,7 +2255,7 @@
 	if (strcmp (symtab->filename, s->filename) != 0)
 	  continue;
 	l = LINETABLE (s);
-	ind = find_line_common (l, line, &exact);
+	ind = find_line_common (l, line, &exact, find_exact, start_index);
 	if (ind >= 0)
 	  {
 	    if (exact)
@@ -2271,15 +2287,16 @@
   return best_symtab;
 }
 \f
-/* Set the PC value for a given source file and line number and return true.
-   Returns zero for invalid line number (and sets the PC to 0).
-   The source file is specified with a struct symtab.  */
+/* Set the PC value for a given source file and line number and return index
+   into the line table for the symbol table;
+   Returns 0 for if doesn't find an entry (and sets the PC to 0).
+   The source file is specified with a struct symtab.
+   Begins the search at index ind */
 
 int
-find_line_pc (struct symtab *symtab, int line, CORE_ADDR *pc)
+find_line_pc (struct symtab *symtab, int line, CORE_ADDR *pc, int ind)
 {
   struct linetable *l;
-  int ind;
 
   *pc = 0;
   if (symtab == 0)
@@ -2290,7 +2307,7 @@
     {
       l = LINETABLE (symtab);
       *pc = l->item[ind].pc;
-      return 1;
+      return ind + 1;
     }
   else
     return 0;
@@ -2310,7 +2327,7 @@
   struct symtab_and_line found_sal;
 
   startaddr = sal.pc;
-  if (startaddr == 0 && !find_line_pc (sal.symtab, sal.line, &startaddr))
+  if (startaddr == 0 && !find_line_pc (sal.symtab, sal.line, &startaddr, 0))
     return 0;
 
   /* This whole function is based on address.  For example, if line 10 has
@@ -2339,11 +2356,13 @@
    table for the pc of the nearest line whose number is >= the specified one.
    Return -1 if none is found.  The value is >= 0 if it is an index.
 
-   Set *EXACT_MATCH nonzero if the value returned is an exact match.  */
+   Set *EXACT_MATCH nonzero if the value returned is an exact match.
+   If find_exact is non-zero, it forces an exact match
+   start_index is the index to start searching from */
 
 static int
 find_line_common (struct linetable *l, int lineno,
-		  int *exact_match)
+                  int *exact_match, int find_exact, int start_index)
 {
   int i;
   int len;
@@ -2361,7 +2380,7 @@
     return -1;
 
   len = l->nitems;
-  for (i = 0; i < len; i++)
+  for (i = start_index; i < len; i++)
     {
       struct linetable_entry *item = &(l->item[i]);
 
@@ -2371,6 +2390,8 @@
 	  *exact_match = 1;
 	  return i;
 	}
+      if (find_exact)
+	continue;
 
       if (item->line > lineno && (best == 0 || item->line < best))
 	{
Index: gdb-6.2/gdb/symtab.h
===================================================================
--- gdb-6.2.orig/gdb/symtab.h	2004-06-11 01:35:44.000000000 +0530
+++ gdb-6.2/gdb/symtab.h	2004-09-21 19:05:52.000000000 +0530
@@ -1256,12 +1256,12 @@
 
 /* Given a symtab and line number, return the pc there.  */
 
-extern int find_line_pc (struct symtab *, int, CORE_ADDR *);
+extern int find_line_pc (struct symtab *, int, CORE_ADDR *, int);
 
 extern int find_line_pc_range (struct symtab_and_line, CORE_ADDR *,
 			       CORE_ADDR *);
 
-extern void resolve_sal_pc (struct symtab_and_line *);
+extern void resolve_sal_pc (struct symtabs_and_lines *, int *, char ***);
 
 /* Given a string, return the line specified by it.  For commands like "list"
    and "breakpoint".  */
Index: gdb-6.2/gdb/tracepoint.c
===================================================================
--- gdb-6.2.orig/gdb/tracepoint.c	2004-06-15 06:34:20.000000000 +0530
+++ gdb-6.2/gdb/tracepoint.c	2004-09-21 19:05:52.000000000 +0530
@@ -384,6 +384,7 @@
   struct tracepoint *t;
   char *addr_start = 0, *addr_end = 0;
   int i;
+  int j;
 
   if (!arg || !*arg)
     error ("trace command requires an argument");
@@ -399,7 +400,11 @@
 
   /* Resolve all line numbers to PC's */
   for (i = 0; i < sals.nelts; i++)
-    resolve_sal_pc (&sals.sals[i]);
+  {
+    /* Let resolve_sal_pc insert sals if required */
+    j = i;
+    resolve_sal_pc (&sals, &j, NULL);
+  }
 
   /* Now set all the tracepoints.  */
   for (i = 0; i < sals.nelts; i++)
@@ -2348,7 +2353,7 @@
     return;		/* presumably decode_line_1 has already warned */
 
   /* Resolve line numbers to PC */
-  resolve_sal_pc (&sals.sals[0]);
+  resolve_sal_pc (&sals, NULL, NULL);
   block = block_for_pc (sals.sals[0].pc);
 
   while (block != 0)
Index: gdb-6.2/gdb/mi/mi-cmd-disas.c
===================================================================
--- gdb-6.2.orig/gdb/mi/mi-cmd-disas.c	2002-09-30 21:27:26.000000000 +0530
+++ gdb-6.2/gdb/mi/mi-cmd-disas.c	2004-09-21 19:05:52.000000000 +0530
@@ -148,7 +148,7 @@
       s = lookup_symtab (file_string);
       if (s == NULL)
 	error ("mi_cmd_disassemble: Invalid filename.");
-      if (!find_line_pc (s, line_num, &start))
+      if (!find_line_pc (s, line_num, &start, 0))
 	error ("mi_cmd_disassemble: Invalid line number");
       if (find_pc_partial_function (start, NULL, &low, &high) == 0)
 	error ("mi_cmd_disassemble: No function contains specified address");
Index: gdb-6.2/gdb/tui/tui-layout.c
===================================================================
--- gdb-6.2.orig/gdb/tui/tui-layout.c	2004-09-21 19:17:08.000000000 +0530
+++ gdb-6.2/gdb/tui/tui-layout.c	2004-09-21 19:19:42.000000000 +0530
@@ -520,7 +520,7 @@
     case SRC_DATA_COMMAND:
       find_line_pc (cursal.symtab,
 		    TUI_SRC_WIN->detail.source_info.start_line_or_addr.line_no,
-		    &pc);
+		    &pc, 0);
       addr = pc;
       break;
     case DISASSEM_COMMAND:
Index: gdb-6.2/gdb/tui/tui-win.c
===================================================================
--- gdb-6.2.orig/gdb/tui/tui-win.c	2004-09-21 19:25:44.000000000 +0530
+++ gdb-6.2/gdb/tui/tui-win.c	2004-09-21 19:26:41.000000000 +0530
@@ -1313,7 +1313,7 @@
 	    line.line_no = cursal.line;
 	  else
 	    {
-	      find_line_pc (s, cursal.line, &line.addr);
+	      find_line_pc (s, cursal.line, &line.addr, 0);
 	    }
 	  tui_update_source_window (win_info, s, line, TRUE);
 	}
Index: gdb-6.2/gdb/tui/tui-winsource.c
===================================================================
--- gdb-6.2.orig/gdb/tui/tui-winsource.c	2004-09-21 19:31:59.000000000 +0530
+++ gdb-6.2/gdb/tui/tui-winsource.c	2004-09-21 19:32:43.000000000 +0530
@@ -178,7 +178,7 @@
     {
     case DISASSEM_COMMAND:
     case DISASSEM_DATA_COMMAND:
-      find_line_pc (s, line, &pc);
+      find_line_pc (s, line, &pc, 0);
       tui_update_source_windows_with_addr (pc);
       break;
     default:
@@ -186,7 +186,7 @@
       tui_show_symtab_source (s, l, FALSE);
       if (tui_current_layout () == SRC_DISASSEM_COMMAND)
 	{
-	  find_line_pc (s, line, &pc);
+	  find_line_pc (s, line, &pc, 0);
 	  tui_show_disassem (pc);
 	}
       break;

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

* Re: breakpoints in constructors
  2003-04-30 14:44 Michael Elizabeth Chastain
@ 2003-05-01  2:13 ` Daniel Berlin
  0 siblings, 0 replies; 16+ messages in thread
From: Daniel Berlin @ 2003-05-01  2:13 UTC (permalink / raw)
  To: Michael Elizabeth Chastain; +Cc: carlton, drow, gdb, pkoning


On Wednesday, April 30, 2003, at 10:43  AM, Michael Elizabeth Chastain 
wrote:

> Hi Daniel,
>
>> It's not required multi-object-code, it's only required that it does
>> the right thing when called with a certain name  (not the same at all,
>> since one can  just make up the symbols for the constructors that 
>> start
>> at the right points in the "one object code constructor" function,
>> without even having to make stub functions with gotos in them. Just
>> multiple symbol names and one object code).
>
> I see what you mean.  The ABI requirements are that there be two or 
> three
> labels, and that the labels have different semantics.  It was just an
> assumption on my part that C++ compilers always emit distinct,
> single-entry-point functions.

It was just a "it's simple to implement this way, we'll optimize it 
later" thing, i think.
You know, of the "why not keep the ABI implementation simple before we 
make it buggy" thought? :P
>
>> One way is to make one "visible" breakpoint and 2 "hidden" 
>> breakpoints.
>> This is a bit ugly, unless you special case the breakpoint printouts 
>> so
>> that it says the one "visible" breakpoint is at pc x, y, z, rather 
>> than
>> just x (the code to do this is probably ugly too in this method).
>
> This is possible but I am really not into this approach.
>
> I would rather expose to the user that one block of source code really
> does generate several blocks of object code, and then handle 
> constructors
> and destructors in a similar way that we handle inline functions.
> After one initial surprise ('how come gdb sets 2-3 breakpoints when I
> break on a constructor'), I think that users would actually understand
> this model pretty well.
>
>> You could also just make a hierarchy of breakpoints and avoid the 
>> magic
>> methods and hiding altogether.
>> You have one parent breakpoint named "Foo:Foo" that just consists of 3
>> sub-breakpoints, each at the right place in the constructor.
>
> Yeah.  You call them hierarchical, but I think of them as different
> types.  The 'parent' here is of type 'source breakpoint'.  The
> 'subs' are of type 'object code breakpoint'.
>
> The current model is that a 'source breakpoint' and an 'object code
> breakpoint' have a 1-1 relationship.  We could separate the types and
> then a source breakpoint could have a 1-many relationship with a
> list of object code breakpoints.
>
> So your vision is a tree of nodes, all of the same type, and my vision
> is of fixed depth 2, where level 1 is type SB, and level 2 is type OCB.
> An SB has a list of OCB's and that's the whole structure.
>
> Is this making sense?
>
Yup.
But i was thinking that the problem with a flattened tree like that is 
that it requires more work when checking breakpoints, which can be 
expensive
See, we can easily test whether we are possibly within the range of a 
level 1 breakpoint by keeping track of the upper/lower bounds, even in 
your scheme (I say possibly since it could be multiple disjoint ranges, 
so we mihgt not *really* be in the bounds, but it's an optimization to 
not look at 2+ level breakpoints to see which we hit when it's 
impossible that we hit any of them)

However, in your case, we'll need a linear walk of all the level 2+ to 
determine whether we are in range of any of them. O(n)
If it's still organized as a multi-level binary tree (kept in some sort 
of sorted order), we only have to check log N of the breakpoints.
If you breakpoint a heavily constructed object and set a condition on 
it, we might hit this thing a billion times, so it can add up quickly.

>> ... (since i imagine in some extremely complex case, one could want to
>> have a subbreakpoint consisting of subbreakpoints) ...
>
> Mmmmm, what would be a use case for that?  If there is a real use case
> than my simple two-level structure would be inadequate.

I thought of a separate use of a BP hierarchy yesterday, which is 
handling inlined code (since it also may appear in multiple places, and 
if the user breaks on a source line that's inlined, he wants it to stop 
in all the copies)
It led me just now to think of a use case: Inlined code in Inlined code.
In that case, you *could* flatten the tree into 2 levels, but it's 
easier to build it as a subtree of a subtree (since we do a lot of 
debug reading recursively, and don't know where we came from), so 
unless the flattening was done in the l2breakpoint_add or whatever 
automatically, this might be problematic.


>
>> (You can either just make it print "exists at multiple pc's, or 
>> recursively
>> print out the pc's of the sub breakpoints).
>>
>> Hitting one of the subbreakpoints doesn't require any magic, since 
>> what
>> we say is that we've hit the parent breakpoint, "Foo:Foo".
>
> Yes, this sounds good to me.  Again in terms of "source breakpoint"
> and "object code breakpoint", it becomes very simple:
>
>   by definition, only an object code breakpoint can actually be 
> executed
>   gdb usually translates the OCB back to a SB for display
>
> Michael C

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

* Re: breakpoints in constructors
@ 2003-04-30 14:44 Michael Elizabeth Chastain
  2003-05-01  2:13 ` Daniel Berlin
  0 siblings, 1 reply; 16+ messages in thread
From: Michael Elizabeth Chastain @ 2003-04-30 14:44 UTC (permalink / raw)
  To: dberlin; +Cc: carlton, drow, gdb, pkoning

Hi Daniel,

> It's not required multi-object-code, it's only required that it does 
> the right thing when called with a certain name  (not the same at all, 
> since one can  just make up the symbols for the constructors that start 
> at the right points in the "one object code constructor" function, 
> without even having to make stub functions with gotos in them. Just 
> multiple symbol names and one object code).

I see what you mean.  The ABI requirements are that there be two or three
labels, and that the labels have different semantics.  It was just an
assumption on my part that C++ compilers always emit distinct,
single-entry-point functions.

> One way is to make one "visible" breakpoint and 2 "hidden" breakpoints.
> This is a bit ugly, unless you special case the breakpoint printouts so 
> that it says the one "visible" breakpoint is at pc x, y, z, rather than 
> just x (the code to do this is probably ugly too in this method).

This is possible but I am really not into this approach.

I would rather expose to the user that one block of source code really
does generate several blocks of object code, and then handle constructors
and destructors in a similar way that we handle inline functions.
After one initial surprise ('how come gdb sets 2-3 breakpoints when I
break on a constructor'), I think that users would actually understand
this model pretty well.

> You could also just make a hierarchy of breakpoints and avoid the magic 
> methods and hiding altogether.
> You have one parent breakpoint named "Foo:Foo" that just consists of 3 
> sub-breakpoints, each at the right place in the constructor.

Yeah.  You call them hierarchical, but I think of them as different
types.  The 'parent' here is of type 'source breakpoint'.  The
'subs' are of type 'object code breakpoint'.

The current model is that a 'source breakpoint' and an 'object code
breakpoint' have a 1-1 relationship.  We could separate the types and
then a source breakpoint could have a 1-many relationship with a
list of object code breakpoints.

So your vision is a tree of nodes, all of the same type, and my vision
is of fixed depth 2, where level 1 is type SB, and level 2 is type OCB.
An SB has a list of OCB's and that's the whole structure.

Is this making sense?

> ... (since i imagine in some extremely complex case, one could want to
> have a subbreakpoint consisting of subbreakpoints) ...

Mmmmm, what would be a use case for that?  If there is a real use case
than my simple two-level structure would be inadequate.

> (You can either just make it print "exists at multiple pc's, or recursively 
> print out the pc's of the sub breakpoints).
> 
> Hitting one of the subbreakpoints doesn't require any magic, since what 
> we say is that we've hit the parent breakpoint, "Foo:Foo".

Yes, this sounds good to me.  Again in terms of "source breakpoint"
and "object code breakpoint", it becomes very simple:

  by definition, only an object code breakpoint can actually be executed
  gdb usually translates the OCB back to a SB for display

Michael C

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

* Re: breakpoints in constructors
  2003-04-30  4:36 Michael Elizabeth Chastain
@ 2003-04-30  5:20 ` Daniel Berlin
  0 siblings, 0 replies; 16+ messages in thread
From: Daniel Berlin @ 2003-04-30  5:20 UTC (permalink / raw)
  To: Michael Elizabeth Chastain; +Cc: drow, pkoning, carlton, gdb


On Wednesday, April 30, 2003, at 12:36  AM, Michael Elizabeth Chastain 
wrote:

> Can I de-lurk for a minute?
>
> gcc 2.95.3 had a single object code function for each constructor,
> with a hidden flag to indicate its "in-charge-ness".  I always thought
> that was much nicer for debugging.
>
> But gcc 3.X's multi-object-code implementation is mandated by the
> multi-vendor ABI, which will make it harder.

No it isn't.
It's not required multi-object-code, it's only required that it does 
the right thing when called with a certain name  (not the same at all, 
since one can  just make up the symbols for the constructors that start 
at the right points in the "one object code constructor" function, 
without even having to make stub functions with gotos in them. Just 
multiple symbol names and one object code).

One can also have "one object code implementation" with labels and use 
gotos and stub functions if you like.
Or one can have three copies of the object code.

It's not like even with three copies, that this is a laborious task.
It just means that you set multiple breakpoints.

One way is to make one "visible" breakpoint and 2 "hidden" breakpoints.
This is a bit ugly, unless you special case the breakpoint printouts so 
that it says the one "visible" breakpoint is at pc x, y, z, rather than 
just x (the code to do this is probably ugly too in this method).

Another way is to do this is make it all invisible to the user, but 
still have "hidden" breakpoints is to make breakpoints have an 
associate set of methods, where they perform this magic internally.

You could also just make a hierarchy of breakpoints and avoid the magic 
methods and hiding altogether.
You have one parent breakpoint named "Foo:Foo" that just consists of 3 
sub-breakpoints, each at the right place in the constructor.

Only non-hidden top level breakpoints (since i imagine in some 
extremely complex case, one could want to have a subbreakpoint 
consisting of subbreakpoints) are visible, and thus, Foo:Foo is visible 
in an info breakpoints printout, but it's sub-breakpoints aren't (You 
can either just make it print "exists at multiple pc's, or recursively 
print out the pc's of the sub breakpoints).

Hitting one of the subbreakpoints doesn't require any magic, since what 
we say is that we've hit the parent breakpoint, "Foo:Foo".

--Dan

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

* Re: breakpoints in constructors
@ 2003-04-30  4:36 Michael Elizabeth Chastain
  2003-04-30  5:20 ` Daniel Berlin
  0 siblings, 1 reply; 16+ messages in thread
From: Michael Elizabeth Chastain @ 2003-04-30  4:36 UTC (permalink / raw)
  To: drow, pkoning; +Cc: carlton, gdb

Can I de-lurk for a minute?

gcc 2.95.3 had a single object code function for each constructor,
with a hidden flag to indicate its "in-charge-ness".  I always thought
that was much nicer for debugging.

But gcc 3.X's multi-object-code implementation is mandated by the
multi-vendor ABI, which will make it harder.

I missed the beginning of this thread so someone's probably already
brought up these points, my apologies if I'm rehashing obvious stuff.

Michael C

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

end of thread, other threads:[~2005-12-27  4:07 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-04-18 20:04 breakpoints in constructors David Carlton
2003-04-24 14:50 ` Daniel Jacobowitz
2003-04-24 22:02   ` Paul Koning
2003-04-25  0:30     ` Daniel Jacobowitz
2003-04-29 20:45   ` Paul Koning
2003-04-29 21:24     ` Daniel Jacobowitz
2003-04-30 19:04       ` Michael Eager
2003-04-30 19:11         ` Paul Koning
2003-04-30 19:19         ` Daniel Jacobowitz
2003-04-30  4:36 Michael Elizabeth Chastain
2003-04-30  5:20 ` Daniel Berlin
2003-04-30 14:44 Michael Elizabeth Chastain
2003-05-01  2:13 ` Daniel Berlin
2005-12-15 14:06 Breakpoints " Amit Kale
2005-12-26  7:52 ` Amit Kale
2005-12-27  4:07   ` Jim Blandy

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