Single stepping a simple C-program, but...

Pedro Alves pedro@codesourcery.com
Mon May 19 22:39:00 GMT 2008


A Monday 19 May 2008 21:48:18, Pedro Alves wrote:
> A Monday 19 May 2008 21:18:36, Peter Toft wrote:
> > Hi guys
> >
> > I was a bit surprised today with GDB, and I hope one of you can explain
> > it to me. Take a look at http://pastebin.org/37117
>
> 01. #include <stdio.h>
> 02.
> 03. int main(void)
> 04. {
> 05.   int ii=4;
> 06.
> 07.   if ((ii>3) || (ii<1))
> 08.    printf("hej A\n");
> 09.   else
> 10.    printf("hej B\n");
> 11.
> 12.   return 0;
> 13. }
>
> > Press download and save as my_program.c
> > $ gcc -g my_program.c
> > $ gdb ./a.out
> > (gdb) br 7
> > Breakpoint 1 at 0x804838c: file my_program.c, line 7.
> > (gdb) r
> > Starting program: /home/pto/c/a.out
> >
> > Breakpoint 1, main () at my_program.c:7
> > 7	  if ((ii>3) || (ii<1))
> > (gdb) s
> > 8	    printf("hej A\n");
> > (gdb) s
> > hej A
> > 7	  if ((ii>3) || (ii<1))     <----------- WHY!!!!??
> > (gdb) s
> > 12	  return 0;
> >
> > -------
> >
> > Why does the second "step" i.e. "s" take me BACK to line 7 after I
> > have been in line 8????
>
> Presumably, because there's a branch instruction after the printf
> call to skip the else clause, GDB hits it (step-resume breakpoint),
> and the debug info gcc is producing is marking that address as belonging
> to line 7?

I got curious.
 gcc version 4.2.3 (Ubuntu 4.2.3-2ubuntu7) (x86_64-linux-gnu)
 GNU gdb 6.8.50.20080515-cvs

Built with gcc my_program.c -g3 -O0 -o my_program

5         int ii=4;
(gdb) n
7         if ((ii>3) || (ii<1))
(gdb)
8           printf("hej A\n");
(gdb)
hej A
7         if ((ii>3) || (ii<1))
(gdb) p $pc
$1 = (void (*)()) 0x4004bd <main+37>

(gdb) disassemble /m
6
7         if ((ii>3) || (ii<1))
0x00000000004004a7 <main+15>:   cmpl   $0x3,-0x4(%rbp)
0x00000000004004ab <main+19>:   jg     0x4004b3 <main+27>
0x00000000004004ad <main+21>:   cmpl   $0x0,-0x4(%rbp)
0x00000000004004b1 <main+25>:   jg     0x4004bf <main+39>
0x00000000004004bd <main+37>:   jmp    0x4004c9 <main+49>

8           printf("hej A\n");
0x00000000004004b3 <main+27>:   mov    $0x4005b8,%edi
0x00000000004004b8 <main+32>:   callq  0x4003c0 <puts@plt>

9         else
10          printf("hej B\n");
0x00000000004004bf <main+39>:   mov    $0x4005be,%edi
0x00000000004004c4 <main+44>:   callq  0x4003c0 <puts@plt>

11
12        return 0;
0x00000000004004c9 <main+49>:   mov    $0x0,%eax

Humm, this output isn't clear, as GDB is grouping insns by
line number first then sorting by address.

objdump -dS:

int main(void)
{
  400498:       55                      push   %rbp
  400499:       48 89 e5                mov    %rsp,%rbp
  40049c:       48 83 ec 10             sub    $0x10,%rsp
  int ii=4;
  4004a0:       c7 45 fc 04 00 00 00    movl   $0x4,-0x4(%rbp)

  if ((ii>3) || (ii<1))
  4004a7:       83 7d fc 03             cmpl   $0x3,-0x4(%rbp)
  4004ab:       7f 06                   jg     4004b3 <main+0x1b>
  4004ad:       83 7d fc 00             cmpl   $0x0,-0x4(%rbp)
  4004b1:       7f 0c                   jg     4004bf <main+0x27>
    printf("hej A\n");
  4004b3:       bf b8 05 40 00          mov    $0x4005b8,%edi
  4004b8:       e8 03 ff ff ff          callq  4003c0 <puts@plt>

int main(void)
{
  int ii=4;

  if ((ii>3) || (ii<1))
  4004a7:       83 7d fc 03             cmpl   $0x3,-0x4(%rbp)
  4004ab:       7f 06                   jg     4004b3 <main+0x1b>
  4004ad:       83 7d fc 00             cmpl   $0x0,-0x4(%rbp)
  4004b1:       7f 0c                   jg     4004bf <main+0x27>
    printf("hej A\n");
  4004b3:       bf b8 05 40 00          mov    $0x4005b8,%edi
  4004b8:       e8 03 ff ff ff          callq  4003c0 <puts@plt>

int main(void)
{
  int ii=4;

  if ((ii>3) || (ii<1))
  4004bd:       eb 0a                   jmp    4004c9 <main+0x31> 

                                           ^^^  jmp over else
    printf("hej A\n");
  else
    printf("hej B\n");
  4004bf:       bf be 05 40 00          mov    $0x4005be,%edi
  4004c4:       e8 f7 fe ff ff          callq  4003c0 <puts@plt>

  return 0;
  4004c9:       b8 00 00 00 00          mov    $0x0,%eax
}

Ah, that's better.  Notice how line info is making objdump print
the same sources more than once:

readelf -wl ./my_program

 Line Number Statements:
  Extended opcode 2: set Address to 0x400498
  Special opcode 8: advance Address by 0 to 0x400498 and Line by 3 to 4
  Special opcode 118: advance Address by 8 to 0x4004a0 and Line by 1 to 5
  Special opcode 105: advance Address by 7 to 0x4004a7 and Line by 2 to 7
  Special opcode 174: advance Address by 12 to 0x4004b3 and Line by 1 to 8
  Special opcode 144: advance Address by 10 to 0x4004bd and Line by -1 to 7 
                                                 ^^^^^^                   ^
  Special opcode 36: advance Address by 2 to 0x4004bf and Line by 3 to 10
  Special opcode 147: advance Address by 10 to 0x4004c9 and Line by 2 to 12
  Special opcode 76: advance Address by 5 to 0x4004ce and Line by 1 to 13
  Advance PC by 2 to 0x4004d0
  Extended opcode 1: End of Sequence

There you go.  Not much for GDB to do.

-- 
Pedro Alves



More information about the Gdb mailing list