http://xianzilu.spaces.live.com/blog/cns!4201FDC93932DDAF!268.entry
使用DDD+GDB开发ARM Linux程序
今天又取得了一些进展,赶快写下来以免自己忘记。
自从Linux在我的板子上跑起来之后,我一直在想一个问题,怎么调试将来写的程序。其实我在Linux开发方面真得很外行,到了今天才知道 GDB到底是干什么用的,呵呵。我相信很多人从Bootloader调试开始一直都使用LED啊,printf这样的方法来调试。我做毕设时,就是在 MTDBLOCK里面划出一个USER分区,然后把编译好的程序放入文件系统映像,通过Bootloader用串口下到NAND里,然后mount上调 试,实在很花时间。今天,白痴的我终于找到了一条捷径,已经不咳嗽了!
先介绍下DDD和GDB,GDB是一种用于调试Linux下程序的工具,它不仅能调试C/C++,还可以调试Pascal等很多其他语言。我们 看个例子:假设有一个程序叫做test.c,要用GDB调试它,首先,编译的时候需要加上产生debug信息选项“-g”,如#arm-linux- gcc test.c -o test -g;然后,由于我们并不是开发本机程序,在目标机(arm)上需要用一个server启动这个含有调试信息的程序,当然,本机和目标机之间得有一定的数 据共享方式(如nfs)和一定的通信方式(如以太网或串口);最后,在本机上启动一个GDB客户端,就可以登陆到目标机的server上调试程序了。 GDB的原理网上也有很多文章说,可以搜索下,但是我是初学者,就不去看那些内容了。为了让大家更加明确GDB和DDD的区别,我们先看一个GDB的调试 过程:
我通过以太网调试,本机IP地址192.168.2.31,目标机(arm开发板IP地址192.168.2.223),本机通过nfs共享开发目录lgraphics。
首先本机上编译:
lxz@lxzlinux:~/lgraphics> arm-linux-gcc lgraphics.c -o lg -g
切换到目标机:
[root@(none) lgraphics]# gdbserver 192.168.2.31:2345 lg
Process lg created; pid = 402
Listening on port 2345
Process lg created; pid = 402
Listening on port 2345
切换到本机:
lxz@lxzlinux:~/lgraphics> arm-linux-gdb lg
GNU gdb 6.6
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-linux"...
(gdb) target remote 192.168.2.223:2345 lg
Remote debugging using 192.168.2.223:2345 lg
0x40001290 in _start () from /lib/ld-linux.so.2
lxz@lxzlinux:~/lgraphics> arm-linux-gdb lg
GNU gdb 6.6
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-linux"...
(gdb) target remote 192.168.2.223:2345 lg
Remote debugging using 192.168.2.223:2345 lg
0x40001290 in _start () from /lib/ld-linux.so.2
此时,目标机上也会出现:
Remote debugging from host 192.168.2.31
在本机上输入:
(gdb) b main (设置断点到main函数)
Breakpoint 1 at 0x9c00: file lgraphics.c, line 442.
(gdb) cont (开始执行)
Continuing.
Breakpoint 1 at 0x9c00: file lgraphics.c, line 442.
(gdb) cont (开始执行)
Continuing.
Breakpoint 1, main () at lgraphics.c:442 (遇到断点,并显示断点程序行)
442 int i, j, b = 0;
(gdb) step (单步执行)
445 linitgraph("/dev/fb0"); (显示目前程序行)
442 int i, j, b = 0;
(gdb) step (单步执行)
445 linitgraph("/dev/fb0"); (显示目前程序行)
好了,看到这里,差不多就明白GDB是干什么的、怎么用了吧。我相信你会和我一样对GDB界面的不友好表示愤慨,想想Windows下的开发工 具,哪一种调试的时候还是文本界面的。幸运的是,有一些勤快的人,帮我们写了很多GDB的图形化前端,我们更本不用像上面这样使用GDB。
开始说DDD。DDD是一种GDB的图形化前端,就是一种用图形界面帮你输入繁琐的GDB调试指令工具。当然,也有很多文章说DDD多么不足,用Insight来取代它之类的。我的Suse里恰好就有DDD,我也不管那么多了,先用了。看看用DDD的时候怎么调试:
一样本机上编译:
lxz@lxzlinux:~/lgraphics> arm-linux-gcc lgraphics.c -o lg -g
切换到目标机:
[root@(none) lgraphics]# gdbserver 192.168.2.31:2345 lg
Process lg created; pid = 402
Listening on port 2345
Process lg created; pid = 402
Listening on port 2345
切换到本机:
lxz@lxzlinux:~/lgraphics> ddd -debugger arm-linux-gdb lg
lxz@lxzlinux:~/lgraphics> ddd -debugger arm-linux-gdb lg
然后就会启动DDD的图形界面,在窗口下方有一个文本输入框,这里就是ddd的基础gdb的所在,在这里输入target remote 192.168.2.223:2345 lg,提示信息和我们用GDB时候是一样的。不同的是,除了这句连接目标机的指令,其他指令都不用输入了,可以在图形化界面里找到,这我就不说了。另外, 连接目标机的指令也可以用在DDD中设置,不用输入,可以查找其他介绍DDD使用的文章。下面是DDD的图形界面,工具栏下面的是watch,代码可以设 置断点(红色点),可以看到单步位置(绿色箭头),右边是执行控制工具条,最下面是GDB的输入和输出显示。
看到这里,想我一样的菜鸟们一定发现了,原来Linux程序可以这么好调啊,简直和CE没有什么差别了,呵呵。下面介绍为了使用GDB+DDD 所要做的东西。我不是从零开始建立的,具体的包依存关系我也不明白,只好假设你在安装Linux的时候已经安装了像GCC,DDD之类的工具。GDB的源 代码包gdb-6.6.tar.bz2可以从
ftp://gcc.gnu.org上下载到,还有一个要求是你已经安装了交叉编译器arm-linux-gcc。
下载下来后:
# tar xvjf gdb-6.6.tar.bz2
# mkdir gdbbuild
# cd gdbbuild
# ../gdb-6.6/configure --target=arm-linux --prefix=/home/lxz/lxzgdb
这里,--prefix参数是需要安装的目录,然后
# make
# make install
这样,arm-linux-gdb这个工具就在/home/lxz/lxzgdb/bin里头了,你可以把这个路径添加到PATH里面去
接下来建立gdbserver,在gdbbuild的上一级目录下
# mkdir gdbserverbuild
# cd gdbserverbuild
# CC=arm-linux-gcc ../gdb-6.6/gdb/gdbserver/configure --host=arm-linux --prefix=/home/lxz/lxzgdbserver
一样,--prefix参数是需要安装的目录,然后
# make
# make install
有的文章里说,要去除arm-linux-strip的调试信息
# cd /home/lxz/lxzgdbserver/bin
# arm-linux-strip gdbserver
把这个gdbserver复制到你的开发板上,就OK了。
今天就写到这里。