一、编译运行
1.1、程序带调试信息
使用额外的 '-g' 选项来编译程序:
gcc -g eg.c -o eg
1.2 运行 gdb
装载程序
方法一:在 shell 中,可以使用 'gdb' 命令并 指定程序名 作为参数来运行 gdb
gdb + 程序名
方法二:在 gdb 中,可以使用 file 命令来装入要调试的程序
(gdb)file + 文件名
两种方式都假设您是在包含程序的目录中执行命令。
命令 缩写 功能
run r 运行程序
continue c (fg) 继续执行直到下一次断点
until +行号 u 继续执行直到指定行
每次执行结束重新输入 run 可重新执行
参数设置
装入程序之后,可以用 gdb 命令 'run + 运行参数' 来启动程序。
run + 参数 # 启动程序 或者 restart
或者在执行run前 通过 set args + 运行参数 设置
set args + 运行参数
run
如果一切正常,程序将执行到结束(要是不想让其结束要提前设置断点),此时 gdb 将重新获得控制。
1.3 退出gdb
quit [退出条件] # 退出gdb
二、调试命令
2.1 设置断点
普通断点
命令 缩写 用法1 用法2 用法3
break b b + 函数名 b + 行号(文件名:行号) b + *地址(*0x7c00)
查看断点
info breakpoints
条件断点
(1) break + .. + if 条件
(2) condition 断点号 条件
根据规则设置断点
rbreak printNum* #所有以printNum开头的函数都设置了断点
rbreak . #对所有函数设置断点
rbreak test.c: . #对test.c中的所有函数设置断点
rbreak test.c:^print #对以print开头的函数设置断点
临时断点
断点只想生效一次,可以设置临时断点
tbreak test.c:l0 #在第10行设置临时断点
删除断点
clear #删除当前行所有breakpoints
clear function #删除函数名为function处的断点
clear filename:function #删除文件filename中函数function处的断点
clear lineNum #删除行号为lineNum处的断点
clear filename:lineNum #删除文件filename中行号为lineNum处的断点
delete #删除所有breakpoints,watchpoints和catchpoints
delete bnum #删除断点号为bnum的断点
跳过多次设置断点
ignore + 断点号 + 忽略次数
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000004005e8 in printNum2 at test.c:16 ignore next 30 hits
根据表达式值变化产生断点
需要观察某个值或表达式,知道它什么时候发生变化
watch + 变量或者表达式的值
watch + 条件
让程序继续运行,如果值发生变化,则会打印相关内容,如:
Hardware watchpoint 2: a
Old value = 12
New value = 11
其 info breakpoints 信息
Num Type Disp Enb Address What
2 hw watchpoint keep y a breakpoint already hit 11 times
禁用或启动断点
有些断点暂时不想使用,但又不想删除,可以暂时禁用或启用。例如:
disable #禁用所有断点
disable bnum #禁用标号为bnum的断点
enable #启用所有断点
enable bnum #启用标号为bnum的断点
enable delete bnum #启动标号为bnum的断点,并且在此之后删除该断点
2.2 单步执行
命令 缩写 用法 用法1
next n 执行一行源程序代码,不进入函数 n + 步数
step s 执行一行源程序代码,单步跟踪进入函数 s + 步数
nexti ni 执行一行汇编程序代码,不进入函数 ni + 步数
stepi si 执行一行汇编程序代码,单步跟踪进入函数 si + 步数
finish 跳过该函数,继续后面的执行
2.3 查看变量
在查看变量之前,需要先启动调试并设置断点
命令 缩写 用法1 用法2
print p p + 变量名 p + 数组名
命令 缩写 用法3 用法4 用法5
print p p + 文件名(函数名) :: 变量名 p + *(地址或指针) p + *指针@数量
环境变量$
$ 可表示上一个变量,假设此时有一个链表linkNode,它有next成员代表下一个节点,则可使用下面方式不断打印链表内容:
(gdb) p *linkNode #显示linkNode节点内容
(gdb) p *$.next #显示linkNode节点下一个节点的内容
如果想要查看前面数组的内容,你可以将下标一个一个累加,还可以定义一个类似UNIX环境变量,这样就不需要每次修改下标去打印,例如:
(gdb) set $index=0
(gdb) p b[$index++]
$11 = 1
(gdb) p $pc # 当前指令
2.4 打印格式
x 按十六进制格式显示变量。 d 按十进制格式显示变量。 o 按八进制格式显示变量。
t 按二进制格式显示变量。 c 按字符格式显示变量。 f 按浮点数格式显示变量。
(gdb) p/x c
2.5 查看内存
命令 用法 用法1
x 查看内存内容 x / [n内存单元数] [f格式] [u单元长度] addr地址
格式
t 二进制 x 十六进制 d 十进制 o 八进制 u 十进制无符号
c 字符 s 字符串 f 浮点数 z 零拓展十六进制 a 地址单元的长度
i 指令地址格式
单元长度
b 字节 h 双字节 w 四字节 g 八字节
默认是4个byte
查看堆栈信息
x /8x $esp
2.6 自动显示变量
程序断住时,就显示某个变量的值
命令 用法 用法1
display 查看变量名 display + 变量名
清除变量
delete display num # num变量的编号,不带num时清除所有变量
去使能
disable display num # num为变量的编号,不带num时去使能所有
2.4 info
命令 缩写 功能
info breakpoints i b 查看已设置断点
info watchpoints i wat 查看已设置观测点
info registers i r 查看所有寄存器
info skip i s 查看所有需要跳过的函数
info local i lo 查看当前函数局部变量
help info可查看更多
2.7 skip
命令 功能
skip + 函数名 单步执行时跳过一些不想关注的函数
skip file + 文件名 单步执行时跳过某个文件的代码
skip delete [num] 删除对应编号skip
skip enable [num] 使能对应编号skip
skip disable [num] 去使能对应编号skip
三、查看源码
3.1 list
list 列出指定行附件的源码
命令 缩写 用法1 用法2 用法3 用法4
list l l + 行号 l + 函数名 l 行号 , 行号(指定范围) l + 文件名:行号
set listsize 20 # 显示 每次显示的行数