OpenWRT开发之——远程debug

jopen 9年前

想要用gdb对OpenWrt进行远程调试。首先得在OpenWrt目标机上安装gdbserver。

其实在trunk路径下也有gdb的ipk安装包的,不信find一下。

[trunk]$ find bin/ -name "gdb*.ipk"  bin/ar71xx/packages/base/gdb_7.8-1_ar71xx.ipk  bin/ar71xx/packages/base/gdbserver_7.8-1_ar71xx.ipk

查看一下它们的大小:

[trunk]$ ls -lh bin/ar71xx/packages/base/gdb*.ipk  -rw-r--r--. 1 hevake_lcj hevake_lcj 1.5M May  3 02:31 bin/ar71xx/packages/base/gdb_7.8-1_ar71xx.ipk  -rw-r--r--. 1 hevake_lcj hevake_lcj  96K May  3 02:31 bin/ar71xx/packages/base/gdbserver_7.8-1_ar71xx.ipk

OMG,gdb这个包有1.5M!对于FLASH总共才只有8M的路由器,实在有点吃紧!

还好,gdbserver只有96K。我们可以将gdbserver安装在目标机上,将其用网络或串口与开发机上的gdb进行协同使用。



1. 安装gdbserver

gdbserver 可以用 ipk 包进行安装。

在OpenWrt的trunk目录下,运行 make menuconfig,进行系统进行裁剪。

OpenWRT开发之——远程debug

gdbserver在 Development 目录下。

OpenWRT开发之——远程debug

将gdbserver选为M,保存退出。

可以打开 .config 进行查看:

OpenWRT开发之——远程debug

可以看到 CONFIG_PACKAGE_gdbserver=m。

好了,再 make V=s 。

编译完成之后,生成 bin/ar71xx/packages/base/gdbserver_7.8-1_ar71xx.ipk 包文件。

将这个文件用 scp 传送到目标机上,进行安装。

root@OpenWrt:~# opkg install gdbserver_7.8-1_ar71xx.ipk   Installing gdbserver (7.8-1) to root...  Collected errors:   * satisfy_dependencies_for: Cannot satisfy the following dependencies for gdbserver:   *     libthread-db *    * opkg_install_cmd: Cannot install package gdbserver.

依赖 libthread-db 库。那就先安装 libthread 。安装包是:

trunk/bin/ar71xx/packages/base/libthread-db_0.9.33.2-1_ar71xx.ipk

将其传到目标机上并安装。

然后再安装 gdb-server:

root@OpenWrt:~# opkg install gdbserver_7.8-1_ar71xx.ipk   Installing gdbserver (7.8-1) to root...  Configuring gdbserver.

好了!安装好了,那就用用看吧。


2. 试用gdbserver

远程调试需要目标机启动 gdbserver并执行调试目标程序。在调试的过程中,gdbserver开启一个TCP服务,由开发机上的gdb连接。之后 gdbserver接收gdb的指令并将指令操作结果反馈给gdb,从而达到了远程调试的目的。


开发机(CentOS)IP:192.168.1.10

目标机(OpenWrt)IP:192.168.1.2


2.1 首次尝试

在目标机上启动gdbserver

root@OpenWrt:~# gdbserver 127.0.0.1:3000 debug-demo  Process cpp11-demo created; pid = 3335  Listening on port 3000

如上,命令格式为:gdbserver <local IP>:<port> <program> [args list]

<local IP>就写成127.0.0.1,<port>指定为3000,要调试的是debug-demo程序。

如下为程序源码:

src/main.c

#include <stdio.h>    int nGlobalVar = 0;    int tempFunction(int a, int b)  {      printf("tempFunction is called, a = %d, b = %d \n", a, b);      return (a + b);  }    int main()  {      int n;      n = 1;      n++;      n--;        nGlobalVar += 100;      nGlobalVar -= 12;        printf("n = %d, nGlobalVar = %d \n", n, nGlobalVar);        n = tempFunction(1, 2);      printf("n = %d\n", n);        return 0;  }

src/Makefile:

target:=debug-demo  CFLAGS+=-g    objects:=$(subst .c,.o,$(wildcard *.c))    $(target) : $(objects)      $(CC) $(CFLAGS) -o $@ $^    .PHONY:clean  clean:      $(RM) $(objects)

值得注意的是:在 src/Makefile中,添加一行:

CFLAGS+=-g

使之在make的时候能够将调试信息加进去。

将这个程序打包安装到OpenWrt上去。至于怎么打包与安装,博主已上前面两三个博文里详细讨论过了,这里不再重复啰嗦。若想了解详细步骤,请参考:【OpenWrt对C++11的支持


然后,在开发机上启动gdb,并执行 target remote 192.168.1.2:3000 进行连接:

$ gdb  (gdb) target remote 192.168.1.2:3000  Remote debugging using 192.168.1.2:3000  warning: while parsing target description (at line 10): Target description specified unknown architecture "mips"  warning: Could not load XML target description; ignoring  Reply contains invalid hex digit 59

出现问题:(1)首先gdb不认识mips平台。(2)没有XML目标描述文件。


2.2 解决问题

应该说,什么样的平台就应该用什么样的gdb进行调试。如果像上面那样,用开发机的 gdb 与目标机上的 gdbserver 连接进行调试,应该是不对的。

那么应该使用 mips 平台的gdb。而这个gdb就在 staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/ 路径下,有一个:mips-openwrt-linux-gdb 文件。

运行它来进行调试:

[trunk]$ cd ./staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/  [bin]$ ./mips-openwrt-linux-gdb  GNU gdb (Linaro GDB) 7.6-2013.05  Copyright (C) 2013 Free Software Foundation, Inc.  License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>  This is free software: you are free to change and redistribute it.  There is NO WARRANTY, to the extent permitted by law.  Type "show copying"  and "show warranty" for details.  This GDB was configured as "--host=i686-redhat-linux --target=mips-openwrt-linux-uclibc".  For bug reporting instructions, please see:  <http://bugs.launchpad.net/gdb-linaro/>.  (gdb)

可以看到,gdb在启动时提示:"This GDB was configured as "--host=i686-redhat-linux --target=mips-openwrt-linux-uclibc",说明该gdb是针对mips平台的。

这里,博主要总结一下。gdb有三种:

  1. 安装到目标机上,在目标机上运行的gdb。(通过SSH在目标机上运行gdb调试)

  2. 运行在开发机上,用于调试目标机上程序的。(通过SSH在目标机上运行gdbserver开启调试服务,在开发机上启动平台对应的gdb连接gdbserver进行调试)

  3. 运行在开发机上,用于调试开发机程序的。

这3种gdb不能搞混淆了。


好,再连接目标机:

(gdb) target remote 192.168.1.2:3000  Remote debugging using 192.168.1.2:3000  warning: Can not parse XML target description; XML support was disabled at compile time  0x77fe0f40 in ?? ()  (gdb)

结果还是报没有XML目标描述文件。

从网上找到资料:http://blog.csdn.net/yangzhongxuan/article/details/13002789

具这位大牛说,是在编译gdb的时候,没有XML的解析库expat。

那我就在开发机上看一下有没有这个库。用locate查一下:

$ locate libexpat  ...  /lib/libexpat.so.1  /lib/libexpat.so.1.5.2  ...

说明开发机系统是有expat库的。

那为什么没有编译进去呢?有可能是在编译 gdb 的 ./configure 时候,将expat去除了。

查看trunk路径下,关于gdb包的Makefile。打开文件:package/devel/gdb/Makefile,发现:

OpenWRT开发之——远程debug

嘿!第56行,看到了吗?禁了expat。为什么要禁它???

博主也就尝试一下,把第56行删除。改成:

OpenWRT开发之——远程debug

重新make gdb。

[trunk]$ make package/devel/gdb/install V=s

思考一下:你说,这是编译目标机上在gdb呢,还是开发机上的gdb?

实践证明,我想错了。在package目录下都是要打包成ipk的。

因为上面的make命令并没有影响到:staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-gdb

而是:bin/ar71xx/packages/base/gdb_7.8-1_ar71xx.ipk


应该是在 toolchain 目录下的才是。

来自:http://my.oschina.net/hevakelcj/blog/416394