调试器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 <编号>
删除<编号>指示的断点或监视点。