Home gdb常用指令一
Post
Cancel

gdb常用指令一

常见指令

这里记录常用的指令和基本使用方式。

程序运行控制相关指令

显示带行号的源码

使用list(l)命令可以显示源代码,方便确定行号,之后打断点可以用到。

程序启动和重启

使用 runstart 指令,start会在main函数处停下,run会一直运行直到第一个断点。(start相当于在main函数处放了一个断点再run)。run命令简写为r。

另外,重定向功能也是支持的,包括输入重定向,输入重定向,如 run > outpirint.txt

程序继续运行

在遇到断点停下后,(可以进行一些单步执行命令),继续运行程序,使用continue命令,简写为c。

环境设置

经常需要在程序运行前设置一些环境,如启动参数,环境变量,工作目录等。

设置程序启动参数

1
2
3
4
5
(gdb)set args [arg1] [arg2] [...]
# 或 
(gdb) run [arg1] [arg2] [...]
# 查看已设置的参数
(gdb) show args

如果设置时一个都不填,就是没有参数。

设置环境变量

1
2
3
4
5
(gdb) set environment VAR=value
# 查看所有环境变量
(gdb) show environment 
# 查看指定环境变量
(gdb) show environment VAR

对于环境的设置,如果频繁,可以使用初始化文件:创建好文件并将需要的一些初始化命令写入,如设置参数,环境变量等,然后在启动gdb时,指定该 命令文件即可,gdb会自动执行里面的指令。

1
2
vim ./testapp.gdbini
gdb -x ./testapp.gdbini ./testapp

还有一个~/.gdbinit 文件,该文件是用户的全局gdb初始化文件,效果同理,对该用户的所有gdb生效。

断点

break指令是一个用于设置断点的指令。断点是在程序中指定的位置,当程序执行到该位置时,会暂停执行并返回给调试器,以便检查程序状态、变量的值 以及执行路径等。break指令简写为b。

设置断点:

break <location>:在指定的代码位置设置断点。位置可以是函数名、行号或文件名中的函数名/行号组合。例如:

1
2
3
4
5
6
break 123             // 在当前文件的123行设置断点
break file.c:10      // 在 file.c 文件的第 10 行设置断点
break my_function    // 在 my_function 函数入口处设置断点
break file.c:func2   // 在 file.c 中的func2函数处设置断点
break *0x12345678    // 在地址 0x12345678 处设置断点,这里的*是一定要写的
break *(&gb_a)        // 在全局变量gb_a出打断点

条件断点:

break <location> if <condition>:设置条件断点,仅当condition条件满足时才会触发断点,即停下。例如:

1
break main if argc > 5    // 仅当 argc 大于 5 时,在 main 函数处设置断点

如果要修改条件,可以使用

1
condition <breakpoint-number> <new-condiftion>

临时断点:

tbreak <location>:设置临时断点,该断点只会触发一次,触发后自动删除,其他同普通的break指令。

特殊的正则表达式断点

rbreak指令,这个仅对C/C++函数有效,会在函数的开头设置断点。例如:

1
2
# 为所有的 mytestfunc_开头的函数设置断点。
rbreak mytestfunc_*

列出断点:

info breakpoints:列出当前所有已设置的断点。可以写为 info b。里面有一个断点的序号,用于管理断点。

禁用和启用断点:

disable <breakpoint-number>:禁用指定编号的断点。

enable <breakpoint-number>:启用指定编号的断点。

enable:启用所有已禁用的断点。

断点的Num可以通过 info b指令列出查看。

删除断点:

使用deleteclear指令。

delete <breakpoint-number>:删除指定编号的断点。

clear <location>:删除指定位置的断点。

clear:删除所有已设置的断点。

忽略断点N次

可以使用ignore指令忽略count次断点。

ignore <breakpoint-number> <count>

观察点(监视点)

watch指令是一个用于监视变量或表达式的指令。它允许您在程序执行期间跟踪特定变量或表达式的值,并在该值发生更改时暂停程序执行。 通常监视全局变量多一些,局部变量在栈退出后就消失了,监视不到。

监视变量:

watch <variable>:监视指定的变量,并在其值发生更改时暂停程序执行。

watch <expression>:监视指定的表达式,并在其值发生更改时暂停程序执行。

例如:

1
2
3
4
watch my_variable    // 监视名为 my_variable 的变量
watch my_array[i]    // 监视 my_array 数组中索引为 i 的元素
watch ptr_age        // 监视 ptr_age 指针变量
watch *ptr_age       // 监视 ptr_age 指针变量对应的值

条件监视:

watch <expression> if <condition>:设置条件监视,仅当条件满足时才会停止。例如:

1
watch counter if counter > 100    // 仅当 counter 大于 100 时进行监视

观察点类型:

watch:设置读/写观察点,当变量被读取或写入时触发监视。

rwatch:设置读取观察点,当变量被读取时触发监视。

awatch:设置写入观察点,当变量被写入时触发监视。

例如:

1
2
3
watch my_variable    // 读/写观察点
rwatch my_variable   // 读取观察点
awatch my_variable   // 写入观察点

列出/禁用和启用/删除监视点:

相关用法和break指令的用法相似。

info watchpoints:列出当前所有已设置的监视点。

disable <watchpoint-number>:禁用指定编号的监视点。

enable <watchpoint-number>:启用指定编号的监视点。

delete <watchpoint-number>:删除指定编号的监视点。

监视点类型说明

监视点分硬件监视点(hardware watchpoint)软件监视点(software watchpoint),它们的实现有区别。

在实现方式上,软件监视点是GDB调试器每次执行指令后,去检测目标变量(表达式)的值是否发生改变,这样实现的,相当于是“实时都会检测“的方式,所以对程序性能有影响(尤其是有大量循环的场景)。 而硬件监视点,是配合硬件实现的,系统会为GDB调试器提供少量寄存器,并在变量更改时触发中断,大致这样配合完成监视任务的。所以,硬件监视点的性能肯定比软件监视点高。 但相对的,硬件监视点需要硬件支持才行,(x86和arm硬件都有支持),软件监视点没有这样的限制。

在支持数量上,软件监视点的数量通常都比硬件监视点多,软件监视点的数量仅受限于系统资源和GDB的设置,硬件监视点受限于硬件情况。

对于监控类型上,软件监视点可以监视更多的变量和表达式,更强大灵活,硬件监视点主要监视内存地址,比如全局变量。

在使用 GDB 进行调试时,可以通过 set can-use-hw-watchpoints on 命令来启用硬件监视点。(如果支持)。GDB 会尽力使用硬件监视点,但如果达到限制或不适用,则会使用软件监视点。 选项默认是开启的。show can-use-hw-watchpoints 命令来查看当前系统是否支持硬件监视点。

捕获点catch

catch 是一个用于捕捉异常和信号的命令。它允许设置捕获点,以便在程序中发生异常或特定信号时暂停执行并返回给调试器。

捕捉异常:

catch throw:在发生 C++ 异常时暂停执行。 catch catch:在 C++ 异常被捕获时暂停执行。 catch catch throw:同时捕获异常的抛出和捕获。

例如:

1
2
3
catch throw    // 在发生 C++ 异常时暂停执行
catch catch    // 在 C++ 异常被捕获时暂停执行
catch catch throw    // 同时捕获异常的抛出和捕获

捕捉信号:

catch signal <signal-name>:在指定信号发生时暂停执行。可以使用信号名称或信号编号。

例如:

1
2
catch signal SIGSEGV    // 在发生 SIGSEGV(段错误)信号时暂停执行
catch signal 11          // 在发生信号编号为 11 的信号时暂停执行

捕捉系统调用:

catch syscall <syscall-name>:在执行指定的系统调用时暂停执行。

例如:

1
catch syscall open    // 在执行 open 系统调用时暂停执行

条件捕获

catch <event> if <condition>:设置条件捕获,仅当条件满足时才会触发捕获。对上面三个类型适用。示例:

1
catch throw if my_variable > 10    // 仅当 my_variable 大于 10 时进行捕获

更多捕获类型查看 (gdb) help catch

自动化调试命令

可以在断点停下时,自动执行一些用户自定义的命令,典型场景就是断点停下后,打印xx变量的值,通常都是手动打印,使用commands可以实现自动打印:

1
2
3
4
5
6
7
8
commands <breakpoint-number>
... command-list ...
end

commands
printf "x is %d ",x		 // 格式和C中的printf 有一点不一样,必须用gdb中的写法
continue
end

测试示例

1
2
3
4
5
6
7
8
9
10
11
(gdb) b main if gb_a > 0
(gdb) info b
Num     Type           Disp Enb Address            What
4       breakpoint     keep y   0x0000555555555149 in main at ./test.c:7
	stop only if gb_a > 0
(gdb) commands 4 
Type commands for breakpoint(s) 4, one per line.
End with a line saying just "end".
>printf "gb_a is %d",gb_a
>end
(gdb) r

要清除,重新设置命令集为空即可。

状态查看

在程序停止/暂定运行后,可以查看程序的状态,内存变量,寄存器信息等

1
2
# 查看进程状态
(gdb)info program

参考

man gdb

This post is licensed under CC BY 4.0 by the author.

gdb介绍

gdb常用指令二