1.gdb和gdbserver调试原理html
经过linux虚拟机里的gdb,来向开发板里的gdbserver发送命令,好比设置断点,运行setp等,而后开发板上的gdbserver收到命令后,便会执行应用程序作相应的动做,来实现调试的功能linux
和以前学的裸板GDB调试 同样,只不过以前学的是在win下的,本次是在linux里的gdb服务器
1.1一样,它们都会须要一个带调试信息的编译文件.函数
经过Makefile里的arm-linux-gcc -g 来的, -g:表示编译文件里包含gdb调试信息测试
1.2为何须要调试信息的编译文件?ui
好比读开发板的应用程序里的变量a:spa
首先gdb经过应用程序的带调试信息的编译文件,来找出变量a存的地址位置debug
而后将地址发送给开发板里的gdbserver,来读出a地址的值指针
2.安装gdb和gdbserver 调试
首先进入官网下载gdb-7.4: http://ftp.gnu.org/gnu/gdb/
2.1在虚拟机上安装GDB:
# tar xjf gdb-7.4.tar.bz2 //解压
# cd gdb-7.4/ //进入gdb-7.4目录
#./configure --target=arm-linux //GDB须要在pc本机里运行,并调试开发板里的应用程序,因此--target设为arm-linux
#make //编译
#mkdir tmp #make install prefix=$PWD/tmp //安装到./tmp目录下
sudo cp tmp/bin/arm-linux-gdb /bin/ //复制到/bin目录下
/bin/arm-linux-gdb -v //-v: 肯定一下gdb的版本VID,是不是7.4
2.2 在开发板上安装GDBServer:
cd gdb/gdbserver/ //在gdb-7.4目录下输入
./configure --target=arm-linux --host=arm-linux //设GDBServer的工做环境
make //编译
出现如下错误:
指在linux-arm-low.c里,没有找到PTRACE_GETSIGINFO 定义
2.3 解决:
1)
#echo $PATH //来查看PATH环境变量
找到编译器gcc位于/work/tools/gcc-3.4.5-glibc-2.3.6/bin
2)
#cd /work/tools/gcc-3.4.5-glibc-2.3.6/ # grep "PTRACE_GETSIGINFO" * -nR
在gcc根目录下,搜索到在linux/ptrace.h中定义:
3)
#vi linux-arm-low.c
添加: #define PTRACE_GETSIGINFO 0x4202
4)最后从新make,生成gdbserver命令文件
而后将gdbserver命令文件,放入咱们开发板的根目录/bin中,便能使用了
cp gdbserver /nfs_root/bin/ //nfs_root:开发板的nfs系统根目录
3.测试程序以下(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; }
其中A2(&a)会调用A2()->C(),而后将a赋值为0x12.
A(p)会调用A()->B()->C(),因为p是个空指针,这里将会出错.
接下来,咱们便以这个应用程序为例.
4.编译
#arm-linux-gcc -g -o test_debug test_debug.c //-g:附带调试信息
5.调试test_debug.c
在开发板上:
首先,须要让gdbserver创建本地服务器,以及要测试的哪一个文件:
#gdbserver 192.168.2.107:2345 ./test_debug //192.168.2.107:本地IP地址 //2345:端口号,用来让gdb来链接用的 //./test_debug:要测试的哪一个文件
在虚拟机上:
#/bin/arm-linux-gdb ./test_debug // 启动gdb,指定调试文件为test_debug
#target remote 192.168.2.107:2345 //与gdbserver创建链接
5.1链接成功,便使用gdb命令来调试
经常使用命令以下所示(参考http://blog.sciencenet.cn/blog-619295-813770.html):
l
列出全部源代码
break [file]:[row]
打断点,好比:
break test_debug.c:21 //在test_debug.c文件的第21行处打断点
info br
查看断点
info file
列出当前的文件,共享库。
delete <num>
删除第几个断点,以下图所示:
c
启动程序运行
step
单步执行
next
单步执行,和step不一样的是,好比:当前行里有函数调用时,next直接执行下一句,step会进入函数
print a
打印a变量的值
quit
退出gdb
6.也能够经过gdb+coredump来调试test_debug.c
当程序运行出错时,便会生成core文件,并将程序里的运行情况存到core中,也就是coredump,供给gdb来调试
6.1首先,经过ulimit来查看coredump的资源大小
ulimit命令(user limit),主要用来限制用户的各个进程资源.
在开发板里,输入
如上图所示,能够看到coredump的资源大小为0,也就是说,当程序运行出错时,不会生成core文件
6.2设置core文件
设置core文件的资源大小为无限制,输入:
ulimit -c unlimited //-c:对应coredump
6.3生成core文件
执行:
#./test_debug
出现段错误,并生成core文件,以下图所示:
6.4 进入虚拟机
将core拷贝过来,而后执行:
#/bin/arm-linux-gdb ./test_debug ./core
而后输入bt,即可查看调用关系: