Mirror of the gdb mailing list
 help / color / mirror / Atom feed
* "next" single-steps all the way
@ 2001-04-11  5:16 Eli Zaretskii
  2001-04-11  5:57 ` Fernando Nasser
  0 siblings, 1 reply; 3+ messages in thread
From: Eli Zaretskii @ 2001-04-11  5:16 UTC (permalink / raw)
  To: gdb

Here's a simple C++ program, call it car.cc:

    int count;
    int i, k;

    class Paths {
    public:
      static void car7()
      {
      for( i=0; i<10; i++) {
        for( k=0; k<1000; k++) {
	    if ( (i | k) == 127)
	          ++count;
		    }
		    }
      }
    };

    int main()
    {
      count = 0;
      Paths::car7();
      count += 2;
      return count;
    }

I compile it like this:

  g++ -Wall -Os -g -o car car.cc

Then debug it like this:

  gdb car
  (gdb) b 18
  (gdb) r
  (gdb) n

That "next" command takes forever to execute, because it seems to
single-step the whole body of Paths::car7, instead of stepping over
it.

It looks like the reason is that GCC inlines the entire body of
Paths::car7, and that somehow confuses the logic of "next".  It
normally makes a single step into car7, then puts a breakpoint on the
return address of car7 and then resumes the debuggee.  However, in
this case, the body of Paths::car7 has no frame and no return address,
so GDB continues single stepping all the way.

This happens with DJGPP, so it could be something specific to the
DJGPP port of GDB or the debug info emitted by the DJGPP port of GCC.
I did try both with -gcoff and -gstabs+, just to be sure, and it
didn't seem to help much.

Do others see this on other platforms?

Is my analysis of the problem correct?  If so, can this be corrected
somehow?  I think at the very least GDB should announce that it is
single stepping, so that the user expects slow execution.  (The
original real-life version of the above code had 4 nested loops, so
the total loop count was much greater than 10000, and the program
would _really_ run forever.)

TIA


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

* Re: "next" single-steps all the way
  2001-04-11  5:16 "next" single-steps all the way Eli Zaretskii
@ 2001-04-11  5:57 ` Fernando Nasser
  2001-04-11  8:37   ` Eli Zaretskii
  0 siblings, 1 reply; 3+ messages in thread
From: Fernando Nasser @ 2001-04-11  5:57 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb

Eli,

The core of the problem is that GDB is not recognizing car7() as a
function (method).  Maybe it has been inlined? 


So, for all practical purposes, this would be the same as if you use
"step" in a line like the following:

     for (i=0; i < NNNNNN; i++) ;

If NNNNNN is large, "step" will take a very, very long time :-(



To prevent this cases, we could add a new GDB setting: max_single_steps
that would cause a confirmation message to be asked to the user (after
printing where it is currently).


Anyway, your problem seem to be related to prologue-less functions.  The
in_prologue() test is not firing.





Eli Zaretskii wrote:
> 
> Here's a simple C++ program, call it car.cc:
> 
>     int count;
>     int i, k;
> 
>     class Paths {
>     public:
>       static void car7()
>       {
>       for( i=0; i<10; i++) {
>         for( k=0; k<1000; k++) {
>             if ( (i | k) == 127)
>                   ++count;
>                     }
>                     }
>       }
>     };
> 
>     int main()
>     {
>       count = 0;
>       Paths::car7();
>       count += 2;
>       return count;
>     }
> 
> I compile it like this:
> 
>   g++ -Wall -Os -g -o car car.cc
> 
> Then debug it like this:
> 
>   gdb car
>   (gdb) b 18
>   (gdb) r
>   (gdb) n
> 
> That "next" command takes forever to execute, because it seems to
> single-step the whole body of Paths::car7, instead of stepping over
> it.
> 
> It looks like the reason is that GCC inlines the entire body of
> Paths::car7, and that somehow confuses the logic of "next".  It
> normally makes a single step into car7, then puts a breakpoint on the
> return address of car7 and then resumes the debuggee.  However, in
> this case, the body of Paths::car7 has no frame and no return address,
> so GDB continues single stepping all the way.
> 
> This happens with DJGPP, so it could be something specific to the
> DJGPP port of GDB or the debug info emitted by the DJGPP port of GCC.
> I did try both with -gcoff and -gstabs+, just to be sure, and it
> didn't seem to help much.
> 
> Do others see this on other platforms?
> 
> Is my analysis of the problem correct?  If so, can this be corrected
> somehow?  I think at the very least GDB should announce that it is
> single stepping, so that the user expects slow execution.  (The
> original real-life version of the above code had 4 nested loops, so
> the total loop count was much greater than 10000, and the program
> would _really_ run forever.)
> 
> TIA

-- 
Fernando Nasser
Red Hat Canada Ltd.                     E-Mail:  fnasser@redhat.com
2323 Yonge Street, Suite #300
Toronto, Ontario   M4P 2C9


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

* Re: "next" single-steps all the way
  2001-04-11  5:57 ` Fernando Nasser
@ 2001-04-11  8:37   ` Eli Zaretskii
  0 siblings, 0 replies; 3+ messages in thread
From: Eli Zaretskii @ 2001-04-11  8:37 UTC (permalink / raw)
  To: fnasser; +Cc: gdb

> Date: Wed, 11 Apr 2001 08:53:22 -0400
> From: Fernando Nasser <fnasser@redhat.com>
> 
> The core of the problem is that GDB is not recognizing car7() as a
> function (method).  Maybe it has been inlined? 

It is definitely inlined.

> To prevent this cases, we could add a new GDB setting: max_single_steps
> that would cause a confirmation message to be asked to the user (after
> printing where it is currently).

Seems like a good idea.  I will try to find a way to do that, thanks
for the hint.

> Anyway, your problem seem to be related to prologue-less functions.  The
> in_prologue() test is not firing.

No, in_prologue is not even called in this case.

The actual reason for single-stepping seems to be that COFF debug info
used by DJGPP doesn't handle inlining well enough.  This part of the
program:

     int main()
     {
       count = 0;
       Paths::car7();

together with the inlined car7 code, is seen by gdb as only one long
line.  Observe:

    (gdb) list
    17      int main()
    18      {
    19        count = 0;
    20        Paths::car7();
    21        count += 2;
    22        return count;
    23      }
    (gdb) info line 19
    Line 19 of "car.cc" starts at address 0x1570 <main>
       and ends at 0x15c6 <main+86>.
    (gdb) info line 20
    Line 20 of "car.cc" is at address 0x15c6 <main+86> but contains no code.

So GDB thinks that line 19 starts at 0x1570, the beginning of `main',
and ends at 0x15c6.  Disassembly shows that this range includes the
entire inlined code of car7().  So this code in handle_inferior_event:

    /* If stepping through a line, keep going if still within it.

       Note that step_range_end is the address of the first instruction
       beyond the step range, and NOT the address of the last instruction
       within it! */
    if (stop_pc >= step_range_start
    && stop_pc < step_range_end)
      {
      /* We might be doing a BPSTAT_WHAT_SINGLE and getting a signal.
         So definately need to check for sigtramp here.  */
	 check_sigtramp2 (ecs);
	 keep_going (ecs);
	 return;
      }

keeps single-stepping all the way.

Thanks for the feedback.


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

end of thread, other threads:[~2001-04-11  8:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-04-11  5:16 "next" single-steps all the way Eli Zaretskii
2001-04-11  5:57 ` Fernando Nasser
2001-04-11  8:37   ` Eli Zaretskii

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox