应用调试之使用gdb和gdbserver

一、调试原理
这里的gdb调试是在pc机上对在开发板上运行的程序进行调试。具体来说的话,在pc机上要运行gdb,在开发板上运行dbserver。gdb调试的时候,pc机上的gdb向开发板上的gdbserver发出命令,而开发板上的gdbserver就会向应用程序发出信号,使应用程序停下来或者完成其他一些工作!由此我们知道, pc机上要运行gdb开发板上要运行gdbserver


二、安装gdb与gdbserver:需要 gdb-7.4.tar.bz2 

gdb:
1、下载: http://ftp.gnu.org/gnu/gdb/ 
2、解压:tar xvf gdb-7.4.tar.bz2
3、配置:cd gdb-7.4/
                ./configure --target=arm-linux
4、编译: make
5、安装:mkdir tmp 
                make install prefix=$PWD/tmp
                这里是安装到了我们当前目录的tmp里面
6、查看PC机上以前安装好的gdb版本:arm-linux-gdb -v
发现是7.4版本的,我们编译的正好也是7.4版本的哦!
7、拷贝: cp tmp/bin/arm-linux-gdb /bin/
以后我们如果想使用我们自己编译的gdb的话可以使用绝对路径:/bin/ arm-linux-gdb

gdbserver
1、cd gdb/gdbserver/
2、配置: ./configure --target=arm-linux --host=arm-linux
3、编译: make CC=/usr/local/arm/3.4.5/bin/arm-linux-gcc
出现错误:
linux-arm-low.c: In function `arm_stopped_by_watchpoint':
linux-arm-low.c:642: error: `PTRACE_GETSIGINFO' undeclared (first use in this function)
linux-arm-low.c:642: error: (Each undeclared identifier is reported only once
linux-arm-low.c:642: error: for each function it appears in.)

解决方法:这里提示没有 PTRACE_GETSIGINFO这个东西,这里搜索 PTRACE_GETSIGINFO的路径为-I指定的头文件以及交叉 编译工具链,我们不妨到交叉编译工具链里面去查找一下:
cd /usr/local/arm/3.4.5/
grep "PTRACE_GETSIGINFO" * -nR
找到如下信息:
arm-linux/sys-include/linux/ptrace.h:27:#define PTRACE_GETSIGINFO       0x4202
arm-linux/include/linux/ptrace.h:27:#define PTRACE_GETSIGINFO   0x4202
distributed/arm-linux/sys-include/linux/ptrace.h:27:#define PTRACE_GETSIGINFO   0x4202
distributed/arm-linux/include/linux/ptrace.h:27:#define PTRACE_GETSIGINFO       0x4202
说明 PTRACE_GETSIGINFO是在交叉编译工具链: linux/ ptrace.h文件里 定义的,那么可能是头文件没有包含好吧!
我们到gdbserver下的linux-arm-low.c里面一看,可不是嘛,只有:#include <sys/ptrace.h>而没有:#include <linux/ptrace.h>,于是加上:#include <linux/ptrace.h>,再次编译: make CC=/usr/local/arm/3.4.5/bin/arm-linux-gcc,成功!

4、拷贝: 将gdbserver拷贝到开发板的bin目录下

三、调试
1、 编译要调试的应用程序:必须要加-g选项
测试程序如下(名字是:test_debug.c):
#include <stdio.h>
void C(int *p)
{
*p = 0x12;
}

void B(int *p)
{
C(p);
}

void A(int *p)
{
B(p);
}

void A2(int *p)
{
C(p);
}

int main(int argc, char **argv)
{
int a;
int *p = NULL;

A2(&a);  // A2 > C
printf("a = 0x%x\n", a);

A(p);    // A > B > C
return 0;
}

按如下编译它: arm-linux-gcc -g -o test_debug test_debug.c

2、运行时出现错误:
/mnt/code/28th_app_debug # ./test_debug
a = 0x12
Segmentation fault
下面就开始进行调试

3、 在开发板上:gdbserver 192.168.183.127:2345 ./test_debug(或者 gdbserver localhost:2345 ./test_debug)

 
打印出如下信息:
Process ./test_debug created; pid = 751
Listening on port 2345
 
其中 192.168.183.127:本开发板的ip
       123:端口号,自己随便写的
        ./test_debug:要调试的程序
 
4、在 PC上:/bin/arm-linux-gdb ./test-debug (在bin目录下,其实可以直接敲:arm-linux-gdb ./test_debug)
                     target remote 192.168.183.127:2345
 
5、下面就可以正式调试了!我们先来说一下 几个常用的命令
(1)l:列出所有源代码
(2)break/b main:在main处打断点
         break test_debug.c:11:在test_debug.c的11行打断点
(3)c:运行到断点处
(4)step:单步执行
(5)next:单步执行,但是step会进入函数里面,但是next不会
(6)print a:打印a这个变量的值(打印16进制: p/x a)
(6)quit:退出,输入此命令则开发板上的gdbserver也退出
(7)bt: 显示调用堆栈
更详细的命令,我们在下一节里面会进一步来讲讲的!
 
6、另一种调试方法, 根据core dump文件调试
让程序在开发板上直接运行,当它发生错误时,令它产生core dump文件
然后使用gdb根据core dump文件找到发生错误的地方
 
在ARM开发板上:
1. ulimit -c unlimited
2. 执行应用程序 : 程序出错时会在当前目录下生成名为core的文件
 
在PC上:
3、首先 将core文件拷贝到pc机上
     然后:/bin/ arm-linux-gdb ./test_debug ./core
 
打印出如下信息:
 
GNU gdb (GDB) 7.4
Copyright (C) 2012 Free Software Foundation, Inc.
…………
[New LWP 748]
warning: `/lib/libc.so.6': Shared library architecture unknown is not compatible with target architecture arm.
warning: `/lib/ld-linux.so.2': Shared library architecture unknown is not compatible with target architecture arm.
Core was generated by `./test_debug'.
Program terminated with signal 11, Segmentation fault.
#0  0x000084ac in C (p=0x0) at test_debug.c:6
6               *p = 0x12;
 
4、bt:可以显示调用关系
 
#0  0x000084ac in C (p=0x0) at test_debug.c:6
#1  0x000084d0 in B (p=0x0) at test_debug.c:12
#2  0x000084f0 in A (p=0x0) at test_debug.c:17
#3  0x00008554 in main (argc=1, argv=0xbeb32eb4) at test_debug.c:34

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值