GDB 调试基本命令
目标
- GDB基本命令
- GDB的高级增强插件的使用
- GDB的多线程多进程调试
- GDB破解和破解讲解
安装下载GDB
sudo apt-get install gdb
wget -q -O- https://github.com/hugsy/gef/raw/master/scripts/gef.sh | sh
安装GDB插件GDF
依次运行 即可安装成功
//安装gef 插件
wget -q -O- https://github.com/hugsy/gef/raw/master/gef.sh | sh
wget -q -O ~/.gdbinit-gef.py https://github.com/hugsy/gef/raw/master/gef.py
echo source ~/.gdbinit-gef.py >> ~/.gdbinit
//安装peda
git clone https://github.com/longld/peda.git ~/peda
//安装gdbinit配置信息
git clone git@github.com:gdbinit/Gdbinit.git
cp Gdbinit/gdbinit ~/.gdbinit
启动 GDB
- gdb FileName gdb 加上要调试的文件名
- 程序已经运行 在用gdb 挂接上去
- 使用 core 文件 启动程序
GDB 基本命令
- 想要调试的程序 在gcc 中必须加上 -g | l | 显示函数体内容 | | —- | —- | | b | 给程序下断点 | | info breakpoints | 查看当前程序下的断点 | | run | 运行程序 | | s | 步进 进入函数中运行调试 | | n nest | 步出 不进入函数中调试 | | p | 查看变量信息 | | u | 跳出当前循环 | | info lpcals | 查看当前函数中所有局部变量的值 | | set listsize | 更换字体大小 | | x / n、f、u | 查看变量地址 | | bt | 查看函数当前函数是谁调用的 | | info frame | 打印栈所有信息 | | shell | 运行shell 命名 | | finish | 结束当前函数 | | disable | 停止断点 | | enable | 启动断点 | | file | 载入符号表 | | set args | 设置 程序进入参数 | | quit | 退出gdb | | display | 每次运行打印信息 | | commands bnum ~~end | 执行到某个断点执行commands bnum中的命令 | | nexti/ni | 汇编执行一条 | | vmmap | 查看当前程序所有段 地址 | | | |
list l
>>> gdb hello //启动gdb
gdb>> l main //显示main 函数内容
gdb>> list 4 //显示主程序前4行代码
gdb>> l hell:4 //显示主程序前4行代码
break
b 18 //在程序18行下断点
break 18 //在程序18行下断点
b 8 if sum>100 //在sum>100时在第8行停下 条件断点
b hello.c:18 if sum>100 //在hello.c文件中的第18行 当sum>100时在第18行停下 条件断点
b heClass::fun //在 heclass类中的fun函数设置断点 针对虚函数
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。c
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。p/a i
c 按字符格式显示变量。p/c i
f 按浮点数格式显示变量。
p i //查看i变量的值c
p i=100 //把i的值改为100
p *arr@24 //查看arr数组的24个元素
until u
set listsize
gdb>> set listsize20 //设置字体为20
examine x
符代参数:
参数 | 含c义 | 助记 |
---|---|---|
n | 表示显示内存的长度 | 个数 |
f | 表示显示的格式,跟print 的格式参数相同 | 单位 |
u | 表示从当前地址往后请求的字节数 | 字符 |
u参数可以用下面的字符来代替
b表示单字节,h表示双字节,w表示四字节,g表示八字节
gdb>> x &i //查看i变量的内存地址
gdb>> x/d &i //查看i变量的内容地址的值为十进制
gdb>> x/10xw 0xffe74 //以十六进制查看10个四字节的地址
gdb>> x/100dw x //查看x数组的100个元素 用10进制四字节表示查看
info proc mappings 查看内存分布
shell
gdb>> shell pwd //在gdcb中运行shell命名
disable / enable c 暂时失效断点
gdb>> info breakpoints //查看当前断点ID号
Num Type Disp Enb Address What
1 breakpoint keep y 0x000055555555464e in main at hello.c:3
breakpoint already hit 1 time
gdb>> disable 1 //取消1号断点
gdb>> enable
gdb>>quit //退出gdb
导入符号表的方法
- 启动后在gdb里面导入
file ./hello.symbol
- 在启动gdb时导入
gdb --symbol-hello.symbol --exec-hello
1.启动后在gdb里面导入
gdb>> file ./hello.symbol
//在当前文件夹下导入hello.symbol 符号表,hello.symbol是用 objcopy --only-keep-debug 生成的
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2.在启动gdb时导入
shell#>> gdb --symbol-hello.symbol --exec-hello
--symbol 表示符号表文件
--exec 启动文件
set args
启动gdb后设置参数
gdb>> set atgs 10 20 30 40 // 传入 4个参数
gdb>> b 20 // 设置断点在20行出
gdb>> bt //查看当前函数调用栈
display
gdb>> display a //每次运行都打印a的值
gdb>> display 0x1024 //每次运行都打印地址的值
commands bnum ~~end
gdb>> b 20 //设置断点
gdb>> info breakpoints //查看断点id
1 breakpoint keep y 0x00005555555546ea in main at hello.c:15
breakpoint already hit 1 time
gdb>> commands 1 //在1号断点id出设置触发代码
> print a
> shell pwdc
> end //结束输入
geb>> run //运行
确定程序是否存在符号表
readelf -s
确定程序是否存在符号表
readelf -s hello //加上文件名
导出符号表文件
objcopy --only-keep-debug
objcopy --only-keep-debug hello hello.symbol
// 把hello的符号表导出成hello.symbol文件
用Debug程序生成Release 程序
objcopy--strip-debug
objcopy --srtip-debug hello hello.release
// 把Debug版的hello程序脱离符号表生成hello.release程序
GDB高级使用方法
GDB 观察点
是当某一个内存/变量被查看/修改时暂停到这个内存这个地址上
- watch 地址
- info watchpoints
- rwatch
如果在局部变量于全局变量重名 他会按照就近原则来匹配
要观察全局就要加上函数名字和双分号
watch i // 在最近的i变量设置内容访问断点
watch main::i // 在main函数中的全局i变量设置内容访问断点
watch *0x10964 // 在0x10964这个内存上设置设置内容访问断点
捕捉点
可以设置捕捉点来捕捉程序运行时的一些事件,如:载入共享库(动态链接库)或是C++的异常。设置捕捉点的格式为:
catch <event>
| | 作用 | 含义 | | —- | —- | —- | | throw | 一个C++抛出的异常 | 只在C++程序中可以使用 | | catch | 一个C++捕捉到的异常 | 只在C++程序中可以使用 | | exec | 调用系统调用exec时 | exec 表示系统调用 如:在一个进程中启动另一个程序 | | fork | 调用系统调用fork时 | fork 表示创建进程 | | load/load | 载入共享库(动态链接库)时 | load 表示 载入新的库文件时 | | unload 或 unload | 卸载共享库(动态链接库)时 | unload表示 删除载入库时 |
gdb>> throw
gdb>> catch exec
gdb>> load<Wso32.so>
搜索原代码
命令 | 含义 |
---|---|
reverse-search | 全部搜索 |
forward-search | 向前面搜索 |
search | 向前面搜索 |
forward-search <regexp>
没有生成的变量 或 还未调用的函数 是搜索不到的
gdb>> b 20 //设置断点
gdb>> run //启动程序 只有进入堆占的 内容才会被搜索到
gdb>> search fun //查找堆占中的fun
GDB多进程多线程调试
多进程
进程是一些资源的总和:内存 文件 时间片 协处理器(gpu dsp)
进程是为了运行程序 进程的创建是复制(fork) 完全复制
gid 表示进程多线程
程序执行单元 线程在进程中 是一直轻量级的进程
测试调试
程序中生成进程 GDB会默认跟随新的进程执行(子进程)
命令 | 含义 |
---|---|
show follow-fork-mode | 显示当前跟随进程 是 parent or child |
set follow-fork-mode parent | 跟随父进程调试 |
set follow-fork-mode child | 跟随子进程调试 |
set detach-on-fork off | 设置未跟随进程暂停运行 |
info inferiors | 查看当前所有运行进程 带*表示正在查看的进程 |
remmove-inferiors | 删除一个进程 |
add-inferior | 复制一个进程 |
dgb>> set detach-on-fork off //暂停的进程等于已经被杀死 不可以在恢复,可以挂接上去
gdb>> info inferiors //查看当前所有运行进程
gdb>> shell ps -ef | grep 3980 //在系统进程中查找 3980的进程
gdb>> inferior <进程编号> // 跳转到其他进程中去
gdb>> remmove-inferiors <进程编号> //删除一个进程
挂接到另一个进程中去
命令 | 含义 |
---|---|
inferior | 切换到其他进程中去 |
attach | 挂接到另一个进程中 |
gdb>> info inferiors //查看当前所有运行进程
gdb>> attach 3889 //挂接到3889进程上
- attach
gdb>>
gdb>> attach 38891 //挂接到 38891进程中
- add-inferior
add-inferior [-copies n] [-exec executable]
//copies 表示复制进程ID executable 表示新开一个进程 文件路径
add-inferior -copies 3 //复制3号进程
add-inferior -exec ./hello //新开hello程序
gdb attach 挂接进程
启动方式 2 通过进程ID挂接到程序中
shell>> gdb attach 38891 //挂接到38891进程上
gdb>>