OpenWRT開發之——遠程debug
想要用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,進行系統進行裁剪。
gdbserver在 Development 目錄下。
將gdbserver選為M,保存退出。
可以打開 .config 進行查看:
可以看到 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; }</pre>
src/Makefile:
target:=debug-demo CFLAGS+=-gobjects:=$(subst .c,.o,$(wildcard *.c))
$(target) : $(objects) $(CC) $(CFLAGS) -o $@ $^
.PHONY:clean clean: $(RM) $(objects)</pre>
值得注意的是:在 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有三種:
安裝到目標機上,在目標機上運行的gdb。(通過SSH在目標機上運行gdb調試)
</li>運行在開發機上,用于調試目標機上程序的。(通過SSH在目標機上運行gdbserver開啟調試服務,在開發機上啟動平臺對應的gdb連接gdbserver進行調試)
</li>運行在開發機上,用于調試開發機程序的。
</li> </ol>這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,發現:
![]()
嘿!第56行,看到了嗎?禁了expat。為什么要禁它???
博主也就嘗試一下,把第56行刪除。改成:
![]()
重新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