本帖最后由 xcoder 于 2016-4-3 19:50 编辑
实战8 GDB调试应用程序
GDB是一个强大的调试工具,通过命令可以随时运行、停止程序,也可以实现设置断点、查看变量值、函数调用栈、寄存器等等。它能够完全“控制”目标程序,在分析程序运行以及查找bug时十分有用。使用GDB调试pcDuino板上运行的应用程序时,首先需要搭建调试环境,网络拓扑如图所示。
图8.1 GDB调试环境模型 虚拟机与pcDuino板在同一个局域网内,二者可以通过网络互相访问。gdbserver是GDB的服务端程序,它监听GDB客户端的连接,配合GDB客户端完成程序调试,pcDuino板上使用gdbserver启动待调试的应用程序,在虚拟机上运行gdb,也就是GDB客户端程序,之后连接到gdbserver进行调试。
8.1 编译gdbserver 下载GDB源码,网址http://www.gnu.org/software/gdb,我们以gdb-7.9.tar.xz版本为例。解压源码: # cd /home/ubuntu/pcduino # xz -d gdb-7.9.tar.xz # tar xvf gdb-7.9.tar |
编译生成gdbserver工具 # cd gdbserver # ./configure --target=arm-linux-gnueabihf --host=arm-linux-gnueabihf # make |
最后生成的gdbserver工具在gdb-7.9/gdb/gdbserver目录中。 按照调试环境的网络拓扑描述,需要将gdbserver保存到pcDuino板中,如果pcDuino板以NFS的方式启动,只需要将gdbserver拷贝到NFS目录/home/ubuntu/pcDuino/nfs中。因为该目录是pcDuino板启动后的根目录,可以看到gdbserver,我们采取这种方式。 # mkdir /home/ubuntu/pcduino/nfs/app# cp /home/ubuntu/pcduino/gdb-7.9/gdb/gdbserver/gdbserver/home/ubuntu/pcduino/nfs/app/ |
读者也可以采用SD卡启动的方式,这种情况需要将gdbserver保存到SD卡中。 对于虚拟机中运行的gdb工具,直接使用工具链自带的arm-linux-gnueabihf-gdb。
8.2 编译测试程序在源码目录/home/ubuntu/pcduino/experiments/gdb-example中执行: # cd /home/ubuntu/pcduino/experiments/gdb-example# make# make install |
生成测试程序,gdb-example会被自动拷贝到/home/ubuntu/pcduino/nfs/app目录下。
8.3 调试演示 pcDuino板以NFS的方式启动,查看/app目录,已经存在gdb_example 和gdbserver了。 图8.2 pcDuino板上程序
配置pcDuino板的IP地址,当前使用192.168.1.110
图8.3 pcDuino地址配置
使用gdbserver运行测试程序gdb_example,在pcDuino板上执行如下命令: # ./gdbserver 192.168.1.110:6000 gdb_example |
其中6000是gdbserver监听的端口号。 图8.4 gdbserver监听连接 在虚拟机上启动GDB客户端 # cd /home/ubuntu/pcduino/experiments/gdb-example# arm-linux-gnueabihf-gdb gdb_example |
gdb启动输出如下,等待用户输入 GNU gdb (crosstool-NG linaro-1.13.1-4.9-2014.07 - Linaro GCC 4.9-2014.07) 7.6.1-2013.10Copyright (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-build_pc-linux-gnu --target=arm-linux-gnueabihf".For bug reporting instructions, please see:<https://bugs.launchpad.net/gcc-linaro>...Reading symbols from /home/ubuntu/pcduino/experiments/gdb-example/gdb_example...done.(gdb) |
现在开始连接到pcDuino板的gdbserver,输入: (gdb) target remote 192.168.1.110:6000 |
注意IP地址和端口号要与pcDuino板启动gdbserver使用的一致。如果连接成功则有如下提示信息:Remote debugging using 192.168.1.110:6000Reading symbols from /home/ubuntu/pcduino/gcc-linaro-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/ld-linux-armhf.so.3...done.Loaded symbols for /home/ubuntu/pcduino/gcc-linaro-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/ld-linux-armhf.so.30xb6fdfa40 in _start () from /home/ubuntu/pcduino/gcc-linaro-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/ld-linux-armhf.so.3(gdb) |
同时pcDuino板会出现提示连接成功的打印 图8.5 连接gdbserver成功 此时,我们就可以在虚拟机中运行gdb命令来调试测试程序。 1.查看源码 (gdb) list
1 int add(int a, int b)
2 {
3 return a + b;
4 }
5
6 int main(int argc, char *argv[])
7 {
8 int i;
9
10 int sum[10] = { |
2.设置断点 (gdb) break addBreakpoint 1 at 0x83aa: file gdb_example.c, line 3. |
3.运行程序 (gdb) continue Continuing.
Breakpoint 1, add (a=48, b=85) at gdb_example.c:3
3 return a + b; |
程序遇到断点,停止运行。
4.查看调用栈 (gdb) backtrace
#0 add (a=48, b=85) at gdb_example.c:3
#1 0x0000845c in main (argc=1, argv=0xbefffe84) at gdb_example.c:23 |
每一行列出一个函数,调用过程自下而上。即main->add
5. 退出gdb(gdb) q
A debugging session is active.
Inferior 1 [process 67] will be killed.
Quit anyway? (y or n) y |
本章首相介绍了GDB的运行拓扑环境,接下来以实际例子演示如何使用,GDB拥有十分丰富的命令用于调试程序,对于GDB命令的讲解不是本书重点,因此不做详细说明,读者可以参考gdb help或相关书籍进行学习。
|