嵌入式中自己编译gdb和gdbserver工具

发 布 时 间 : 2008-11-17 来 源 : 21icbbs 作 者 : db10 浏 览 :
目 录
一.序论    2
二.开发环境说明    2
三.编译gdb和gdbserver工具    2
四.Gdbserver操作使用    5


一.序论
就目前而言,嵌入式Linux系统中,主要有三种远程调试方法,分别适用于不同场合的调试工作:
用ROMMonitor调试目标机程序、
用KGDB调试系统内核
用gdbserver调试用户空间程序。

  这三种调试方法的区别主要在于,目标机远程调试stub的存在形式的不同,而其设计思路和实现方法则是大致相同的。
而我们最常用的是调试应用程序。就是采用gdb+gdbserver的方式进行调试。在很多情况下,用户需要对一个应用程序进行反复调试,特别是复杂的程序。采用GDB方法调试,由于嵌入式系统资源有限性,一般不能直接在目标系统上进行调试,通常采用gdb+gdbserver的方式进行调试。Gdbserver在目标系统中运行,gdb则在宿主机上运行。

目标系统必须包括gdbserver程序,宿主机也必须安装gdb程序。一般linux发行版中都有南京背景板搭建可以运行的gdb,但开发人员不能直接使用该发行版中的gdb来做远程调试,而要获取gdb的源代码包,针对arm平台作一个简单配置
二.开发环境说明
嵌入式中自己编译gdb和gdbserver工具,由自己亲自编译通过并可以正确运行使用。所在环境是pc运行在red 9.0.硬件板子:at91rm9200,跑嵌入式linux-2.4.27.gcc为3.3.2,gdb和gdbservr源代码选用gdb-5.2.1(先后试过gdb6.0, gdb6.4, gdb6.6三个版本,这三个没有成功,具体以后有时间再研究),可以到ftp://ftp.gnu.org/gnu/gdb下载。.

三.编译gdb和gdbserver工具
   可以在根据下面一步一步做,也可以象我一样,做一个shell脚本文件,这样可以提高效率(可以在windows上先做好这个脚本,南京桁架搭建制作好后拷贝到pc的linux下,可能不能执行,要用:先执行dos2unix 脚本名 将dos格式转化成linux认识的文件,然后再执行chmod 777 脚本名。这样就可以直接执行这个脚本了)。
操作具体情况请看脚本里的注释,编译中,源代码中好像没有出现语法错误提示,如果有的话,也就是添加或取消包含.H文件。
#!/bin/sh
#编译gdb
#download from http://cygwin.mirrors.pair.com/gdb/old-releases/
# tar jxf gdb-5.2.1.tar.bz2
#文件的很多目录也许你还没有建立,跟我的电脑上不一致,则要自己建立起目录。
cd /usr/src/arm/gdb/gdb-5.2.1
mkdir ../build-gdb
cd  ../build-gdb
../gdb-5.2.1/configure --target=arm-linux --enable-shared --prefix=/usr/src/arm/gdb/build-gdb --without-x --disable-gdbtk --disable-tui --without-included-regex --without-included-gettext
#具体说明请看相关附录
make
make install

#编译gdbserver gdb5.2.1版本
mkdir ../build-gdbserver
cd ../build-gdbserver
chmod +x ../gdb-5.2.1/gdb/gdbserver/configure
CC=/usr/local/arm/3.3.2/bin/arm-linux-gcc ../gdb-5.2.1/gdb/gdbserver/configure arm-linux --without-included-regex --without-included-gettext
#具体说明请看相关附录
make
cp -vf gdbreplay gdbserver  /nfsshare/gdb


具体说明附录:对应脚本里的两行编译配置:../gdb-5.2.1/configure --target=arm-linux --enable-shared --prefix=/usr/src/arm/gdb/build-gdb --without-x --disable-gdbtk --disable-tui --without-included-regex --without-included-gettext
还有:
CC=/usr/local/arm/3.3.2/bin/arm-linux-gcc ../gdb-5.2.1/gdb/gdbserver/configure arm-linux --without-included-regex --without-included-gettext
上面两个配置,在我电脑如果书写成用\隔开的几行,这样不能运行,不知道为什么。我一直还没有搞明白,不过这是小问题。
上面的配置一定要加对,否则编译有问题,或者编译好后,使用时有问题,如运行不起来,或者运行时不能设置断点,只能全速跑。

整个编译过程如果碰到这些问题:
1.编译后,在板子上运行gdbserver后出现
[root@AT91RM9200DK /usr]$gdbserver: error in loading shared libraries: libthread
_db.so.1: cannot open shared object file: No such file or directory
出现这个问题,是跟上面的两个配置有关,如只是简单的配置了如网上流行的说法target host prefix,没有其他选项了。这样生成的gdbserver是要共享库的,目标文件在使用时要求有libthread_db.so.1共享库文件,可以尝试将gcc3.3.2(我自己使用的版本)交叉编译器下的这个文件拷贝到你的板子linux 下的/lib 或 /tm/lib,或/usr/lib(具体不是很明白,我试过拷贝在/lib),但是有这个文件后,会导致这个文件要调用libc.so.6这个文件,这个文件又需要libc-2.3.2.so ,这些文件更换后,最后更多文件依赖。原因是:我的根文件下面ramdisk解开后库文件的版本低,好像全是1.3.2版本的(在家没带板子),就是说libc-2.3.2.so,ld-2.3.2.so,还很多别的库文件都是1.0版本的。其实这些库只是版本低,在原来的ramdisk里都有,但是提示找不到。你上一步我也是跟综过的。
然而我用新的如gcc 3.3.2或3.4.1里面的库换掉后换掉后,如换成libc-2.3.2.so,ld-2.3.2.so,连根文件ramdisk启动不来,也就是说要改动init部分,也就意外重新做busybox部分,那工作量更大,然而我也做了busybox,发现新做的自吸式射流曝气机做成ramdisk后,内核起不来,处在init过不去。
所以如果文件版本不一致的话,busybox和ramdisk不是自己作的话,上面这种动态编译gdbserver然后再在板子上加共享库,那是很难成功的。
  上面这个原因,我没有搞定,如果有人知道原因,请提示我。谢谢!
2.为了解决问题,看了一篇老外的文章,说可以在编译gdbserver时,改动gdbserver下面的Makefie.in或configure后的Makefile,里面的LDFLAGS改成 LDFLAGS= -static。
原始老外文章:
[bgat@mars build-gdb] cd gdb/gdbserver
[bgat@mars build-gdb] make CC=arm-linux-gcc
[bgat@mars build-gdb] file gdbserver
./gdbserver: ELF 32-bit LSB executable, ARM, version 1 (ARM), dynamically linked (uses shared libs), not stripped
You probably don't want your gdbserver to use shared libraries, unless your target environment supports them (and you want to prove that they actually work!). To save some hair, you'll probably want to build a statically-linked gdbserver instead, so that you can debug even if shared libraries are broken. To do that, edit the Makefile in gdb/gdbserver, and modify LDFLAGS:


LDFLAGS = -static
There may be other LDFLAGS flags already there, which you'll want to leave alone--- just add -static to the end of the list. In other cases, LDFLAGS may not exist at all; just add the above line somewhere near CFLAGS.

Then, rebuild gdbserver:


[bgat@mars build-gdb] make clean
[bgat@mars build-gdb] make CC=arm-linux-gcc
[bgat@mars build-gdb] file gdbserver
gdbserver: ELF 32-bit LSB executable, ARM, version 1 (ARM), statically linked, not stripped
Run arm-linux-strip on the executable, if you want to shrink it down:


[bgat@mars build-gdb] arm-linux-strip gdbserver
[bgat@mars build-gdb] ls -l gdbserver
-rwxrwxr-x    1 bgat     bgat       249164 Aug  2 11:16 gdbserver

我这样编译gdbserver后,gdbserver终于可以运行了,但是让我失望的是,gdbserver调试时程序不能设置断点,跑一次就完了。提示:
warnning
Cannot insert breakpoint 1.
  Error accessing memory address 0x8...
上面这个原因,我没有搞定,如果有人知道原因,请提示我。谢谢!
3.尝试了快1个星期后,很多版本的gdb尝试过。最后就是使用了第三条说的方法编译的,通过了,gdbserver可以跑了,可以设置断点了,现在正常。

四.Gdbserver操作使用
  有关gdb和gdbserver调试操作使用说明,资料一大把,这里讲讲要注意的地方:
1.    在target machine输入
gdbserver 59.69.74.87:2345 hello
59.69.74.87主机IP,2345任意写一个。Hello一定要用arm-linux-gcc(我的板子)交叉编译,带-g编译。
2. 在target machin出现
Process hello created; pid = 68

3. 进入潜水射流曝气机制作gdb时生成的arm -linux-gdb所在目录(也可以export),在PC机上输入
arm-linux-gdb hello (这个程序一定跟target machine程序保持一致,是交叉编译的)
(gdb) target remote 203.239.30.207:2345
出现 Remote debugging using 59.69.75.186:2345
0x40002a00 in ?? ()

(gdb) c //相当于主机gdb的run命令

此时目标机上出现
Remote debugging from host 59.69.74.87
hello,world

连接成功后,这时候就可以输入各种gdb命令如list、run、next、step、break等进行程序调试了。

调试结束.
 次文章献给热爱linux的所有人
                                 
作者:db10
  2007.12.11于深圳

上一篇:在WinCE中创建自己的快捷方式 下一篇:qtopia-core-opensource-src-4.3.3移植到ARMSYS2440