GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具
一般来说,GDB主要完成下面四个方面的功能:
1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
3、当程序被停住时,可以检查此时你的程序中所发生的事。
4、动态的改变你程序的执行环境。
GDB的执行方式:
- gdb <program> :program也就是你的执行文件,一般在当前目录下。
- gdb <program> core:用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件。
- gdb <program> <PID>:如果你的程序是一个正在运行程序,那么你可以指定这个程序运行时的进程ID。gdb会自动attach上去,并调试他。
调试带参数的程序时,先gdb <program> 进入调试界面,然后设置程序运行时的参数,输入命令 :
set args [para list]
GDB常用命令:
- file <FILE>:指定一个可执行文件进行调试,读取指定文件的调试信息,如 file a.exe
- l[ist] :从第一行开始例出原码
- r[un] :装载完要调试的可执行文件后,可以用 run 命令运行可执行文件
- b[reak] <n/FunctionName>:设置断点。如 b 25 ,则在源程序的第 25 行设置一个断点,当程序执行到第 25 行时,就会产生中断;也可以使用 b funcname ,当程序调用些函数时,则产生中断
- i[nfo] b[reak]:查看断点信息
- bt(backTrace):查看函数堆栈
- c[ontinue] :让中断的程序执行直到下一个中断点或程序结束
- p[rint] <args>:输出某个变量的值,如程序定义了一个 int aa 的就是, p aa 就会输出 aa 的当前值
- n[ext] :程序执行到断点时中断执行,可以用 n 指令进行单步执行下一条语句,但是不进入函数
- s[tep] :程序执行到断点时中断执行,可以用 s 指令进行单步执行下一条语句,并进入函数
- finish:一直执行到正在运行的函数执行完毕
- attach <PID>:使用该命令调试正在运行的程序之前,先用file命令读取程序的符号表,然后再attach正在运行的程序。调试完毕后detach,解除gdb和程序的链接,程序继续执行
- info program: 显示有关你的程序的状态信息,你的程序是在运行还是停止,是什么进程,为什么停止,等等;
- info stack/frame: 显示栈/帧的摘要信息
- f[rame] <STACK_FRAME_NO/ADDRESS>: 选择一个栈帧,并进入这个栈帧,同时打印被选择的栈帧的内容摘要信息;该命令的参数是一个栈帧的号码或者是一个栈帧地址
- q[uit] :退出 GDB
- help <Command>: 显示命令Command的详细用法
- break 类名::函数名
- break +OFFSET 或 break -OFFSET:程序运行到当前行时的前几行或后几行; OFFSET表示行号
- break FILENAME:LINENUM:在文件名为FILENAME的源文件中的第LINENUM行上设置断点
- break FILENAME:FUNCTION:在文件名为FILENAME的源文件中的名为FUNCTION的函数上设置断点
- break *ADDRESS:在地址ADDRESS上设置断点.这个命令允许你在没有调试信息的程序中设置断点
- break:不含任何参数的break命令,会在当前执行到的程序运行栈中的下一条指令上设置一个断点.除了栈底以外,这个命令使程序在一旦从当前函数返回时停止
- break [LOCATION] if CONDITION:设置一个条件断点,条件由CONDITION来决定.如果CONDITION条件为非0(条件成立时),程序就在LOCATION处停止。LOCATION 可能是line number, function name, 或者"*" 和an address。With no LOCATION, uses current execution address of the selected stack frame. This is useful for breaking on return to a stack frame.
- clear:不带任何参数的clear命令会在当前所选择的栈上清除下一个所要执行到的断点(指令级).当你当前的栈帧是栈中最内层的时候,使用这个命令可以很方便地删除刚才程序停止处的断点;
- clear FUNCTION 和 clear FILENAME:FUNCTION:删除名为FUNCTION的函数上的断点;
- clear LINENUM 和 clear FILENAME:LINENUM:删除第LINENUM行上的断点;
- delete [breakpoints] [BNUMS...]:删除参数所指定的断点,如果没有指定参数,则删除程序中所有的断点.这个命令可以缩写成d;
- pwd: 查看gdb当前的工作路径
- cd : 改变gdb当前的工作路径
- info terminal:显示gdb当前所使用的终端的类型信息
- show paths: 显示当前路径变量的设置情况
- show environment/env [VARNAME]:显示程序的环境变量VARNAME的值;如果不指明环境变量名,那么该命令将显示所有环境变量的值
- set environment/env VARNAME [=] VALUE:设置程序的某个环境变量VARNAME的值;不过,只对你所调试的程序有效,对gdb本身不起作用
- unset environment/env VARNAME:删除程序的某个环境变量VARNAME;
- watch EXPR:watch命令使用EXPR作为表达式设置一个观察点.gdb将把表达式加入到程序中,并监视程序的运行,当表达式的值被改变的时候,gdb将会停止程序;
- rwatch EXPR:使用EXPR作为表达式设置一个观察点,当EXPR被程序读取时,程序被gdb暂停;
- awatch EXPR:使用EXPR作为表达式设置一个观察点,当EXPR被读出然后被写入时,gdb会暂停程序;这个命令常和rwatch合用;
- info watchpoints:显示所有设置的观察点的列表
对多线程程序的调试:
A、thread <THREAD_NO>: 该命令用于在线程之间进行切换,把线程号为THREAD_NO(gdb设置的线程号)的线程设置为当前线程
B、info threads: gdb按照顺序显示当前进程所拥有的所有线程的状态摘要信息
- 线程号: gdb为被调试进程中的线程设置的顺序号
- 目标系统的线程标识
- 此线程的当前栈信息
C、thread apply [THREAD_NO] [ALL] ARGS: 该命令用于向线程提供命令
另外,无论gdb何时中断了你的程序(因为一个断点或者是一个信号),gdb会自动选择信号或断点发生的线程作为当前线程
gdb选项:
- -s(symbol) file 读出文件(file)中的符号表
- -write 开通(enable)往可执行文件和核心文件写的权限
- -se File 从File读取符号表并把它作为可执行文件,与第一个参数等价
- -d Directory 把Dicrctory加入源文件搜索的路径中
- -tty=Device 使用Device作为你程序运行的标准输入输出
关于core dump(核心转储):
这里的core不是核心,而是内存。在开发程序时,最怕的就是程序莫明其妙地挂掉。于是,操作系统就会把程序挂掉时的 内存内容写入一个叫做core的文件里(这个写入的动作就叫core dump),我们可以根据core文件分析程序出错的原因,以便于我们调试。
1. 在嵌入式系统中,有时core dump直接从串口打印出来,结合objdump查找ra和epa地址,运用栈回溯,可以找到程序出错的地方。
2. 在一般Linux系统中,默认是不会产生core dump文件的,通过ulimit -c来查看core dump文件的大小,一般开始是0。可以设置core文件大小,例如:
ulimit -c 1024(kbytes单位)或者ulimit -c unlimited
3. core dump文件输出设置,一般默认是当前目录,并且文件名固定为core,如果程序产生多次崩溃,就会覆盖掉前一个core文件。可以通过
echo "/root/corefile/core-%e-%p-%t" > /proc/sys/kernel/core-pattern 控制core文件保存位置和文件名格式
查看core dump文件路径的命令:
cat /proc/sys/kernel/core-pattern
core-pattern中使用的参数列表:
- %p - insert pid into filename 添加pid
- %u - insert current uid into filename 添加当前uid
- %g - insert current gid into filename 添加当前gid
- %s - insert signal that caused the coredump into the filename 添加导致产生core的信号
- %t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
- %h - insert hostname where the coredump happened into filename 添加主机名
- %e - insert coredumping executable name into filename 添加命令名
需要说明的是,在内核中还有一个和core dump相关的文件,/proc/sys/kernel/core-user-pid,如果执行以下命令即使core-pattern中没有设置%p,也会在生成的core文件中添加上pid。
echo "1"
> /proc/sys/kernel/core-user-pid
4. 发生core dump之后, 用gdb进行查看core文件的内容, 以定位文件中引发core dump的行。
gdb [exec file] [core file]