GDB, The GNU Project debugger, allows you to see what is going on inside another program while it executes – or what another program was doing at the moment it crashed.
GDB 主要完成以下四件事:
- 启动程序,指定影响程序运行的条件。
- 使程序在特定的条件下停止。
- 程序停止时,检查程序锁发生的事。
- 动态的改变程序的执行环境。
前期准备
GDB 一般用于调试C/C++
程序,要想能够使用GDB
调试C/C++
程序,首先必须将调试信息添加到可执行程序中。使用gcc/g++
的-g
参数可以做到这一点。如:
1
|
|
此时,可执行程序programe
中就包含了调试需要的各种信息,如程序函数名、变量名等。
对于 MAC OSX 系统,调试信息会包含在另外一个programe.dSYM
(debug symbols)文件夹下面,可以使用dwarfdump programe.dSYM
直接查看各符号信息。
启动GDB方法
- gdb
program就是执行的文件,一般在当前目录下。 - gdb
core 用GDB同事调试一个运行程序和 core 文件,core 是程序非法执行后 core dump 后产生的文件。 - gdb
如果程序是一个服务程序,则可以指定服务程序运行时的进程ID。gdb 自动 attach 上去,并调试它。 program 应该在 PATH 环境变量中搜索得到。
如果出现Segment Fault
,可以通过方法 2 来进行 Debug 程序,启动方式为gdb {executable} {dump file}
,如果没有产生 core 文件,需要在执行 executable 之前先执行如下命令:
1
|
|
设置运行参数
set args 可指定运行时参数。(如:set args 10 20 30)
show args 命令可以查看设置好的运行参数。
查看源码
1 2 |
|
断点break 使用
设置断点的方法
1 2 3 4 5 |
|
查看断点信息
1 2 |
|
条件断点,就是在上述设置断点的同时,指定断点的进入条件。
1
|
|
忽略前面的某个断点
1
|
|
运行程序
运行程序如下
1 2 |
|
查看运行时数据
1 2 |
|
当运行程序到某个位置时,我们希望看看此时程序的状态,比如某个变量的值是否按照预期改变、某块内存的值是否被改。此时就需要用到查看程序运行数据的集中方法。
查看格式 print <expr>
或print /<f> <expr>
,其中<expr>
是要查看的表达式,可以是一个变量、数组、表达式等,<f>
是输出时的格式,比如想要按照 16 进制输出,就使用/x
。
可以使用 examine 命令查看内存地址中的值。格式是x /<n/f/u> <addr>
,其中<addr>
是内存地址。
查看内存数据
在调试代码时,经常需要查看某块内存的数据,此时就需要使用GDB
中的Examining memory。
可以使用命令x
(即examine
)来检查任意格式的内存数据,不管你的程序数据类型。使用的格式为:
1 2 |
|
其中n/f/u 是选项参数,指定内存的大小及显示格式;addr 指定显示的内存的起始地址。n 是十进制的整数,指定小时内存的大小;f 指定显示的格式,它的使用与 GDB 中的 print 使用的格式一样,如x
指定使用 16 进制显示,
d
按十进制格式显示等;u 是指每个显示单元的大小,如b
是指每个显示单元为 byte,h
是指每个显示单元为半字(两个 byte)等;addr 指定要显示的内存的起始地址。
如果需要查看的数据比较多,比如我们需要 dump 一块 buffer 的数据,与特定的数据进行比较,上面提到的examine
就很难实现了。此时需要将块内存 dump 出来。使用到的命令是 dump
或append
或restore
。此处主要介绍dump
命令。
它的格式为:
1
|
|
从格式可以看出,它的含义是从start_addr
开始到end_addr
结束的 memory dump 到 指定的文件 filename 中。
分割窗口
layout 用于分割窗口,可以一边查看代码,一边测试。主要有以下几种用法:
- layout src:显示源代码窗口
- layout asm:显示汇编窗口
- layout regs:显示源代码汇编和寄存器窗口
- layout split:显示源代码和汇编窗口
- layout next:显示下一个 layout
- layout prev:显示上一个 layout
- Ctrl+L:刷新窗口
- Ctrl+x,再按1:单窗口模式,显示一个窗口
- Ctrl+x,再按2:双窗口模式,显示两个窗口
- Ctrl+x,再按a:回到传统模式,即退出 layout, 回到执行 layout 之前的调试窗口
查看寄存器
查看寄存器的值,很简单,可以使用如下命令:
- info registers, 查看寄存器的情况,除了浮点寄存器。
- info all-registers, 查看所有寄存器的情况,包括浮点寄存器。
- info registers
, 查看所指定的寄存器的情况。
同样可以使用 print 命令来访问寄存器的情况,只需要在寄存器名字前加一个$
符号就可以了,例如p $eip
。
汇编调试
在做 ARM 汇编时,需要使用 GDB 对汇编语言进行单步调试,但很多时候,没办法直接通过stepi
或nexti
进入汇编函数内调试。使用了一个迂回的方法:
- 设置断点,在汇编函数名处先设置断点。 break
。 - 直接显示汇编代码,layout asm;显示寄存器值,layout regs。
- 单步执行汇编命令
stepi
和nexti
。
问题汇总
- 在工作中经常遇到把编译处的
.o
或.bin
可执行文件,拿到别的路径下运行、Debug,经常遇到GDB
找不到debug src info
的情况,此时可以通过directory
命令指定寻找的路径。