1、GDB简介
GDB(GNU Debugger)是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。是linux系统环境下的C/C++开发者必须掌握的一个开发工具。
2、 GDB调试流程
2.1 准备
这里用c程序做演示;
#include <stdio.h>
int main()
{
printf("enter main()\n");
int i = 0;
for(; i<10; i++){
printf("---%d\n",i);
}
printf("out main()\n");
return 0;
}
通过 gcc 的 -g
选项,将调试信息加到可执行文件中。
$ gcc -g hello.c -o hello
如果使用 Makefile 构建,一般要在 CFLAGS 中指定 -g
选项。
CFLAGS := -Wall -O2 -g
注意,给 GCC 编译器加上优化选项后,实际的执行顺序可能由于优化而与源代码顺序不同,因此利用调试器跟踪运行时,有时会执行到莫名奇妙的地方,从而造成混乱。
add:附加进程进入GDB调试
# 获取进程id
ps -ef | grep <process name>
# 通过进程id附加进程GDB调试
gdb -p <process id>
2.2 启动
使用命令"gdb <程序名>"启动 gdb
gdb test
gdb -q test //表示不打印gdb版本信息,界面较为干净;
2.3 设置断点
可以使用断点命令 break
在函数名和行号等上设置断点。程序到达断点就会自动暂停运行。此时可以查看该时刻的变量值,显示栈帧、重新设置断点或重新运行等。
设置好的断点可以通过 info break
确认。
2.4 运行
使用 run 参数
命令开始运行,其中参数为可执行程序的参数。如果设置了断点,会执行到设置了断点的位置后暂停运行。
2.5 显示栈帧
backtrace
命令可以在遇到断点或异常而暂停执行时显示栈帧,该命令简写为 bt
。此外,backtrace 的别名还有 where
和 info stack
。
显示栈帧之后,就可以看出程序在何处停止,以及程序的调用路径。
2.6 显示变量
print
命令可以显示变量,可以简写为 p
。
格式:print 变量
。
2.7 显示寄存器
info registers
可以显示寄存器,简写为 info reg
。
在寄存器名之前添加 $,显示寄存器的内容,例如 p $eax
。
p/格式 $寄存器
可以指定寄存器的显示格式,例如 p/c $eax
。可使用的格式如下:
格式 | 说明 |
---|---|
x | 显示为十六进制数 |
d | 显示为十进制数 |
u | 显示为无符号十进制数 |
o | 显示为八进制数 |
t | 显示为二进制数 |
a | 地址 |
c | 显示为字符(ASCII) |
f | 浮点小数 |
s | 显示为字符串 |
i | 显示为机器语言,仅在显示内存的 x 命令中可用 |
程序指针可以写为 $pc,也可以写为 $eip,使用 p $pc
显示程序指针内容。程序指针指向当前程序的运行点的地址。
x
命令可以显示内存的内容,格式:x/<格式> <地址>
。例如 x/i $ps,显示汇编指令。
一般使用 x 命令时,格式为 x/<NFU> <ADDR>。此处 ADDR 为希望显示的地址,N 为重复次数,F 为前面的显示格式,U 代表的单位如下:
单位 | 说明 |
---|---|
b | 字节 |
h | 半字(2 字节) |
w | 字(4 字节)(默认值) |
g | 双字(8 字节) |
例如命令 x\10i $pc 显示从 pc 所指地址开始的 10 条指令。
反汇编命令