|
一个 gdbserver 搞来搞去也花了不少时间。之前测试不成功,主要原因还是选择 gdbserver 的版本以及相关的工具链不对。老的工具链如果编译新版本的 gdbserver 则可能会出错。我的板子的是以前华恒的 S3C2410 HHARM-STUDY 。这个板子已经自带有编译好的工具链,是基于 5.2.1 版本的,所以 gdbserver 也要用这个。这些老版本的软件包可以在:
http://cygwin.mirrors.pair.com/gdb/old-releases/
下载得到。
如果还没有 gdb 的,可以用如下命令编译:configure --target=armv4l-unknown-linux --enable-shared --prefix=/opt/host/ --without-x --disable-gdbtk --disable-tui --without-included-regex --without-included-gettext
$ make
$ make install
这样,工具链会被安装到 --prefix 指定的 /opt/host 文件夹下,这个安装路径可以自定义。
现在编译 gdbserver ,先 cd 到 gdb-5.2.1/gdb/gdbserver 目录下,然后:./configure --host=arm-linux --target=arm-linux
make CC=/opt/host/armv4l/bin/armv4l-unknown-linux-gcc 上面,CC 指定用的是基于 ARM 的 GCC 编译器。因为这个 gdbserver 是要上传到开发板上去运行的,所以不能使用主机上的基于 X86 的编译器。
这样,gdbserver 就编译出来了。现在要把 gdbserver 上传到开发板上。上传可以通过 NFS, FTP, TFTP, HTTP 。我一开始用 NFS 上传不成功,不知道是什么原因,而用 NFS 传其它的文件却可以,暂时不去追究。幸好在开发板里的 /bin 目录下有个 wget ,所以采用 http 的方式下载过来。HTTP 服务,需要在主机上安装 apache 相关组件,在 ubuntu 里,服务器的主默认主目录是 /var/www ,如果是在 openSUSE ,那这个主目录就是 /srv/www/htdocs ,这依据发行版的不同而不同。我现在用 ubuntu 9.10 ,下载 gdbserver 到开发板的 /bin 目录下(这个命令的执行在开发板端):/bin # wget http://192.168.2.88/gdbserver
Connecting to 192.168.2.88[192.168.2.88]:80
gdbserver 100% |*****************************| 104 KB 00:00 ETA
再把要调试的一个 test.exe 的文件(这个文件也要用基于 ARM 的 GCC 来编译)也下载到 bin 目录下:/bin # wget http://192.168.2.88/test.exe
Connecting to 192.168.2.88[192.168.2.88]:80
test.exe 100% |*****************************| 16521 00:00 ETA
为了方便调试,在主机一端,把 test.exe 拷贝到 /opt/host/armv4l/bin/ 目录下。
接下来调试,在板子上执行命令:/bin # ./gdbserver 192.168.2.222:2345 test.exe 上面的命令,192.168.2.222 是目标板的 IP 地址,2345 是监听的端口,test.exe 是要调试的程序,执行上面的命令后,会出现:/bin # ./gdbserver 192.168.2.222:2345 test.exe
Process test.exe created; pid = 66 说明 gdbserver 运行正常,它正在等待着主机上发送过来的调试信息。
现在在主机上启动调试程序:beyes@beyes-groad:/opt/host/armv4l/bin$ ./armv4l-unknown-linux-gdb test.exe
GNU gdb 5.2.1
Copyright 2002 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=armv4l-unknown-linux"...
上面信息的出现,说明 gdb 启动成功。接下来,在 gdb 里执行以下命令:
(gdb) target remote 192.168.2.222:2345
Remote debugging using 192.168.2.222:2345
0x40002a00 in ?? () 执行了上面的蓝色部分的命令后,出现 0x40002a00 in ?? () 说明正常的调试可以开始了:(gdb) l /*列出源代码*/
1 #include <stdio.h>
2 #include <string.h>
3
4 main()
5 {
6 int i;
7 int j = 0;
8 char str[20];
9
10 for (i = 0; i < 3; i++) {
(gdb) l
11 j += i;
12 }
13
14 strcpy (str, "hello world");
15
16 printf ("%s\n", str);
17
18 return (0);
19 }
(gdb) b 6 /*在第 6 行下断*/
Breakpoint 1 at 0x83f8: file test.c, line 6.
(gdb) c /*运行,注意 x86 上的 GDB 的运行命令是 g*/
Continuing.
Breakpoint 1, main () at test.c:7
7 int j = 0;
/*在 GDB 里反汇编查看代码 。
disas 反汇编一段指令。可以带零个、一个或两个参数。第一个参数是反汇编开始地址,第二个参数是反汇编结束地址。如果没有参数,则反汇编当前的函数。*/
(gdb) disas
Dump of assembler code for function main:
0x83e8 <main>: mov r12, sp
0x83ec <main+4>: stmdb sp!, {r11, r12, lr, pc}
0x83f0 <main+8>: sub r11, r12, #4 ; 0x4
0x83f4 <main+12>: sub sp, sp, #28 ; 0x1c
0x83f8 <main+16>: mov r3, #0 ; 0x0
0x83fc <main+20>: str r3, [r11, -#20]
0x8400 <main+24>: mov r3, #0 ; 0x0
0x8404 <main+28>: str r3, [r11, -#16]
0x8408 <main+32>: ldr r3, [r11, -#16]
0x840c <main+36>: cmp r3, #2 ; 0x2
0x8410 <main+40>: ble 0x8418 <main+48>
0x8414 <main+44>: b 0x8438 <main+80>
0x8418 <main+48>: ldr r2, [r11, -#20]
0x841c <main+52>: ldr r3, [r11, -#16]
0x8420 <main+56>: add r3, r2, r3
0x8424 <main+60>: str r3, [r11, -#20]
0x8428 <main+64>: ldr r3, [r11, -#16]
0x842c <main+68>: add r3, r3, #1 ; 0x1
0x8430 <main+72>: str r3, [r11, -#16]
0x8434 <main+76>: b 0x8408 <main+32>
0x8438 <main+80>: sub r3, r11, #40 ; 0x28
0x843c <main+84>: mov r0, r3
---Type <return> to continue, or q <return> to quit---
0x8440 <main+88>: ldr r1, [pc, #28] ; 0x8464 <main+124>
0x8444 <main+92>: bl 0x82d4 <strcpy>
0x8448 <main+96>: sub r3, r11, #40 ; 0x28
0x844c <main+100>: ldr r0, [pc, #20] ; 0x8468 <main+128>
0x8450 <main+104>: mov r1, r3
0x8454 <main+108>: bl 0x82c4 <printf>
0x8458 <main+112>: mov r3, #0 ; 0x0
0x845c <main+116>: mov r0, r3
0x8460 <main+120>: ldmdb r11, {r11, sp, pc}
0x8464 <main+124>: streqh r8, [r0], -r12
0x8468 <main+128>: andeq r8, r0, r8, asr #9
End of assembler dump.
gdbserver 调试环境搭建完毕。
小结:
要成功编译 gdbserver 要选择合适版本的工具链以及 gdbserver ,不能一味求新。比如我之前用 6.1 版本的 gdbserver ,虽然编译成功,但无法在开办版上用,因为开发板上的库是 libc-2.2.2.so ,而 6.1 版本需要的库是 libc-2.2.5.so 。
在编译 gdbserver 的过程中,可能会出现提示缺少 sys/reg.h 文件的错误提示,那么可以屏蔽掉当前目录下的 config.h 文件种的以下一句:/* Define if you have the <sys/reg.h> header file. */
//#define HAVE_SYS_REG_H 1
需要注意的是,主机上调试的 test.exe 文件和远程监控的 test.exe 是两个一样的文件,而不是共享的一个文件。调试的大概原理是,把主机上的调试信息发送到目标机上,目标机产生相应的动作,然后再把这个动作反馈给主机,于是主机接着调试。 |
|