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:~$