gdb+ gdbserver 远程调试(应用程序)
远程调试环境由宿主机(PC 机)GDB和目标机调试stub共同构成,两者通过串口或TCP连接。使用GDB标准远程串行协议协同工作,实现对目标机上的系统内核和上层应用的监控和调试功能。调试stub是嵌入式系统中的一段代码,作为宿主机GDB和目标机调试程序间的一个媒介而存在。就目前而言,嵌入式Linux系统中,主要有三种远程调试方法,分别适用于不同场合的调试工作:
用ROM Monitor调试目标机程序
用KGDB调试系统内核
用gdbserver调试用户空间程序。
这三种调试方法的区别主要在于:目标机远程调试stub的存在形式的不同,而其设计思路和实现方法则是大致相同的,而我们最常用的是调试应用程序,就是采用gdb+gdbserver的方式进行调试。在很多情况下,用户需要对一个应用程序进行反复调试,特别是复杂的程序,采用GDB方法调试,由于嵌入式系统资源有限性,一般不能直接在目标系统上进行调试,通常采gdb + gdbserver的方式进行调试。Gdbserver在目标系统中运行,gdb则在宿主机上运行。
要进行GDB调试,目标系统必须包括gdbserver程序,宿主机也必须安装gdb程序,一般linux发行版中都有一个可以运行的gdb,但开发人员不能直接使用该发行版中的gdb来做远程调试,而要获取gdb的源代码包,针对arm平台作一个简单配置,重新编译得到相应gdb。gdb的源代码包可以从http://ftp.cs.pu.edu.tw/Linux/sourceware/gdb/releases/下载,最新版本为gdb-7.5.1,
一.编译安装arm-linux-gdb
<1>#tarjxvf gdb-6.4.tar.bz2
<2>#cdgdb-6.4
<3>#./configure--target=arm-linux--enable-sim --prefix=/usr/local/arm/arm-gdb
<4>#make
<5>#makeinstall
二.编译安装gdbserver
<1>#cdgdb-6.4/gdb/gdbserver
<2>#./configure--target=arm-linux--host=arm-linux
<3>#make
这样在gdb-6.4/gdb/gdbserver目录下就生成了一个gdbserver可执行文件,拷贝到目标开发板上(/bin).
三.使用putty终端telnet 到目标板测试目标板与宿主机(PC 虚拟机)是否能相互 ping 得通。说一下我遇到的一些情况:
宿主机无法与目标板 ping 通。
1):请检查宿主机的IP是否与目标板子在同一局域网。
2):排查虚拟机与主机(XP WIN7 ……)是怎样连接网咯,虚拟机与主机是否能通。
3):让Vmware 网咯恢复默认值,路劲:Vmware->编辑->虚拟网咯编辑器->(这里用哪个就让哪个恢复默认值,我用的是桥接模式)桥接模式。
三.测试arm-linux-gdb +gdbserver
<1>在超级终端输入:
#./gdbserver 192.168.1.20:2345 hello
[192.168.1.20为pc机ip地址,2345为监听端口,hello为待调试程序
(这里连接不是那么顺畅,首先检查 servicenfs status 与 serviceportmap status服务是否启动, 注意 nfs 服务里面与目录权限设置。最后防火墙(serviceiptables stop)服务一定要关掉,否则看不到下面的信息)
这样在开发板上可以看到如下提示信息:
Process wpa_cli created; pid = 730
Listening onport 2345
表示gdbserver 成功运行等待客户端的连接信息
<2>在pc机上输入:
#arm-linux-gdbhello
然后在GDB界面输入:
#targetremote 192.168.1.230:2345
[192.168.1.230为开发板ip地址,2345为开发版监听端口]
这样在开发板上可以看到如下提示信息:
Remote debugging from host 192.168.1.20
表示gdbserver成功运行并且建立连接关系,等待客户端的调试信息
Gdb 基本调试命令:
GDB调试命令 | |
命令 | 描述 |
backtrace(或bt) | 查看各级函数调用及参数 |
finish | 连续运行到当前函数返回为止,然后停下来等待命令 |
frame(或f)帧编号 | 选择栈帧 |
info(或i) locals | 查看当前栈帧局部变量的值 |
list(或l) | 列出源代码,接着上次的位置往下列,每次列10行 |
list 行号 | 列出从第几行开始的10行源代码 |
list 函数名 | 列出某个函数的源代码 |
next(或n) | 执行下一行语句 |
print(或p) | 打印表达式的值,通过表达式可以修改变量的值或者调用函数 |
quit(或q) | 退出gdb调试环境 |
set var | 修改变量的值 |
start | 开始执行程序,停在main函数第一行语句前面等待命令 |
step(或s) | 执行下一行语句,如果有函数调用则进入到函数中 |
break(或b)行号 | 在某一行设置断点 |
break 函数名 | 在某个函数开头设置断点 |
break … if … | 设置条件断点 |
continue(或c) | 从当前位置开始连续运行程序 |
delete breakpoints 断点号 | 删除断点 |
display 变量名 | 跟踪查看某个变量,每次停下来都显示它的值 |
disable breakpoints 断点号 | 禁用断点 |
enable 断点号 | 启用断点 |
info(或i) breakpoints | 查看当前设置了哪些断点 |
run(或r) | 从头开始连续运行程序 |
undisplay 跟踪显示号 | 取消跟踪显示 |
watch | 设置观察点 |
info(或i) watchpoints | 查看当前设置了哪些观察点 |
x | 从某个位置开始打印存储单元的内容,全部当成字节来看,而不区分哪个字节属于哪个变量 |
==================================================================