GDB 调试常用命令

GDB是一个非常强大的调试工具。

启动

1
2
3
gdb 可执行文件名  # 直接调试
gdb 可执行文件名 进程PID # 调试某个正在执行的程序
gdb 可执行文件名 core # 调试core

当然,也可以先启动gdb,再使用file命令来加载可执行文件。

指定程序运行时的命令行参数

1
set args 命令行参数

显示源代码

1
2
3
4
list   # 显示当前行后面的源代码
list 函数名 # 显示这个函数的源代码
list n,m # 显示第n行到m行的源代码
layout src # 分屏显示源代码

list可以缩写为l

查看信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
i line  # 查看当前行在内存中的地址
i line test.c:test # test.c中的test函数在内存中的地址
i line 10 # 第10行在内存中的地址
i b # 显示当前所有的断点信息
i b 1 # 显示第一个断点的信息

p 变量 # 查看某个变量的值
p /x(duotacf) 变量 # 按16(10、16无符号整形、8、2、16、字符、浮点)显示变量
p *a@10 # 显示有10个元素的数组a
p x=4 # 修改x为4
p $ip # 打印ip寄存器

display 表达式 # 每次程序暂停时打印表达式的值,用法与p类似
i display # 查看当前的自动显示列表
disable display n # 禁用第n条自动显示
enable display n # 启用第n条自动显示
undisplay n # 删除第n条自动显示
d display n # 删除第n条自动显示

bt # 显示堆栈信息
bt +/-n # 打印栈顶(底)n层的信息

whatis 变量 # 显示变量类型
ptype 变量 # 显示变量详细类型

i r # 打印所有寄存器的值(不包括浮点寄存器)
i all-registers # 打印所有寄存器的值(包括浮点寄存器)
layout regs # 分屏显示寄存器和源代码

iinfo的缩写;
bbreak的缩写;
pprint的缩写;
btbacktrace的缩写;

断点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 普通断点
b # 在下一行打断点
b 函数名 # 在指定函数入口打断点
b 5 # 在第5行打断点
b +/-5 # 在当前行+/-5行的地方打断点
b file:5 # 在文件file的第5行打断点
b file:func # 在文件file的func函数入口打断点
b (上述参数) if a==100 # 如果a==100,就在指定地点打断点
b *地址 # 在内存地址处打断点
tb # 设置临时断点,此断点只会作用一次,具体参数与b类似
rb 正则表达式 # 在指定的函数的开头打断点

# 观察断点
watch 表达式 # 当表达式发生变化时停止
rwatch 表达式 # 读取表达式时停止
awatch 表达式 # 读取或表达式发生变化时停止
i watch # 显示当前所有观察点信息

i b # 显示当前所有的断点信息
i b 1 # 显示第一个断点的信息

disable 1 # 禁用第1个断点
enable 1 # 启用第1个断点
d # 删除所有断点
d n # 删除第n个断点
clear n # 删除第n行上的所有断点

bbreak的缩写;
tbtbreak的缩写;
rbrbreak的缩写;
iinfo的缩写;
ddelete的缩写;

执行程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
start   # 开始执行程序,在main函数入口停止
start 参数 # 传递命令行参数
r # 开始运行程序,直到第一个断点
r 参数 # 传递命令行参数
r > 文件 # 重定向输出到文件

c # 执行程序,直到下一个断点
n # 执行一行代码,不进入函数
n N # 执行N行代码
ni # 执行一行汇编指令
ni N # 执行N行汇编指令
s # 执行一行代码,进入函数
s N # 执行N行代码
si # 执行一行汇编指令
si N # 执行N行汇编指令
u # 执行程序,直到退出当前循环
u N # 执行程序,直到第N行

finish # 执行完当前函数,返回到调用当前函数的函数后停止
return 返回值 # 强制返回当前函数
j 8 # 直接跳转到第8行
call 函数名 # 调用某个函数

rrun的缩写;
ccontinue的缩写;
nnext的缩写;
ninexti的缩写;
sstep的缩写;
uuntil的缩写;
jjump的缩写;

信号

1
2
3
4
5
6
7
8
9
10
signal 信号量  # 产生指定信号量的信号

handle signal nostop # 当被调试的程序收到信号时,GDB不会停住程序的运行,但会打出消息告诉你收到这种信号
handle signal stop # 当被调试的程序收到信号时,GDB会停住你的程序
handle signal print # 当被调试的程序收到信号时,GDB会显示出一条信息
handle signal noprint # 当被调试的程序收到信号时,GDB不会告诉你收到信号的信息
handle signal pass/noignore # 当被调试的程序收到信号时,GDB不处理信号
handle signal nopass/ignore # 当被调试的程序收到信号时,GDB不会让被调试程序来处理这个信号
handle signal info signals # 查看有哪些信号在被GDB检测中
handle signal info handle # 查看有哪些信号在被GDB检测中

显示反汇编代码

1
2
3
disas   # 打印当前执行函数的汇编代码
disas 函数名 # 查看指定函数的汇编代码
layout asm # 分屏显示反汇编后的代码

disasdisassemble的缩写

分屏控制

1
2
3
4
5
6
7
8
9
10
11
12
refresh # 重新绘制屏幕

layout asm # 分屏显示反汇编后的代码
layout regs # 分屏显示寄存器和源代码
layout src # 分屏显示源代码

focus next # 焦点切换到下一个屏幕
focus asm # 焦点切换到asm屏幕
focus cmd
focus src

winheight src -1 # 源代码窗口高度减1

其他技巧

1
2
3
[Enter] # 执行上一次运行的命令
[Ctrl + P] # 上一条命令
[Ctrl + N] # 下一条命令

参考

https://www.cnblogs.com/lvdongjie/p/8994092.html
http://c.biancheng.net/gdb/
https://zhuanlan.zhihu.com/p/429118840
https://zhuanlan.zhihu.com/p/74897601