Bug 12257 - gdb ignores line "bar: if(foo)goto bar;"
Summary: gdb ignores line "bar: if(foo)goto bar;"
Status: REOPENED
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: 7.0
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-11-23 10:54 UTC by Askar Safin
Modified: 2013-04-13 07:40 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Askar Safin 2010-11-23 10:54:05 UTC
foo.c:
-----------------------------------
#include <stdio.h>

int main()
{
        int foo;
        printf("Enter foo: ");
        scanf("%d", &foo);
bar:    if(foo)goto bar;
        return 0;
}
-----------------------------------
0:~# gcc -g foo.c
0:~# gdb a.out
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/a.out...done.
(gdb) start
Temporary breakpoint 1 at 0x804842d: file foo.c, line 6.
Starting program: /root/a.out 

Temporary breakpoint 1, main () at foo.c:6
6               printf("Enter foo: ");
(gdb) n
7               scanf("%d", &foo);
(gdb) 
Enter foo: 0
9               return 0;
(gdb) q
A debugging session is active.

        Inferior 1 [process 21382] will be killed.

Quit anyway? (y or n) y
-----------------------------------
But gdb must say:

6               printf("Enter foo: ");
(gdb) n
7               scanf("%d", &foo);
(gdb) 
Enter foo: 0
8       bar:    if(foo)goto bar; 
(gdb) 
9               return 0;
-----------------------------------
0:~# gdb a.out
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/a.out...done.
(gdb) start
Temporary breakpoint 1 at 0x804842d: file foo.c, line 6.
Starting program: /root/a.out 

Temporary breakpoint 1, main () at foo.c:6
6               printf("Enter foo: ");
(gdb) n
7               scanf("%d", &foo);
(gdb) 
Enter foo: 1
^C
Program received signal SIGINT, Interrupt.
0x08048458 in main () at foo.c:8
8       bar:    if(foo)goto bar;
(gdb) q
A debugging session is active.

        Inferior 1 [process 21399] will be killed.

Quit anyway? (y or n) y
-----------------------------------
But gdb must say:

6               printf("Enter foo: ");
(gdb) n
7               scanf("%d", &foo);
(gdb) 
Enter foo: 1
8       bar:    if(foo)goto bar; 
(gdb) 
^C
-----------------------------------
0:~# uname -a
Linux debian 2.6.32-5-686 #1 SMP Sat Oct 30 22:47:19 UTC 2010 i686 GNU/Linux
0:~# gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.5-8' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-targets=all --with-arch-32=i586 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.4.5 (Debian 4.4.5-8)
Comment 1 Tom Tromey 2012-02-07 20:46:45 UTC
I think this is a gcc bug, not a gdb bug.

On Fedora 15,with the system gcc, it fails for me if I compile with -g.
But if I use -g -O1, it works

With plain -g, the line number table looks like:

CU: pr.c:
File name                            Line number    Starting address
pr.c                                           4            0x400534
pr.c                                           6            0x40053c
pr.c                                           7            0x40054e
pr.c                                           8            0x400569
pr.c                                           8            0x40056a
pr.c                                           9            0x400571
pr.c                                          10            0x400576

Note the address of the first occurrence of line 8.
Then if I disassemble I see:

        scanf("%d", &foo);
  40054e:       b8 84 06 40 00          mov    $0x400684,%eax
  400553:       48 8d 55 fc             lea    -0x4(%rbp),%rdx
  400557:       48 89 d6                mov    %rdx,%rsi
  40055a:       48 89 c7                mov    %rax,%rdi
  40055d:       b8 00 00 00 00          mov    $0x0,%eax
  400562:       e8 d1 fe ff ff          callq  400438 <__isoc99_scanf@plt>
  400567:       eb 01                   jmp    40056a <main+0x36>
bar:    if(foo)goto bar;
  400569:       90                      nop
  40056a:       8b 45 fc                mov    -0x4(%rbp),%eax
  40056d:       85 c0                   test   %eax,%eax
  40056f:       75 f8                   jne    400569 <main+0x35>
        return 0;

That is, the first "line 8" is that nop, which is skipped after the call.
Comment 2 Askar Safin 2012-02-07 21:16:57 UTC
Thank you, Tom. I posted the bug to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52160
Comment 3 Andrew Pinski 2012-02-07 21:46:08 UTC
This is what GCC produces:
Here is what GCC produces:
	.loc 1 7 0
	leaq	-4(%rbp), %rax
	movq	%rax, %rsi
	movl	$.LC1, %edi
	movl	$0, %eax
	call	__isoc99_scanf
	jmp	.L2
.L5:
	.loc 1 8 0
	nop
.L2:
	.loc 1 8 0 is_stmt 0 discriminator 1
	movl	-4(%rbp), %eax
	testl	%eax, %eax
	jne	.L5

This looks fine to me.
Comment 4 Tom Tromey 2012-02-08 16:25:45 UTC
(In reply to comment #3)

>     .loc 1 8 0 is_stmt 0 discriminator 1

> This looks fine to me.

Yeah, my mistake.
Comment 5 Tom Tromey 2012-02-08 21:38:41 UTC
This seems to be a side effect of this code in handle_inferior_event:

  if ((stop_pc == stop_pc_sal.pc)
      && (ecs->event_thread->current_line != stop_pc_sal.line
 	  || ecs->event_thread->current_symtab != stop_pc_sal.symtab))
    {
      /* We are at the start of a different line.  So stop.  Note that
         we don't stop if we step into the middle of a different line.
         That is said to make things like for (;;) statements work
         better.  */
      if (debug_infrun)
	 fprintf_unfiltered (gdb_stdlog,
			     "infrun: stepped to a different line\n");
      ecs->event_thread->control.stop_step = 1;
      print_end_stepping_range_reason ();
      stop_stepping (ecs);
      return;
    }

Here we have:

(top-gdb) p /x stop_pc
$26 = 0x40056a
(top-gdb) p /x stop_pc_sal.pc
$27 = 0x400569

So we skip this stop and instead keep going.

I am not sure whether that comment still makes sense.  It is present
in the initial public checkin of gdb, so I somewhat suspect it is
very out of date now.