慢慢的大家的 uClinux 都可以跑起来了,也能够自己编译一个内核出来了。但是,如果自己要写驱动、或者修改内核的一些代码、或者像 nickmit 一样要自己写一个内核的移植,那么调试就是不可或缺的了。在这里我摸索了一个使用我们廉价的 Wiggler + GDB + OCDLibremote 来调试内核的方法。
关于 Wiggler 和 GDB 在这里我就不介绍了,说一下 Cygwin 和 OCDLibRemote 吧。
唉……其实 Cygwin 也没什么好说的,现在网络是那么样的发达,如果不知道那是什么东西的话,大家到他的网站看一下就知道了。网址:
http://www.cygwin.com
关于安装的话,如果你仅仅是用来调试,那么照它默认最小的来配置就可以了。如果还要自己编译一点东西的话,那么 Cliff 在这里向你推荐几个需要安装的软件包:
autoconf
automake
make
gcc
g++
gdb
msgfmt
bison
flex
gawk
sed
只要安装了这些,一般编译一些东西就没有什么问题了。
这是一个使用 Wiggler (当然还有一些其他的 JTAG,如 Raven)的调试器,支持 GDB。大家可以到他的官方网站http://www.macraigor.com/full_gnu.htm下载所需要的软件。很可惜的是,只有 Windows 下的 OCDLibRemote 才支持我们的廉价 JTAG——Wiggler。因此虽然那里有 Linux 版本的,却是不能用的(除非你有他支持的其他仿真器,如 Raven)。
安装了这个东西之后,似乎是不能直接运行的,他的驱动程序居然没有装好(我没试过重启一下是否就可以用,但是……我实在是太性急了)。因此我们需要手工安装它的驱动,使用 loaddrv 之类的,它的 sys 文件倒是已经放到了 Windows 的 System32/drivers 目录下了。
不过建议大家可以试一试重启之后能不能正常运行。
如果对这个手工安装驱动没有概念的话,没关系,我们可以在他的网站下载另一个软件:OCD Commander 。它的网址是http://www.macraigor.com/ocd_cmd.htm。只要安装了这个,它倒是要你重启的,然后就可以用我们的 OCDLibRemote 了。
这样软件安装好了之后,那么我们还需要一份 GDB。如果大家环境比较好,那么可以在 Windows 的机器上运行 OCDLibRemote,然后在 Linux 的机器上开发和调试内核。如果只有一台机器(比如我,这样的人应该还是大部分吧),那就需要编译一份 Cgywin 下面的 GDB(或者 Insight,GDB 的图形界面)。
现在的 GDB/Insight 版本是 6.1,但是在 Cygwin 下面 Insight 不能被正确编译。所以如果大家是初学者的话建议使用 Insight 6.0。
关于编译 GDB/Insight,我们首先需要下载它的源代码,这里以 GDB 6.1 为例子:
它的源代码的文件名是 gdb-6.1.tar.bz2 或者 gdb-6.1.tar.gz。下载了这个东西以后(可以在ftp://sources.redhat.com/pub下载):
tar xjvf gdb-6.1.tar.bz2 (tar xzvf gdb-6.1.tar.gz)
mkdir arm-elf-gdb
cd arm-elf-gdb
../gdb-6.1/configure --target=arm-elf
make
make install
如果嫌文件太大,可以使用 strip 命令把调试信息去掉:
strip /usr/local/bin/arm-elf-gdb.exe
开发环境配置好以后,就切入“如何调试”的正题了(我这个人……似乎废话永远比正经的话多啊……)
运行 OCDLibRemote。执行命令 OCDLibRemote -c ARM7 -d WIGGLER 就好了。
运行 arm-elf-gdb:
进入 linux 的目录,例如 uClinux-dist/linux-2.4.x
请注意,你的 Linux 内核在编译的时候需要选择加入调试信息。在配置内核的时候,是在 Kernel hacking 里面选中:
[*] Include debugging information in kernel binary
$ arm-elf-gdb linux
(gdb) target remote localhost:8888
Remote debugging using localhost:8888
0x00000000 in ?? ()
(gdb) c
Continuing.
如果你使用了我们新版本的 BIOS,那么请在执行 c 命令之后到超级终端看一下,因为需要在 10 秒钟内按键进入 BIOS。
进入 BIOS,使用 load 命令把我们的内核镜像 image.ram 下载到 RAM 中(这个我就不多说了吧)。
之后,我们需要设置断点(这才叫调试嘛)。请注意,断点必须是在 load 之后设置,因为软件断点其实是通过改写 RAM 来实现的。如果先设
置断点再 load 那就俗了——断点的特殊指令被冲掉了。
如下所示:
Auto boot in progress, press any key in 9 seconds to run BIOS...
>load
Now begin address for download, use address 0xc008000
Load image file from host
Type tftp -i 192.168.111.8 put filename at the host PC
Press ESC key to exit
Begin to receive filename: image.ram, transtype: octet.
Begin to receive filename: image.ram, transtype: octet.
TFTP transfer finished, and receive 1ab9b8 bytes.
为了设置断点,我们要暂停 BIOS,这可以通过在 GDB 窗口按 CTRL+C 来实现。然后就可以设置断点。如下:
(gdb) target remote localhost:8888
Remote debugging using localhost:8888
0x00000000 in ?? ()
(gdb) c
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
0x0c7c0774 in ?? ()
(gdb) br start_kernel
Breakpoint 1 at 0xc008588: file init/main.c, line 363.
之后继续运行,还是使用 c 命令,并且在 BIOS 使用 run 命令执行内核:
(BIOS)
>run
Run program from 0xc008000, are you aure? [y/n]y
(GDB)
(gdb) c
Continuing.
Breakpoint 1, start_kernel () at init/main.c:363
363 setup_arch(&command_line);
(gdb)
然后就是如何调试的问题了。