A powerful program debugger.
The gdb command is included in the GNU gcc development suite and is a powerful program debugger. While there are many commands in GDB, mastering about ten of them is generally sufficient for daily basic program debugging.
gdb (options) (parameters)
-cd: Set the working directory;
-q: Quiet mode, does not print introductory and version information;
-d: Add file search paths;
-x: Execute GDB instructions from a specified file;
-s: Set the symbol table file to read.
| Command | Description | Example |
|---|---|---|
| file
|
Loads the executable program file to be debugged. Since GDB is usually executed in the directory where the program is located, the filename does not need a path. |
(gdb) file gdb-sample |
| r | Short for Run, starts the execution of the program being debugged. If no breakpoints have been set, it executes the entire program; if there are breakpoints, the program pauses at the first available breakpoint. |
(gdb) r |
| c | Short for Continue, continues execution of the program being debugged until the next breakpoint or program termination. | (gdb) c |
| b <line_number> b <function_name> b *<function_name> b *<code_address> d [number] |
b: Short for Breakpoint, sets a breakpoint. You can specify the breakpoint location using "line number", "function name", "execution address", etc. Adding "*" before a function name sets the breakpoint at the "prologue code generated by the compiler". If you are unfamiliar with assembly, you can ignore this usage. d: Short for Delete breakpoint, deletes a specific breakpoint by number or all breakpoints. Breakpoint numbers increment starting from 1. |
(gdb) b 8 (gdb) b main (gdb) b *main (gdb) b *0x804835c (gdb) d |
| s, n | s: Executes one line of source code; if there is a function call on this line, it enters the function. n: Executes one line of source code; function calls on this line are executed as a single step. s is equivalent to "Step Into" in other debuggers; n is equivalent to "Step Over". These commands require source code debugging information (compiled with GCC's "-g" parameter). |
(gdb) s (gdb) n |
| si, ni | si is similar to s, and ni is similar to n. The difference is that si/ni target assembly instructions, while s/n target source code lines. | (gdb) si (gdb) ni |
| p <variable_name> | Short for Print, displays the value of a specified variable (local or global). | (gdb) p i (gdb) p nGlobalVar |
| display ... undisplay
|
display: Sets data and its format to be shown every time the program stops. For example, to see the next assembly instruction, use "display /i $pc" where $pc represents the current program counter and /i indicates hexadecimal display. This is useful when focusing on assembly code. undisplay: Cancels previous display settings; numbers increment from 1. |
(gdb) display /i $pc (gdb) undisplay 1 |
| i | Short for info, used to display various types of information. See "help i" for details. | (gdb) i r |
| q | Short for Quit, exits the GDB debugging environment. | (gdb) q |
| help [command_name] | GDB help command, providing explanations for various GDB commands. If a "command_name" parameter is provided, it shows the detailed description of that command; otherwise, it lists all GDB commands by category. |
(gdb) help |
File: Binary executable program.
The following is an example of GDB debugging on Linux. First, a small sample C program:
#include <stdio.h>
int nGlobalVar = 0;
int tempFunction(int a, int b)
{
printf("tempFunction is called, a = %d, b = %d /n", a, b);
return (a + b);
}
int main()
{
int n;
n = 1;
n++;
n--;
nGlobalVar += 100;
nGlobalVar -= 12;
printf("n = %d, nGlobalVar = %d /n", n, nGlobalVar);
n = tempFunction(1, 2);
printf("n = %d", n);
return 0;
}
Copy this code and save it as gdb-sample.c, then switch to the directory and compile it with GCC:
gcc gdb-sample.c -o gdb-sample -g
In the command line above, the -o parameter specifies the output executable name as gdb-sample, and -g compiles source code information into the executable. Without -g, debugging with GDB becomes difficult. If you don't have the source code, you can only debug at the assembly level.
Start GDB with the following command (ignoring the GDB intro):
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 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 "i386-redhat-linux-gnu".
(gdb)
The last line (gdb) is the GDB prompt, waiting for input.
Load the program gdb-sample using the file command:
(gdb) file gdb-sample
Reading symbols from gdb-sample...done.
The last line indicates successful loading.
Use the r (Run) command. Since no breakpoints are set, it runs until the end:
(gdb) r
Starting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sample
n = 1, nGlobalVar = 88
tempFunction is called, a = 1, b = 2
n = 3
Program exited normally.
Set a breakpoint at the beginning of the main function using the b command:
(gdb) b main
Breakpoint 1 at 0x804835c: file gdb-sample.c, line 19.
The last line shows the breakpoint info: set at line 19 of gdb-sample.c; it's the first breakpoint (index 1); the address is 0x804835c. Line 19 is n = 1, the first executable statement in main.
Run the program again:
(gdb) r
Starting program: /home/liigo/temp/gdb-sample
Breakpoint 1, main () at gdb-sample.c:19
19 n = 1;
The program stops at line 19. The last line indicates the next statement to be executed is n = 1;.
Execute the next line with the s (Step) command:
(gdb) s
20 n++;
Now we check the value of n using the p (Print) command:
(gdb) p n
$1 = 1
Set breakpoints at line 26 and the start of tempFunction:
(gdb) b 26
Breakpoint 2 at 0x804837b: file gdb-sample.c, line 26.
(gdb) b tempFunction
Breakpoint 3 at 0x804832e: file gdb-sample.c, line 12.
Continue execution with c:
(gdb) c
Continuing.
Breakpoint 2, main () at gdb-sample.c:26
26 printf("n = %d, nGlobalVar = %d /n", n, nGlobalVar);
(gdb) p nGlobalVar
$2 = 88
(gdb) c
Continuing.
n = 1, nGlobalVar = 88
Breakpoint 3, tempFunction (a=1, b=2) at gdb-sample.c:12
12 printf("tempFunction is called, a = %d, b = %d /n", a, b);
(gdb) p a
$3 = 1
(gdb) p b
$4 = 2
To see assembly code, use display /i $pc:
(gdb) display /i $pc
(gdb) r
Starting program: /home/liigo/temp/test_jmp/test_jmp/gdb-sample
Breakpoint 1, main () at gdb-sample.c:19
19 n = 1;
1: x/i $pc 0x804835c <main+16>: movl $0x1,0xfffffffc(%ebp)
Use si to execute a single assembly instruction:
(gdb) si
20 n++;
1: x/i $pc 0x8048363 <main+23>: lea 0xfffffffc(%ebp),%eax
To delete all breakpoints, use d:
(gdb) d
Delete all breakpoints? (y or n) y
Exiting with q:
(gdb) q
The program is running. exit anyway? (y or n)
If source code is deleted, line numbers cannot be displayed.
gcc -g gdb.c -o gdb.out # -g supports GDB debugging; -o specifies output
gdb gdb.out # Enter GDB environment
enter # Repeat last command
l # List source code (default 10 lines)
start # Start single-stepping from main()
p a # Print value of variable a
n # Next line
s # Step into function
bt # Backtrace (function stack)
f 1 # Switch to stack frame 1
q # Quit
Test Code:
#include <stdio.h>
void change(int a, int b){
int tmp=a;
a=b; b=tmp;
}
void change2(int *a, int *b){
int tmp=*a;
*a=*b; *b=tmp;
}
int main(){
int a=5,b=3;
change(a,b);
printf("change:\na=%d\nb=%d\n", a,b);
change2(&a,&b);
printf("change2:\na=%d\nb=%d\n", a,b);
}