您的位置:首页 > 运维架构 > Linux

linux下用gdb调试程序

2013-11-09 17:12 281 查看
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]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: