一、调试原理
这里的gdb调试是在pc机上对在开发板上运行的程序进行调试。具体来说的话,在pc机上要运行gdb,在开发板上运行dbserver。gdb调试的时候,pc机上的gdb向开发板上的gdbserver发出命令,而开发板上的gdbserver就会向应用程序发出信号,使应用程序停下来或者完成其他一些工作!由此我们知道,
pc机上要运行gdb,开发板上要运行gdbserver!
二、安装gdb与gdbserver:需要 gdb-7.4.tar.bz2
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
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: 显示调用堆栈
(7)bt: 显示调用堆栈
更详细的命令,我们在下一节里面会进一步来讲讲的!
6、另一种调试方法,
根据core dump文件调试
让程序在开发板上直接运行,当它发生错误时,令它产生core dump文件
然后使用gdb根据core dump文件找到发生错误的地方
在ARM开发板上:
1. ulimit -c unlimited
2. 执行应用程序 : 程序出错时会在当前目录下生成名为core的文件
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]
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;
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
#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