2009年2月4日星期三

GDB学习及嵌入式下如何使用Debug

作者: Sam(甄峰) sam_code@hotmail.com

前段时间和朋友聊天,谈到工作中使用什么调试工具,Sam很不好意思地讲,我只用printf打印信息调试,被狠狠地嘲笑了一通。Sam一直作嵌入式程序或kernel层程序,在这个领域内,用调试工具的人好像还真不算多。但Sam很认同朋友的话,调试工具能够极大的提高效率。所以决定借当前的移植工作把GDB用起来。


GDB(GNU symbolic debugger)
GDB可以让你调试一个程序,包括让程序在你希望的地方停下,此时你可以查看变量,寄存器,内存及堆栈。更进一步你可以修改变量及内存值。


Sam首先用BT_remote来做GDB试验。
1. 编译时需要加入选项 -g

2. 使用GDB 启动程序。
#gdb BT_remote
GNU gdb Red Hat Linux (6.6-35.fc8rh)
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you arewelcome 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 "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) l //相当于list,列出代码
166 int main(int argc, char** argv)
167 {
168 BOOL bDongle_Ready = FALSE;
169 BTRC_Rel BTRC_Rel_all;
170 int iRet_pthread_create = 0;
171 pthread_t ntid;
172 UINT8 ID;
173 UINT16 SetAudioFile_rel;
174 int i = 0;
175 BT_CONNECTION_STATUS status;
176
177
178
179 BTRC_Rel_all = BluetoothDongleInit();
180 if(BTRC_Rel_all != BTRC_SUCCESS)
181 {
182 printf("\nBluetooth Dongle Init fail. Error Code:[%d]\n", BTRC_Rel_all);
183 return -1;
184 }


(gdb) break 169 //在168行设置断点
(gdb) break BluetoothDongleInit //在函数BluetoothDongleInit处加断点
(gdb) info break //察看断点
Num Type Disp Enb Address What
1 breakpoint keep y BluetoothDongleInit
2 breakpoint keep y 0x0804925c in main at main.c:169

(gdb)clear169 //清除Line 169断点



(gdb)watch iBluetooth_Rel_all //将变量设为观察点,当此变量有变化时,程序立刻停住
(gdb)info watchpoints //显示观察点
(gdb) r //run,开始run程序
到了第一个断点,则停下来,可以用 l 命令看其前后代码,也可以用p 来看某个变量的值

(gdb) p bDongle_Ready
$1 = FALSE

(gdb) n //next
(gdb) c //继续执行



主题二:
嵌入式下如何使用GDB:

1. 下载GDB.
http://ftp.gnu.org/gnu/gdb/

2. 编译:
(注意:因为此gdbserver是为Canmore使用的,所以不需要类似:CC=arm-linux-gcc ./configure --host=.... --target==... 这样的东西,如果是其它ARM平台,则需要这样做)
2.1 编译GDB
#./configure
#make clean;make
2.2 编译gdbserver
#cd gdb/gdbserver
#./configure
#make clean;make
将生成的gdbserver放到嵌入式板子上去。

3. copy 所需库:
将libthread_db copy到嵌入式平台。

4. 使用
4.1在嵌入式平台:
#gdbserver 172.16.1.61:1234 BT_remote
Process BT_remote created; pid = 716
Listening on port 1234
这个意思是:debug BT_remote这个程序。对方是172.16.1.61. 端口为:1234。
4.2在Host 端:
#gdb BT_remote
GNU gdb Red Hat Linux (6.6-35.fc8rh)Copyright (C) 2006 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome 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 "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) target remote 172.16.1.31:1234
Undefined target command: "172.16.1.31:1234 ". Try "help target".(gdb) target remote 172.16.1.31:1234`system-supplied DSO at 0x110000' has disappeared; keeping its symbols.Remote debugging using 172.16.1.31:1234[New Thread 716]
warning: Missing the separate debug info file: /usr/lib/debug/.build-id/ac/2eeb206486bb7315d6ac4cd64de0cb50838ff6.debug0xb7f17810 in _start () from /lib/ld-linux.so.2

此时发现嵌入式板子上有反应:
Remote debugging from host 172.16.1.61

则表明嵌入式板子和Host Debug链接成功,则可以在Host上调试嵌入式板子上的程序了。

但请注意,在Host上,不能使用 r 来运行,而应该使用 c来运行,因为这个程序已经在运行了。

则可以正常使用了。



嵌入式平台上GDB调试实例:
Sam想在X5平台上使用GDB来调试程序。
分析:
1. 需要gdbserver
2. 客户端需要gdb程序。
3. 需要重新编译,加入 -g.

1.编译gdbserver:
#cd gdb-6.8/gdb/gdbserver
#CC=/opt/hisilicon/toolchains/arm-uclibc-linux-soft/bin/arm-uclibc-linux-gcc ./configure --host=arm-linux
#make clean;make all
则gdbserver生成成功。Sam把它copy到板子的/bin目录中

2. 客户端gdb程序。
直接使用交叉编译器中的arm-uclibc-linux-gdb

3.重新编译程序。
Sam是想调试SDL例子程序,所以在SDL库生成过程和test生成过程中均加入 -g.




实际操作:
1. 嵌入式板子中:
#gdbserver 172.16.1.61:1234 testsprite

2. Host
2.1
#arm-uclibc-linux-gdb testsprite
2.2
(gdb) target remote 172.16.1.45:1234
2.3
(gdb) c


之后和本地调试类似。

没有评论: