Monday 10 February 2014

Debugging a C program on Linux using gdb

At times to understand a program we need to run the program at our speed of understanding i.e. one instruction at a time. this can be achieved quite easily in windows with help of various IDEs.  but for a beginner like me debugging a C code via terminal in Linux  can appear to be a very daunting task, but its not. In fact in Linux we can debug the code without installing the heavyweight IDEs, with help of gdb- GNU Debugger.

Suppose my program name is prog.c then for compiling this c program in Linux Terminal one would give the following command,
gcc -o prog prog.c 
But  we will need to add another argument -ggdb to existing command
to include GNU debugger, while compiling
gcc -o prog prog.c -ggdbg
run gdb
gdb prog

on running gdb the following can be seen on terminal

h2o@h2o-Vostro-1015:~/C$ gdb lab3
GNU gdb (GDB) 7.5-ubuntu
Copyright (C) 2012 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 "i686-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/h2o/C/lab3...done.
(gdb)

using gdb now we can do various tasks, some of them include
1.disassemble- converting c code to assembly code
2.list- see the first 10 lines of prog
3.add breakpoint and debug
4 printing variable value while program is executing in single stepping mode.

 disassemble

 Program can be disassembled using disassemble <function_name>
for example disassemble main would yield the following result,

(gdb) disassemble main
Dump of assembler code for function main:
   0x0804840c <+0>:    push   %ebp
   0x0804840d <+1>:    mov    %esp,%ebp
   0x0804840f <+3>:    and    $0xfffffff0,%esp
   0x08048412 <+6>:    sub    $0x20,%esp
   0x08048415 <+9>:    movw   $0x73,0x16(%esp)
   0x0804841c <+16>:    movl   $0x5,0x18(%esp)
   0x08048424 <+24>:    cmpl   $0x9,0x18(%esp)
   0x08048429 <+29>:    jg     0x8048432 <main+38>
   0x0804842b <+31>:    mov    $0x8048518,%eax
   0x08048430 <+36>:    jmp    0x8048437 <main+43>
   0x08048432 <+38>:    mov    $0x804851e,%eax
   0x08048437 <+43>:    lea    0x16(%esp),%edx
   0x0804843b <+47>:    mov    %edx,0x4(%esp)
this is for advanced programmers, to extract pin point precision details of their program's execution.

setting breakpoint in program & debugging

from gdb we can see our program and add breakpoints to it for debugging, 
'list' command prints the first 10 lines of code,
'list main' would yield result

(gdb) list main
1    #include<stdio.h>
2    #include<stdlib.h>
3    int main()
4    {
5        char str[]= "s";
6        int a=5;
7        printf(a<10? "%50s\n":"%s\n",str);
8   
9    int i=2;
10    printf("\n%d%d\n",++i,++i);
 here we can see that the code is printed along with line number, so suppose if we want to add a breakpoint before printf, so we will need the corresponding line number (7 in this case) and using following syntax we can add the breakpoint
  • break [file_name]:line_number
  • break [file_name]:func_name
break 7
(gdb) break 5
Breakpoint 1 at 0x8048415: file lab3.c, line 5.

This places break point in the C program,at the corresponding line number. While executing the program, the debugger will stop at the break point, and gives us  the prompt to debug.

Now we can run the program using run command
run main
and after the program starts running it will stop and wait for prompt at first breakpoint set by us in previous steps

There are three kind of gdb operations we can perform when the program stops at a break point.
  • c or continue: Debugger will continue executing until the next break point.
  • n or next: Debugger will execute the next line as single instruction.
  • s or step: Same as next, but does not treats function as a single instruction, instead goes into the function and executes it line by line.
below is the full operation in single screen

h2o@h2o-Vostro-1015:~/C$ gcc -o lab3 lab3.c -ggdb
h2o@h2o-Vostro-1015:~/C$ gdb lab3
GNU gdb (GDB) 7.5-ubuntu
Copyright (C) 2012 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 "i686-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/h2o/C/lab3...done.
(gdb) list main
1    #include<stdio.h>
2    #include<stdlib.h>
3    int main()
4    {
5        char str[]= "s";
6        int a=5;
7        printf(a<10? "%50s\n":"%s\n",str);
8   
9    int i=2;
10    printf("\n%d%d\n",++i,++i);
(gdb) break 5    
Breakpoint 1 at 0x8048415: file lab3.c, line 5.
(gdb) run
Starting program: /home/h2o/C/lab3

Breakpoint 1, main () at lab3.c:5
5        char str[]= "s";
(gdb) s
6        int a=5;
(gdb) s
7        printf(a<10? "%50s\n":"%s\n",str);
(gdb) s
                                                 s
9    int i=2;
(gdb) s
10    printf("\n%d%d\n",++i,++i);
(gdb) s

44
12            return 0;
following relevant commands from Internet

gdb command shortcuts

Use following shortcuts for most of the frequent gdb operations.
  • l – list
  • p – print
  • c – continue
  • s – step
  • ENTER: pressing enter key would execute the previously executed command again.

Miscellaneous gdb commands

  • l command: Use gdb command l or list to print the source code in the debug mode. Use l line-number to view a specific line number (or) l function to view a specific function.
  • bt: backtrack – Print backtrace of all stack frames, or innermost COUNT frames.
  • help – View help for a particular gdb topic — help TOPICNAME.
  • quit – Exit from the gdb debugger.

No comments:

Post a Comment