零、前言
在工作中,无论是学习代码流程还是问题的定位,GDB都显得尤为重要,多掌握一些命令可以提升我们的效率和解决问题的能力;
按照我的理解,对 GDB 的掌握程度可以分为三种人:
- 基础命令,大家都知道;
- 相对高阶一点的,少数人了解,掌握之后可以提升调试解决问题的效率;
- 需要结合反汇编、栈回溯、malloc 内存分配原理和结构、elf 文件结构等知道,配合 GDB 来解决一些内存相关的偶现问题。
一、GDB基础介绍
1.1 简介
gdb 是 GNU 开源组织发布的一个强大的 Linux 下的程序调试工具,gdb 除支持 c/c++ 语言外还支持 go、D、object-c、fortran 等语言。
GDB 主要帮助你完成下面四个方面的功能:
- 启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
- 可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
- 当程序被停住时,可以检查此时你的程序中所发生的事。
- 你可以改变你的程序,将一个BUG产生的影响修正从而测试其他BUG。
1.2 编译
gdb 是开源的,我们可以上网下载开源代码,然后根据自己的交叉编译链这块不是我们的重点,而且网上资料很多,不做展开。
二、GDB的使用
直接在服务器或者当前嵌入式设备环境下运行,如果 gdb 程序为 gdb,应用程序为 build,则运行调试使用命令如下:
gdb ./build
2.1.2 core 分析
查看是否可以生成 coredump 可以在终端输入命令
ulimit -a
如图所示,core file size 为 0 表示用于生成 core 文件的大小为 0,即不生成 core,修改 core file size 可使用命令 ulimit -c yoursize,其中 yousize 为用户指定的大小,若不希望限制大小,可以直接使用命令:
ulimit -c unlimited
core 文件是死机之后为了还原现场进行分析而生成的,后面会详细介绍,这里只是介绍一下 core 文件的解析:
gdb ./build ./core
加载成功之后,可以直接 bt 查看到当前死机的线程,对 core 文件进行分析。
注:
- core 生成的可执行程序要和 core 解析时使用的 debug 版本的可执行程序对应,否则会解析异常
- core 加载有很多问号,需要指定一下动态库的路径。
set solib-search-path ./libso/
set solib-absolute ./libso/
2.2 常用命令
2.2.1 基础命令
命令 | 简介 | gdb功能 | 使用方法及备注 |
---|---|---|---|
run | r | 运行 | 调试开始 |
break | b | 设置断点 | b 断点处 |
info | i | 查看信息 | 查看断点 b,等后面详细列举 |
delete | d | 删除断点 | delete 断点编号 |
disable | disable | 禁用断点 | disable 断点编号 |
backtrace | bt,where | 查看栈帧 | bt N 显示开头 N 个栈帧, bt -N 最后 N 个栈帧 |
p | 打印变量 | p argc 打印变量,后面详细介绍 | |
x | x | 显示内存 | x 0x1234567,后面详细介绍 |
set | set | 改变变量值 | set variable <变量> = <表达式>;比如 set var test=3 |
next | n | 执行下一行 | n 执行到下一行,不管下一行多复杂 |
step | s | 执行下一行 | s 若下一行为函数,则进入函数内部 |
continue | c,cont | 继续 | c 为继续的次数,可省略,表示继续一次 |
finish | finish | 执行完成当前函数 | |
until | until | 执行完成代码块 |
2.2.2 打印变量值
print 支持格式化输出,命令格式:p/格式 变量;支持的格式如下:
格式 | 说明 |
---|---|
x | 显示为16进制 |
d | 显示为10进制 |
u | 显示为无符号10进制 |
o | 显示为8进制 |
t | 显示为2进制数,t表示two |
a | 地址 |
c | 显示为字符 |
f | 浮点小数 |
s | 显示为字符串 |
2.2.3 自动换行
set height 0
去掉 less 的功能,一次性打印所有。
2.2.4 打印所有线程堆栈
thread apply all bt
2.2.5 查看结构体定义
(gdb)ptype pTimeVal
type = struct{
int32 i32tv;
int32 i32Usec;
}
2.2.6 打印格式美观
set print pretty on
2.2.7 打印完整字符串
set print elements 0
2.2.8 打印数组
(gdb)p *sum@4
$35 = {0x1, 0x2, 0x3, 0x4}
2.2.9 查看指令
指令 | 含义 |
info args | 查看当前函数的参数及其值 |
info line | 查看源代码在内存中地址,可以跟行号、函数名 |
info locals | 显示当前函数的局部变量 |
info symbol | 显示全局变量信息 |
info function | 显示所有函数名称 |
info thread | 查看线程信息 |
info registers | 列举寄存器值 |
2.2.10 打印当前进程 map 信息
定位内存相关死机问题时比较常用,确认当前申请的大块内存的头尾
i proc map
(SAW:Game Over!)