启动
gdb 程序名
gdb 程序名 core文件
gdb --pid pid
gdb 程序名 -x 脚本
运行及环境设置
set args #设置运行参数 如nginx -c tem.conf -> set args -c tem.conf
set env [变量名] = 值 #设置环境变量
unset env [变量名] #取消环境变量
show env [变量名] #显示环境变量
流程控制
run 参数 #如nginx -c tem.conf run -c tem.conf 等价于前面的 set args
start 参数 #开始运行,但是会在main函数停止
attach pid #附加进程 等价于 gdb --pid pid
next(n) #下一个条语句 步进
step(s) #下一个条语句 步入
ni #下一条汇编语句 步进
si #下一条汇编语句 步入
finish #退出当前函数
p #输出
printf fmt,... #输出 与c函数类似 -> printf "%s","hello\n\n" 不输出转义
断点命令
break(b)
tbreak #与break相似,只是设置一次断点
rbreak 正则表达式 #给一批满足条件的函数打上断点
info breakpoints #查看断点信息
delete 断点号 #删除断点
disable 断点号 #失效
enable 断点号 #启用
condition 断点号 条件 #增加断点条件 (如: condition 2 sum==6)
condition 断点号 #删除断点条件
ignore 断点号 数目 #忽略断点n次
commands 断点号 #断点触发后执行语句
语句
end
demo
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
int sum = 0;
int i = 0;
for (i = 0;i < 10;i++) {
sum += i;
}
printf("sum = %d\n",sum);
return 0;
}
代码断点
break 行号
break 函数名(默认是main函数的文件)
break 文件名:函数名 (如:b ngx_array.c:ngx_array_create)
break 文件名:行号
条件断点
b 行号 if 条件 (如: b 11 if i==5)
内存断点
awatch #读写断点
watch #写断点
rwaich #读断点
三个命令的用法一致,以awatch举例
awatch 变量名(如:awatch sum) #不建议这么使用
awatch *地址(如:awatch *0x000aaaxasd) #表示读写这个地址对应的内存断下
多线程调试
info threads #看所有线程信息
thread 线程id #切换到指定线程
break 行号信息 thread 线程号 #线程断点
多进程调试
set follow-fork-mode child|parent #fork后,需要跟踪谁
show follow-fork-mode
info forks #显示所有进程信息
fork 进程id #切换到某个进程
detach-fork 进程id #不再跟踪某个进程
delete fork 进程id #kill某个进程并停止对它的跟踪
进程信息查看
信号
info signals #列出所有信号的处理方式
handle 信号 方式 #改变当前处理某个信号的方式
方式包括:
nostop # 当信号发生时不停止,只打印信号曾经发生过
stop # 停止并打印信号
print # 信号发生时打印
noprint # 信号发生时不打印
pass/noignore #应用程序看到这个信号
nopass/ignore #应用程序忽略这个信号
栈帧
bt #查看堆栈
frame(f) [帧号] #不带参数时显示所有帧信息,带参数时切换到指定帧
info frame #显示当前帧信息
info frame addr #显示指定地址的帧信息
info args #显示帧的参数
info locals #显示局部变量信息
info catch #显示本帧异常信息
内存查看
x /nfu 地址 # 查看内存
n 重复n次
f 显示格式,为print使用的格式 z 16进制
u 每个单元的大小,为
b byte
h 2 byte
w 4 byte
g 8 byte
常用: x/20gz 地址 x/20wz 地址
gef使用者
dq 地址 8
dd 地址 4
dw 地址 2
dc 地址 1
显示长度 l
如:
dq 0x000addsafds l20
代码查看
list(l) [行号|函数|文件:行号] #显示指定位置的信息,无参数为当前位置
set listsize n #修改每次显示的行数
show listsize
info line [函数名|行号] #显示指定位置对应的机器码地址范围
disassemble [函数名 | 起始地址 结束地址] #对指定范围进行反汇编
set disassembly-flavor att|intel #指定汇编代码形式
show disassembly-flavor
#宏查看 gcc 编译添加 -gdwarf-2 -g3
info macro 宏名
脚本
gdb 默认加载脚本 ~/.gdbinit
其他要加载脚本可以 在~/.gdbinit里source其他脚本 或者 使用 gdb -x
#变量设置
set $val = 0
#函数定义
#define fun_test
语句
end
#函数参数 $arg0 $arg1..
#分支 (仅仅支持这种 没有elif else if)
if 条件
else
end
#循环
while 条件
end
demo
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
int arr[] = {1,2,3,4,5,6,7};
return 0;
}
脚本案例:写一个调试函数输出arr数组的所有下标是2的倍数的值
define for_int
set $count = 0
while($count < $arg1)
if $count%2 == 0
p $arg0[$count]
end
set $count++
end
end
把脚本写入一个文件gdb_test
#启动
gdb test -x gdb_test
b 7
r
l
int main(int argc,char *argv[])
{
int arr[] = {1,2,3,4,5,6,7};
return 0; ← $pc
}
for_int arr 7
$1 = 0x1
$2 = 0x3
$3 = 0x5
$4 = 0x7