A GDB Tutorial

 

Aaron Brown

September, 2001

 

Compiling C programs:

 

To compile a .c into object code that you can execute, all you have to do is open up an command shell(e.g. xterm, konsole, rxvt), and "cd" to the directory in which you have stored the file you plan to compile. Next, type "gcc [filename]" and press enter. Assuming, you have no errors with your C code, you will be put back at the command prompt. Type "./a.out" and press enter to see your program run. If you want to name your program something other than "a.out", simply pass the "-o" argument along with a suitable filename e.g. "gcc -o program hw.c". Now, after it compiles, you would simply type "./program". If you want to be able to debug your program, you need to pass the "-g" argument to gcc. This would look like "gcc -g -o debugProg hw.c". You could then use "gdb" to debug your program.

 

Using the GNU Debugger:

 

Debugging using GDB is fun for the whole family. If you have compiled your program using the "-g" argument in gcc, you can use GDB to debug the program. To test your program(simply titled "helloworld" here), simply type "gdb ./helloworld" in the directory with the helloworld in it. Once gdb loads up, you will be at a "(gdb)" prompt.

 

At this point, you can type "run" and hit enter to run your program. If you compiled with the "-g" option in gcc(you did compile with that option didn't you?), if you type "list", you will be given the first ten lines of your program. If you type "list main", you will be given the first ten lines of the function "main". After you have listed those 10 lines, if you type "list" again, you'll be shown the next ten lines.

 

If you want to be able to see the assembly code for the function "main", you simply have to type "disassemble main" and you will be shown the assembly code for the function. If you want to set a break point in the code, all you have to do is find the line in which you want to set the breakpoint and type "break [line number]", or if you want to set the break point at a specific function, you would type "break [function name]".

 

If you run the program again after you have set a breakpoint, when you get to the break point, it will print out the line in the code at which it stopped, and drop you back to a "(gdb)" prompt. If you want to have the program continue running, simply type "cont" and hit enter. If you want to step through the code, type "s" and hit enter(a tip: if you simply hit enter, it reruns the last command you typed. So if you want to continue stepping through your code, you only have to hit enter). If you want to see what breakpoinnts you have set, simply type"info breakpoints" at the "(gdb)" prompt and you'll be shown the breakpoints.

 

To clear a breakpoint simply type "clear [line number]" or "clear [function name]" depending on how you set the breakpoint initially. If you want to clear all the breakpoints, simply type "clear". If you want to stop a program while it is running, you simply hit control+c and the program will stop. This allows you to stop the program arbitrarily and step through code, or get a backtrace(a listing of the call stack of your program. So if you are in function f2() which was called by f1() which was called by main(), it will print out f2, f1, main in that order. This can be obtained via the command "bt" at the "(gdb)" prompt). This should help you on your way to debugging using gdb. If you want a listing of everything that you can do with gdb, simply go to http://www.cslab.vt.edu/manuals/gdb/gdb_toc.html .

 


 

An example session:

 

abrown@quine:~$ gcc -g -o program program.c

abrown@quine:~$ gdb ./program

GNU gdb 19990928

Copyright 1998 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB. Type "show warranty" for details.

This GDB was configured as "i686-pc-linux-gnu"...

(gdb) list

1 main()

2 {

3 int i;

4 for(i = 0; i < 100; i++)

5 {

6 printf("%d\n", i);

7 }

8 printf("we are now outside of the loop. yay.\n");

9 return 0;

10 }

(gdb) run

Starting program: /home/abrown/./program

0

1

2

3

.

.[program output cut due to length]

.

98

99

we are now outside of the loop. yay.

 

Program exited normally.

 


 

(gdb) disassemble main

Dump of assembler code for function main:

0x80483f0 <main>:       push   %ebp

0x80483f1 <main+1>:     mov    %esp,%ebp

0x80483f3 <main+3>:     sub    $0x18,%esp

0x80483f6 <main+6>:     nop   

0x80483f7 <main+7>:     movl   $0x0,0xfffffffc(%ebp)

0x80483fe <main+14>:    mov    %esi,%esi

0x8048400 <main+16>:    cmpl   $0x63,0xfffffffc(%ebp)

0x8048404 <main+20>:    jle    0x8048408 <main+24>

0x8048406 <main+22>:    jmp    0x8048421 <main+49>

0x8048408 <main+24>:    add    $0xfffffff8,%esp

0x804840b <main+27>:    mov    0xfffffffc(%ebp),%eax

0x804840e <main+30>:    push   %eax

0x804840f <main+31>:    push   $0x80484c0

0x8048414 <main+36>:    call   0x8048300 <printf>

0x8048419 <main+41>:    add    $0x10,%esp

0x804841c <main+44>:    incl   0xfffffffc(%ebp)

0x804841f <main+47>:    jmp    0x8048400 <main+16>

0x8048421 <main+49>:    add    $0xfffffff4,%esp

0x8048424 <main+52>:    push   $0x80484e0

0x8048429 <main+57>:    call   0x8048300 <printf>

0x804842e <main+62>:    add    $0x10,%esp

0x8048431 <main+65>:    xor    %eax,%eax

0x8048433 <main+67>:    jmp    0x8048435 <main+69>

0x8048435 <main+69>:    leave 

0x8048436 <main+70>:    ret   

End of assembler dump.

(gdb) break main

Breakpoint 1 at 0x80483f6: file program.c, line 4.

(gdb) run

Starting program: /home/abrown/./program

 

Breakpoint 1, main () at program.c:4

4               for(i = 0; i < 100; i++)

(gdb) cont

.

.[program output cut due to length]

.

(gdb) q

abrown@quine:~$