一、调试原理
这里的gdb调试是在pc机上对在开发板上运行的程序进行调试。具体来说的话,在pc机上要运行gdb,在开发板上运行dbserver。gdb调试的时候,pc机上的gdb向开发板上的gdbserver发出命令,而开发板上的gdbserver(是应用程序的父进程)就会向应用程序发出信号,使应用程序停下来或者完成其他一些工作!由此我们知道,pc机上要运行gdb,开发板上要运行gdbserver!
gdb程序需要1个带有调试信息的app文件,从这个文件里面可以得到一些调试信息,以后想打印a变量,gdb就会从带有调试信息的app文件确定a变量的地址,然后发命令给gdbserver,gdbserver再去访问app的内存空间。gdb是命令行的东西,GUI可以使用eclipe
gdb:
2、解压:tar xjf gdb-7.4.tar.bz2
3、配置:cd gdb-7.4/
./configure --target=arm-linux
--build=编译该软件所使用的平台
--host=该软件将运行的平台(默认是PC机)
--target=该软件所处理的目标平台
--host=该软件将运行的平台(默认是PC机)
--target=该软件所处理的目标平台
4、编译:make
5、安装:mkdir tmp
make install prefix=$PWD/tmp
这里是安装到了我们当前目录的tmp里面
查看里面的内容
生成了一个名为arm--linux-gdb的程序。
查看Makefile 看默认的安装目录
6、查看PC机上以前安装好的gdb版本:arm-linux-gdb -v
发现是6.8版本的,我们编译的是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
--build=编译该软件所使用的平台
--host=该软件将运行的平台(默认是PC机)
--target=该软件所处理的目标平台
--host=该软件将运行的平台(默认是PC机)
--target=该软件所处理的目标平台
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指定的头文件的路径,头文件除
了去-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):
A函数调用-》B函数调用-》C函数-》给p赋值
A2函数调用-》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;
}
知道C函数发生错误,从上面知道调用关系有2条路径
-g选项是加调试信息,从而确定调用关系
按如下编译它:arm-linux-gcc
-g -o test_debug test_debug.c
把生成的应用程序拷贝到网络文件系统上去
2、运行时出现错误:
# ./test_debug
a = 0x12
Segmentation fault
下面就开始进行调试
//2345这个是端口,随便写,gdbserver再去访问app的内存空间
3、在开发板上:gdbserver 192.168.1.17:2345 ./test_debug
打印出如下信息:
Process ./test_debug created; pid = 751
Listening on port 2345
Process ./test_debug created; pid = 751
Listening on port 2345
这是自己设置要调试的程序的IP和端口号
其中192.168.1.17:本开发板的ip
2345:端口号,自己随便写的
./test_debug:要调试的程序
gdb要链接到开发板端的应用程序
4、在PC上:/bin/arm-linux-gdb ./test-debug
target remote 192.168.1.17:2345
使用gdb命令来控制程序
再对A2(&a)打断点,在31行
5、下面就可以正式调试了!我们先来说一下几个常用的命令
(1)l:列出所有源代码
(2)break main:在main处打断点
break test_debug.c:22:在test_debug.c的29行打断点
(3)c(continue):运行到断点处
(4)step:单步执行
(5)next:单步执行,但是step会进入函数里面,但是next不会
(6)print a:打印a这个变量的值
(6)quit:退出,输入此命令则开发板上的gdbserver也退出
更详细的命令,我们在下一节里面会进一步来讲讲的!
6、另一种调试方法
让程序在开发板上直接运行,当它发生错误时,令它产生core dump文件
然后使用gdb根据core dump文件找到发生错误的地方
在ARM板上:
1. ulimit -c unlimited (在开发板上输入 ulimit -c 出现值为0时表示当程序出错时产生的core dump文件大小是0(不产生这个文件),unlimited 表示不限制大小)
2. 执行应用程序 : 程序出错时会在当前目录下生成名为core的文件
1. ulimit -c unlimited (在开发板上输入 ulimit -c 出现值为0时表示当程序出错时产生的core dump文件大小是0(不产生这个文件),unlimited 表示不限制大小)
2. 执行应用程序 : 程序出错时会在当前目录下生成名为core的文件
在PC上:
3、首先将core文件(代表core dump)拷贝到pc机上
然后:/bin/arm-linux-gdb ./test_debug ./core
test_debug文件里面含有调试信息
打印出如下信息:
GNU gdb (GDB) 7.4
Copyright (C) 2012 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-pc-linux-gnu --target=arm-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/share/jz2440/test_debug...done.
[New LWP 748]
Copyright (C) 2012 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-pc-linux-gnu --target=arm-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/share/jz2440/test_debug...done.
[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:可以显示调用关系
main->A->B->C,在C 函数里的第6行出错了
#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