调试器gdb的基本使用方法(1)
本系列主要是记录下Linux环境下的标准调试器GDB的使用方法。GDB的功能极其丰富,各种各样的命令使人眼花缭乱。下面按照调试的流程进行说明,流程如下: (1) 带着调试选项编译、构建调试对象。(2) 启动调试器(GDB)、设置断点、显示栈帧、显示值、继续执行。
0x01. 准备
通过gcc的 -g
选项生成调试信息。即如: $ gcc -Wall -O2 -g 源文件
如果使用Makefile构建,一般要给CFLAGS中指定 -g 选项。如: CFLAGS = -Wall -O2 -g
如果用configure脚本生成Makefile,可以这样用: $ ./configur CFLAGS="-Wall -O2 -g"
构建方法通常会写在INSTALL、README等文件中,参考即可。
0x02. 启动
启动gdb调试器很简单,通过如下命令: $ gdb 可执行文件名
启动后会显示一些信息,并出现gdb提示符。
0x03. 设置断点
可以在函数名和行号等上设置断点。程序运行后,到达断点就会自动暂停运行。此时可以查看该时刻的变量值、显示栈帧、重新设置断点或重新运行等。断点命令break(简写b)。
格式: | |
---|---|
break | 函数名 |
break | 行号 |
break | 文件名:行号 |
break | 文件名:函数名 |
break | +偏移量 |
break | -偏移量 |
break | * 地址 |
如上所示,断点可以通过函数名、当前文件内的行号来设置,也可以先指定文件名再指定行号,还可以指定与暂停位置的偏移量,或者用地址来设置。
0x04. 运行
用run
命令开始运行,不加参数只执行run,就会执行到设置了断点的位置后暂停运行。可以简写为r。
1 | 格式: |
经常用到的一个操作是main()上设置断点,然后执行到main()函数。start
命令能达到同样的效果。
0x05. 显示栈帧
backtrace
命令可以在遇到断点而暂停执行时显示栈帧。该命令简写为 bt
。此外,backtrace
的别名还有where
和info stack
(简写为 info s
)。
命令 | 说明 |
---|---|
backtrace | 显示所有栈帧 |
backtrace N | 只显示开头N个栈帧 |
backtrace -N | 只显示最后N个栈帧 |
backtrace full | 显示所有栈帧和局部变量 |
backtrace full N | 显示开头N个栈帧和局部变量 |
backtrace full -N | 显示最后N个栈帧和局部变量 |
0x06. 显示变量
print
命令可以显示变量。简写为p
。
1 | 格式: print 变量 |
0x07. 显示寄存器
info registers
可以显示寄存器内容,简写 info reg
在寄存器名之前添加$
,即可显示各个寄存器的内容。(gdb) p $eax ===> $8 = 97
显示时可以使用以下格式:p/格式 变量
表1-1 显示寄存器可使用的格式
格式 | 说明 |
---|---|
x | 显示为十六进制数 |
d | 显示为十进制数 |
u | 显示为无符号十进制数 |
o | 显示为八进制数 |
t | 显示为二进制数,t的由来是two |
a | 地址 |
c | 显示为字符(ASCII) |
f | 浮点小数 |
s | 显示为字符串 |
i | 显示为机器语言(仅在显示内存的X命令中可用) |
例如:(gdb) p/c $eax ====>$7 = 97 'a'
用x
命令可以显示内存的内容,x这个名字的由来是eXamining。
显示的格式:x/格式 地址
1 | (gdb) x $pc |
反汇编的命令 disassemble
,简写为disas
格式 | 说明 |
---|---|
disassemble | 反汇编当前整个函数 |
disassemble 程序计数器 | 反汇编程序计数器所在的含数 |
disassemble 开始地址 结束地址 | 反汇编从开始地址到结束地址之前的部分 |
0x08. 单步执行
单步执行的意思是根据源代码一行一行地执行。逐条执行源代码的命令为next
(简写为n
)和step
(简写为s
),其中next
为单步步过,即执行时如果遇到函数调用,则跳到函数调用的下一行;step
为单步步入,即执行时如果遇到函数调用,则跳到函数内部。
如果要逐条执行汇编执行,则可以分别使用nexti
和stepi
。nexti
和stepi
的区别同源码级单步执行。
0x09. 继续运行
调试时,可以使用continue
(简写为C
)命令继续运行程序。程序会在遇到断点后再次暂停运行,如果没有遇到断点,就会一直运行到结束。
格式 | 说明 |
---|---|
continue | 继续运行程序,直到遇到断点 |
continue 次数 | 指定次数可以忽略断点 |
0x10. 监视点
大型软件或大量使用指针的程序中,很难弄清变量在什么地方被改变。要想找到变量在何处被改变,可以使用watch
命令(监视点,watchpoint)。
格式 | 说明 |
---|---|
watch <表达式> | <表达式>发生变化时暂停运行,<表达式>指常量或变量 |
awatch <表达式> | <表达式>被访问、改变时暂停运行 |
rwatch <表达式> | <表达式>被访问时暂停运行 |
0x11. 删除断点和监视点
用delete
(简写d
)命令删除断点和监视点
格式如下:delete <编号>
删除<编号>指示的断点或监视点。