远程调试环境由宿主机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-6.4。
一、编译安装gdb+gdbserver
下载到某个目 录,我下载到自己的用户目录:/home/may。
下载完后,进入/home/may目录,配置编译步骤如下:
|
在这一步中出现问题:make CC=/usr/local/arm/2.95.3/bin/arm-linux-gcc
问题:
root@may:~/gdb-6.4/gdb/gdbserver# make CC=/usr/local/arm/2.95.3/bin/arm-linux-gcc /usr/local/arm/2.95.3/bin/arm-linux-gcc -c -Wall -g -O2 -I. -I. -I./../regformats -I./http://www.cnblogs.com/include -Ihttp://www.cnblogs.com/bfd -I./http://www.cnblogs.com/bfd remote-utils.c remote-utils.c: In function `prepare_resume_reply': remote-utils.c:686: parse error before `unsigned' remote-utils.c:697: `gdb_id_from_wait' undeclared (first use in this function) remote-utils.c:697: (Each undeclared identifier is reported only once remote-utils.c:697: for each function it appears in.) remote-utils.c:707: parse error before `void' remote-utils.c:712: `mem_addr_ptr' undeclared (first use in this function) remote-utils.c:712: `len_ptr' undeclared (first use in this function) remote-utils.c:714: `ch' undeclared (first use in this function) remote-utils.c:714: `from' undeclared (first use in this function) remote-utils.c:714: `i' undeclared (first use in this function) remote-utils.c:720: `j' undeclared (first use in this function)
make: *** [remote-utils.o] Error 1
解决方法:在remote-utils.c文件中,直接将有unsigned的那行和前面的一行对换位置就行了!估计是C语言语法的问题!
这样做之后,再执行上述命令,就没有错误了。运行完上述命令,就会在gdbserver目录下生成gdbserver可执行文件,把它烧写到flash的根文件系统分区,或通过nfs mount的方式复制到你的开发板上就可以了。只要保证gdbserver能在开发板上运行就行。我是使用nfs mount的方式,在开发板上挂载宿主机的目录,并将生成的可执行文件gdbserver拷贝到宿主机上的共享目录中,以使其在目标板上可见。如:
mount -o nolock -t nfs 192.168.0.167:/mnt/nfs /mnt
192.168.0.167是宿主机的IP。当然,在使用这种方式时要启动nfs服务。
二、调试步骤
接下面就可以用gdb+gdbserver调试我们开发板上的程序了。在目标板上运行 gdbserver,其实就是在宿主机的minicom下。从上一步mount目录的过程中看出,我将应用程序(hello.c)和gdbserver都拷贝到宿主机的/mnt/nfs目录下了,从而在目标板的/mnt目录可以看到他们(当然你可以将他们再拷到目标板的其他位置),并对其进行操作。
要进行gdb调试,首先要在目标系统上启动gdbserver服务。在gdbserver所在目录下输入命令:
|
192.168.0.167为宿主机IP,在目标系统的2345端口开启了一个调试进程,hello为要调试的程序(主义编译时要加上-g选项)。
在这一步出现问题,./gdbserver: error while loading shared libraries: cannot open shared object...
板子的lib库中缺少一个文件libthread_db.so.1。根据网上查到的解决办法:将宿主机上的交叉编译工具中的lib库中的copy一个过来。于是乎我将/usr/local/arm/2.95.3/arm-linux/lib/libthread_db.so.1文件拷贝到目标板的/lib中后错误消失,并出现提示:
|
出现提示:
|
连接成功,这时候就可以输入各种GDB命令如list、run、next、step、break等进行程序调试了。
仍然存在的问题:
在远程调试一个程序时, pc端输入回馈如下:
(gdb) list
No symbol table is loaded. Use the "file" command.
(gdb) step
Cannot find bounds of current function
(gdb) info program
Debugging a target over a serial line.
Program stopped at 0x14000.
It stopped with signal SIGTRAP, Trace/breakpoint trap.
(gdb) info thread
1 thread 769 0x00014000 in ?? ()
warning: GDB can't find the start of the function at 0x14000.
(gdb) info stack
#0 0x00014000 in ?? ()
输入continue可以跑,
输入break的情况和下list是一样的.
也就是说,还是还不能正常对arm板上的应用程序进行调试。(但是在第二天,再次用带-g选项的交叉编译器编译了源程序后,可以成功进行远程调试了;不知道到底是为什么,嵌入式里面的很多东西我还不懂,但是在做的过程中,可真是痛苦阿!)
参考文档:http://blog.chinaunix.net/u/22630/showart_298299.html
http://www.minigui.org/cgi-bin/lb5000/topic.cgi?forum=6&topic=6279
http://szricky.blog.hexun.com/8886993_d.html
http://xianzilu.spaces.live.com/blog/cns!4201FDC93932DDAF!268.entry