From WeChat Official Account: Embedded and Linux Matters
Starting
To start gdb, simply type the gdb command in the shell. After starting, it will display the following information and show the gdb prompt.
➜ example gdb
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 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 "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb)
Test Code
#include <stdio.h>
int minus(int a,int b){
printf("In minus():\n");
int c = a-b;
return c;
}
int sum(int a, int b) {
printf("In sum():\n");
int c = a+b;
return c;
}
void print(int xx, int *xxptr) {
printf("In print():\n");
printf(" xx is %d and is stored at %p.\n", xx, &xx);
printf(" ptr points to %p which holds %d.\n", xxptr, *xxptr);
int c = sum(2,3);
int d = minus(3,2);
}
int main(void) {
int x = 10;
int *ptr = &x
printf("In main():\n");
printf(" x is %d and is stored at %p.\n", x, &x);
printf(" ptr points to %p which holds %d.\n", ptr, *ptr);
print(x, ptr);
return 0;
}
Setting Breakpoints
Breakpoints can be set at function names and line numbers. When the program runs and reaches a breakpoint, it will automatically pause. At this point, you can check the variable values at that moment, display the stack frames, reset breakpoints, or rerun the program. The breakpoint command (break) can be abbreviated as b.
Format
break breakpoint
Example
(gdb) b main
Breakpoint 1 at 0x758: file gdb_example.c, line 9.
Format
break function_name
break line_number
break filename:line_number
break filename:function_name
break + offset
break - offset
break * address
Example
(gdb) b print
Breakpoint 2 at 0x709: file gdb_example.c, line 4.
(gdb) b gdb_example.c:5
Breakpoint 3 at 0x715: file gdb_example.c, line 5.
(gdb) b +3
Note: breakpoint 2 also set at pc 0x709.
Breakpoint 4 at 0x709: file gdb_example.c, line 4.
(gdb) b *0x709
Note: breakpoints 2 and 4 also set at pc 0x709.
Breakpoint 5 at 0x709: file gdb_example.c, line 4.
(gdb)
The examples above set breakpoints for the print function, at line 5 of gdb_example.c, 3 lines after the current pause position, and at address 0x709.
Breakpoints can be confirmed using info break.
(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000000758 in main at gdb_example.c:9
2 breakpoint keep y 0x0000000000000709 in print at gdb_example.c:4
3 breakpoint keep y 0x0000000000000715 in print at gdb_example.c:5
4 breakpoint keep y 0x0000000000000709 in print at gdb_example.c:4
5 breakpoint keep y 0x0000000000000709 in print at gdb_example.c:4
Displaying Stack Frames
The backtrace command can display stack frames when execution is paused at a breakpoint. This command is abbreviated as bt. Additionally, backtrace has aliases such as where and info stack (abbreviated as info s).
backtrace
bt
Display All Stack Frames
backtrace N
bt N
Only Display the First N Stack Frames
backtrace -N
bt -N
Only Display the Last N Stack Frames
backtrace full
bt full
backtrace full N
bt full N
backtrace full -N
bt full -N
Example
(gdb) b 4
Breakpoint 1 at 0x714: file gdb_example.c, line 4.
(gdb) r
Starting program: /home/zhongyi/code/example/gdb_example
In main():
x is 10 and is stored at 0x7fffffffe2fc.
ptr points to 0x7fffffffe2fc which holds 10.
In print():
xx is 10 and is stored at 0x7fffffffe2cc.
ptr points to 0x7fffffffe2fc which holds 10.
In sum():
In minus():
Breakpoint 1, minus (a=3, b=2) at gdb_example.c:4
4 int c = a-b;
# Display stack frames
(gdb) bt
#0 minus (a=3, b=2) at gdb_example.c:4
#1 0x00005555555547c0 in print (xx=10, xxptr=0x7fffffffe2fc) at gdb_example.c:17
#2 0x0000555555554841 in main () at gdb_example.c:28
# Only show the first 2 stack frames
(gdb) bt 2
#0 minus (a=3, b=2) at gdb_example.c:4
#1 0x00005555555547c0 in print (xx=10, xxptr=0x7fffffffe2fc) at gdb_example.c:17
(More stack frames follow...)
# Show the last 2 stack frames and their local variables
(gdb) bt full -2
#1 0x00005555555547c0 in print (xx=10, xxptr=0x7fffffffe2fc) at gdb_example.c:17
c = 5
d = 21845
#2 0x0000555555554841 in main () at gdb_example.c:28
x = 10
ptr = 0x7fffffffe2fc
(gdb)
After displaying the stack frames, you can confirm where the program stopped and the call path of the program.
Displaying Variables
Format
print variable
Example
(gdb) p x
$1 = 10
(gdb) p ptr
$2 = (int *) 0x7fffffffe2fc
(gdb)
Displaying Registers
Example
(gdb) info reg
rax 0xc 12
rbx 0x0 0
rcx 0x7ffff7af2104 140737348837636
rdx 0x7ffff7dcf8c0 140737351841984
rsi 0x555555756260 93824994337376
rdi 0x1 1
rbp 0x7fffffffe310 0x7fffffffe310
rsp 0x7fffffffe2f0 0x7fffffffe2f0
r8 0x7ffff7fe14c0 140737354011840
r9 0x0 0
r10 0x0 0
r11 0x246 582
r12 0x5555555545f0 93824992232944
r13 0x7fffffffe3f0 140737488348144
r14 0x0 0
r15 0x0 0
rip 0x555555554841 0x555555554841 <main+123>
eflags 0x202 [ IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
Precede registers with $, to display the contents of the registers.
(gdb) p $rdi
$7 = 1
(gdb) p $rax
$8 = 12
(gdb)
Displaying registers can use the following format
p/format variable
Format | Description |
---|---|
x | Display as hexadecimal |
d | Display as decimal |
u | Display as unsigned decimal |
o | Display as octal |
t | Display as binary |
a | Address |
c | Display as ASCII |
f | Floating point |
s | Display as string |
i | Display as machine language (only available in the x command) |
Displaying Memory
The x command can display the contents of memory
Format
x/format address
Example
(gdb) x $r12
0x5555555545f0 <_start>: xor %ebp,%ebp
(gdb) x $r8
0x7ffff7fe14c0: rclb $0xf7,(%rsi,%rdi,8)
(gdb)
x/i can display assembly instructions. Generally, when using the x command, the format is x/NFU ADDR. Here ADDR is the address you wish to display, N is the number of repetitions, and F represents the format discussed earlier. The unit u represents the following.
Unit | Description |
---|---|
b | Byte |
h | Halfword (2 bytes) |
w | Word (4 bytes) |
g | Double word (8 bytes) |
The following displays 10 instructions starting from rsp.
(gdb) x/10i $rsp
0x7fffffffe2f0: (bad)
0x7fffffffe2f1: rex.W push %rbp
0x7fffffffe2f3: push %rbp
0x7fffffffe2f4: push %rbp
0x7fffffffe2f5: push %rbp
0x7fffffffe2f6: add %al,(%rax)
0x7fffffffe2f8: lock rex.RB push %r13
0x7fffffffe2fb: push %rbp
0x7fffffffe2fc: or (%rax),%al
0x7fffffffe2fe: add %al,(%rax)
Displaying Disassembly
Format
disassemble
Format 1 disassembles the entire current function, format 2 disassembles the entire function where the program counter is located. Format 3 disassembles a portion from the start address to the end address.
(gdb) disassemble
Dump of assembler code for function sum:
0x0000555555554722 <+0>: push %rbp
0x0000555555554723 <+1>: mov %rsp,%rbp
0x0000555555554726 <+4>: sub $0x20,%rsp
0x000055555555472a <+8>: mov %edi,-0x14(%rbp)
0x000055555555472d <+11>: mov %esi,-0x18(%rbp)
0x0000555555554730 <+14>: lea 0x1bd(%rip),%rdi # 0x5555555548f4
0x0000555555554737 <+21>: callq 0x5555555545b0 <puts@plt>
=> 0x000055555555473c <+26>: mov -0x14(%rbp),%edx
0x000055555555473f <+29>: mov -0x18(%rbp),%eax
0x0000555555554742 <+32>: add %edx,%eax
0x0000555555554744 <+34>: mov %eax,-0x4(%rbp)
0x0000555555554747 <+37>: mov -0x4(%rbp),%eax
0x000055555555474a <+40>: leaveq
0x000055555555474b <+41>: retq
End of assembler dump.
Single Step Execution
Execute a line in the source code: next
Enter the function and execute: step
Execute assembly instructions one by one: nexti, stepi
Continue Running
Format
continue
continue times
By specifying the number of times, breakpoints can be ignored. For example, continue 5 will not stop at the breakpoint for 5 encounters, and will only stop at the 6th encounter.
Watchpoints
Format
watch <expression>
<expression> will pause execution when it changes, where <expression> can be a constant or variable
awatch <expression>
<expression> will pause execution when it is accessed or changed
rwatch <expression>
<expression> will pause execution when it is accessed
Example
(gdb) watch c
Hardware watchpoint 2: c
(gdb) c
Continuing.
Hardware watchpoint 2: c
Old value = 21845
New value = 5
sum (a=2, b=3) at gdb_example.c:10
10 return c;
(gdb)
Format
Deleting Breakpoints and Watchpoints
delete <number>
<number> refers to the breakpoint or watchpoint
Example
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x000055555555473c in sum at gdb_example.c:9
breakpoint already hit 1 time
2 hw watchpoint keep y c
breakpoint already hit 1 time
(gdb) delete 2
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x000055555555473c in sum at gdb_example.c:9
breakpoint already hit 1 time
(gdb)
Changing Variable Values
Format
set variable <variable>=<expression>
Example
(gdb) p c
$1 = 5
(gdb) set variable c=0
(gdb) p c
$2 = 0
(gdb)
Generating Core Dump Files
(gdb) generate-core-file
warning: Memory read failed for corefile section, 4096 bytes at 0xffffffffff600000.
Saved corefile core.2380
With a core dump file, you can view the execution history at the time of the dump even after exiting GDB.
gcore 'pidof gdb_example'
This command generates a core dump file directly from the command line without stopping the running program. It is very useful when analyzing issues on other machines or customer site problems.
Conditional Breakpoints
break breakpoint if condition
If the condition is true, execution will pause
condition breakpoint_number
condition breakpoint_number condition
The first command deletes the trigger condition for the specified breakpoint number, and the second command adds a trigger condition to the breakpoint.
Repeated Execution
ignore breakpoint_number times
At the specified breakpoint or watchpoint, ignore the specified number of times.
continue and ignore can also specify the number of times, and will not pause when reaching the breakpoint before the specified number.
continue times
step times
stepi times
next times
nexti times
finish
until
until address
finish pauses after executing the current function, and the until command pauses after executing the current function or code block, commonly used to break out of loops.
Deleting Breakpoints or Disabling Breakpoints
clear
clear function_name
clear line_number
clear filename:line_number
clear filename:function_name
delete [breakpoints] breakpoint_number
clear is used to delete defined breakpoints
disable [breakpoints]
disable [breakpoints] breakpoint_number
disable display display_number
disable mem memory_region
disable temporarily disables breakpoints. The third format disables displays defined by the display command, and the fourth format disables memory regions defined by the mem command.
enable
enable [breakpoints] breakpoint_number
enable [breakpoints] once breakpoint_number
enable [breakpoints] delete breakpoint_number
enable disable display display_number
enable mem memory_region
once makes the specified breakpoint enable only once. delete means to delete the breakpoint after the run is paused.
Breakpoint Commands
Format
commands breakpoint_number
command
...
end
The program will automatically execute commands when paused at the specified breakpoint.
Example
(gdb) b 17
Breakpoint 3 at 0x5555555547b1: file gdb_example.c, line 17.
(gdb) command 3
Type commands for breakpoint(s) 3, one per line.
End with a line saying just "end".
>p c
>end
(gdb) r
Starting program: /home/zhongyi/code/example/gdb_example -e 'p 1'
In main():
x is 10 and is stored at 0x7fffffffe2ec.
ptr points to 0x7fffffffe2ec which holds 10.
In print():
xx is 10 and is stored at 0x7fffffffe2bc.
ptr points to 0x7fffffffe2ec which holds 10.
In sum():
Breakpoint 3, print (xx=10, xxptr=0x7fffffffe2ec) at gdb_example.c:17
17 int d = minus(3,2);
$1 = 5
The example above shows pausing at line 17 and printing the value of c.
Using in combination with previous conditional breakpoints, complex actions can be executed when pausing at the breakpoint.
Example
break 17 if c==5
commands
silent
printf "x is %d\n",x
cont
end
Common Commands and Their Abbreviations
Command | Abbreviated Form | Description |
---|---|---|
backtrace | bt/where | Display backtrace |
break | Set breakpoint | |
continue | c/cont | Continue running |
delete | d | Delete breakpoint |
finish | Run to function end | |
info breakpoints | Display breakpoint info | |
next | n | Execute next line |
p | Display expression | |
run | r | Run program |
step | s | Execute one line, including inside functions |
x | Display memory content | |
until | u | Execute to specified line |
directory | dir | Insert directory |
disable | dis | Disable breakpoint |
down | do | Select stack frame to display in current stack frame |
edit | e | Edit file or function |
frame | f | Select stack frame to display |
forward-search | fo | Search forward |
generate-core-file | gcore | Generate core dump |
help | h | Display help documentation |
info | i | Display information |
list | l | Display function lines |
nexti | ni | Execute next line (in assembly code) |
print-object | po | Display target information |
sharedlibrary | share | Load symbols of shared library |
stepi | si | Execute next line |
Value History
The values displayed through the print command are recorded in an internal value history, and these values can be used in other expressions.
Example
(gdb) b 16
Breakpoint 1 at 0x79f: file gdb_example.c, line 16.
(gdb) b 17
Breakpoint 2 at 0x7b1: file gdb_example.c, line 17.
(gdb) b 29
Breakpoint 3 at 0x841: file gdb_example.c, line 29.
(gdb) r
Starting program: /home/zhongyi/code/example/gdb_example
In main():
x is 10 and is stored at 0x7fffffffe2fc.
ptr points to 0x7fffffffe2fc which holds 10.
In print():
xx is 10 and is stored at 0x7fffffffe2cc.
ptr points to 0x7fffffffe2fc which holds 10.
Breakpoint 1, print (xx=10, xxptr=0x7fffffffe2fc) at gdb_example.c:16
16 int c = sum(2,3);
(gdb) p c
$1 = 1431651824
(gdb) c
Continuing.
In sum():
Breakpoint 2, print (xx=10, xxptr=0x7fffffffe2fc) at gdb_example.c:17
17 int d = minus(3,2);
(gdb) p c
$2 = 5
(gdb) c
Continuing.
In minus():
Breakpoint 3, main () at gdb_example.c:29
29 return 0;
The final value can be accessed using $.
Using show values, you can display the last 10 values from history.
Example
(gdb) show values
$1 = 1431651824
$2 = 5
$3 = 10
$4 = 10
(gdb)
Accessing variables and descriptions in value history
Variable | Description |
---|---|
$ | Last value in history |
$n | nth value in history |
$$ | Second last value in history |
$$n | nth last value in history |
$_ | Last address shown by x command |
$__ | Last value of the last address shown by x command |
$_exitcode | Return code of the program being debugged |
$bpnum | Last set breakpoint number |
You can define variables freely. Variables start with $, followed by letters and numbers.
Example
(gdb) set $i=0
(gdb) p $i
$5 = 0
(gdb)
Command History
You can save commands in a file, and once saved, you can use them in other debugging sessions. The default command history file is located at<span>./.gdb_history</span>
set history expansion
show history expansion
You can use csh style ! character
set history filename filename
show history filename
You can save command history to a file, and the default file can be changed using the environment variable GDBHISTFILE.
set history save
show history save
Enables saving and restoring command history to and from a file.
set history size number
show history size
Sets the number of commands to save in command history, default is 256.
Initialization File (.gdbinit)
The gdb initialization file in Linux is .gdbinit. If the .gdbinit file exists, GDB will execute it as a command file before starting.
The order is as follows:
-
$HOME/.gdbinit -
Command line options -
./.gdbinit -
Load command file given by -x option
Command Definitions
You can define commands using define, document can add descriptions to the defined commands, and you can view defined commands using help command_name.
Format for define:
define command_name
command
………...
end
Format for document:
document command_name
description
end
Format for help:
help command_name
The following example defines a command named li.
Example
(gdb) define li
Type commands for definition of "li".
End with a line saying just "end".
>x/10i $rbp
>end
(gdb) document li
Type documentation for "li".
End with a line saying just "end".
>list machine instruction
>end
(gdb) li
0x7fffffffe310: (bad)
0x7fffffffe311: rex.W push %rbp
0x7fffffffe312: push %rbp
0x7fffffffe313: push %rbp
0x7fffffffe314: push %rbp
0x7fffffffe315: add %al,(%rax)
0x7fffffffe316: xchg %edi,(%rax,%riz,4)
0x7fffffffe318: idiv %edi
0x7fffffffe31a: jg 0x7fffffffe31c
0x7fffffffe31c: add %al,(%rcx)
(gdb) help li
list machine instruction
You can also write various settings into a file and read these files when running the debugger.
source filename
Summary
This article provides a brief introduction to gdb command scripts, aiming to inspire further exploration. For those interested in a deeper understanding, please refer to the relevant sections of the gdb manual: Extending GDB (https://sourceware.org/gdb/onlinedocs/gdb/Extending-GDB.html).
Finally, I recommend a .gdbinit file on GitHub: https://github.com/gdbinit/Gdbinit. Understanding this will surely help you master gdb script files.
Recommended article: https://blog.csdn.net/lyshark_lyshark/article/details/125846778
—END—