登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

张继飞的博客

呜呼哀哉

 
 
 

日志

 
 

GDB 远程调试试验(gdbserver)【ZT】  

2009-04-01 09:50:16|  分类: 嵌入式 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

基本原理

调试器是运行在host pc机的应用程序, 被调试的程序是运行在target上。

插桩(stub):在目标操作系统和调试器内分别加入某些功能模块,二者互通信息来进行调试。

调试器与被调程序的通信:  Gdb和调试stub通过GDB串行协议进行通信。指定通信端口(串口 并口 网卡)遵循远程调试协议进行通信。GDB串行协议是一种基于消息的ASCII码协议,包含了诸如读写内存、查询寄存器、运行程序等命令。 

 

被调程序产生异常并及时通知调试器:通过通信模块,告知调试器当前的异常号;调试器根据此向用户显示被调试程序产生了拿一类异常。

目标操作系统需要定义一个设置断点的函数。目标系统添加的这些模块通称为插桩,驻留在ROM中称为ROM monitor。若将kgdb开关打开,就相当于加入了插桩。

运行于目标系统的被调试程序要在入口处调用设置断点的函数产生异常,异常处理程序调用调试端口通信模块,等待主机上的调试器发来信息。双方建立连接后,调试器便等待用户发出调试命令,目标系统等待调试器根据用户命令生成的指令。

所有的符号表都放在本地主机上,在调试之前将符号表导入,调试就可以对着源码进行调试了。

当调试一个远端目标设备时,gdb依靠了一个调试stub来完成其功能。调试stub即是嵌入式系统中一小段代码,它提供了运行gdb的宿主机和所调试的应用程序间的一个媒介。

 

为了设置断点,gdb使用内存读写命令,来无损害地将原指令用一个TRAP命令或其它类似的操作码代替,使得执行该命令时,可以使得控制权转移到调试stub手中去。在此时,调试stub的任务就是将当前场景传送给gdb(通过远程串行通信协议),然后从gdb处接收命令,该命令告诉了stub下一步该做什么。

当处理器遇到了一个TRAP指令(该指令是由gdb 设置的,做断点用)时,该指令使得处理器的当前场景转向一个名为gdb_exception()的函数。最终,目标调用了gdb_return_from_exception()函数,该函数恢复了处理器的场景并将控制权交给应用程序。

 

 

 

 

 

二.GDB常用命令

file        载入命令        先运行gdb  然后file gdbtest

quit    q   推出 gdb       

run     r   运行载入的程序

info        查看程序信息    info source;    info stack;     info local;     info br;    info prog;    info var;       info function

list    l   显示源代码段    list function;  list linenum;   list;   list-;              list finelname:function; list filename;

break       设置断点    break function; break linenum; break filename:linenum;

next    n   在不单步执行进入其他函数的情况下向前执行一行源代码

step    s   单步执行并进入函数

continue c 继续执行正在调试的程序。

finish      出执行函数

print   p   打印数据    print exp; /F选择输入打印格式 x d u f

set         修改变量值  set variable=value

x           检查内存    x /NFU ADDR N重复数 F输出格式 U每个数据单位大小b h w g              x/4ub 0x4000   

clear       删除设置的的断点。

display     每次程序停止后显示表达式的值。display exp

bt          显示所有的调用堆栈。该命令可以用来显示函数的调用顺序

kill        终止正被调试的程序

make        在不退出gdb的情况下运行make工具

help        显示指定命令的帮助信息      help name

GDB为每个断点赋上一个数字,断点有四种状态:有效(enable) 禁止(disable) 一次有效(enable once) 有效后删除(enable for deletion)

enable 2

disable     2

delete  2

 

 

 

 

三.编译 GDB

#copy  gdb-5.3.tar.gz /root //将gdb-5.3.tar.gz拷贝到/root目录下,或任意别的目录

#cd /root

#tar zxvf gdb-5.3.tar.gz

 

3.1 编译GDB Server

#cd gdb-5.3

#vi ./gdb/arm-tdep.c   

    default: break;    // line 2753添加breaks; 因为如果编译器版本较新 可能出错

#./configure --target=arm-linux --prefix=/usr/local/arm-gdb

#make

#make install           // 生成/usr/local/arm-gdb/bin

 

3.2 编译GDB Client

#cd /root/gdb-5.3

#export PATH=$PATH:/usr/local/arm-gdb/bin

#./configure --target=arm-linux --host=arm-linux

#cd ./gdb/gdbserver

#vi config.h

    //#define HAVA_SYS_REG_H    //注释此句

#make CC=arm-linux-gcc          //编译用于目标机的stub程序  生成gdbserverGDB客户端程序在板子上运行。

 

实战调试

1.编辑文件

# vi gdbtest.c

1 #include <stdio.h>

2

3 int

4 func(int n){

5     int   sum=0, i;

6     for (i=0; i<n; i++){

7         sum += i;

8     }

9     return sum;

10 }

11

12 int

13 main(void)

14 {

15    int   i;

16    long result = 0;

17    for (i=0; i<=100; i++){

18        result += i;

19    }

20 

21    printf("result[1-100] = %d \n", result);

22    printf("resutl[1-225] = %d \n", func(255));

23

24    return 0;

25 }

# arm-linux-gcc -g gdbtest.c -o gdbtest         // 交叉编译

 

2.下载

假定 host pc ip:192.168.1.22

board  ip:192.168.1.123   

将文件拷贝到目标板上 有两种方法:

1)Zmodem

minicom 连接到开发板 登陆进入

#cd /root

ctrl+A然后按Z 再按S 选择zmodem选择目录后在弹出的框内输入文件完整路径名下载gdbserver gdbtest /root

 

2)ftp

host pc: 开通ftp服务    // 下面简要介绍在pc机上开通ftp服务

#adduser embedded       // 新建用户 假定embedded

#passwd embedded       // 输入密码 假定embedded 

#vi /etc/vsftpd/vsftpd.conf

  chroot_list_enable=YES                    #禁止用户离开自己的目录

  # (default follows)

  chroot_list_file=/etc/vsftpd.chroot_list #被禁止的用户名单文件

#vi /etc/vsftpd.chroot_list

embedded                                    // add

/etc/rc.d/initd.d/vsftpd start            // 开通ftp服务

把要传递的文件gdbserver gdbtest拷贝到/home/embedded/目录下

client board

ftp 192.168.1.22        // 下载需要的文件

注意:我们通过nfs可以把pc机的某个目录挂载到板子上,挂载点下经过交叉编译过的可执行文件可以在板子上运行,但不能把挂载点下的文件拷贝到板子的其他目录下。

 

3.运行调试

client board

#./gdbserver 192.168.1.22:1234 gdbtest  // 目标板上运行gdbtest 监听端口1234

 

host pc

#cd /usr/local/arm-gdb/bin/

#copy gdbtest /usr/local/arm-gdb/bin/   // 将前面编译的文件gdbtest拷贝到此目录

#./arm-linux-gdb gdbtest

(gdb)target remote 192.168.1.123:1234   // 连接到开发板 成功后就可以进行调试

(gdb)symbol-file gdbtest               

(gdb)list   or l

(gdb)break func

(gdb)break 22

(gdb)info br   

(gdb)continue   or c    // 这里不能用 run

(gdb)next   or n

(gdb)print or p    result 

(gdb) finish        // 跳出func函数

(gdb) next

(gdb) quit

建立连接后进行gdb远程调试和gdb本地调试方法是一样的。这里给出的代码是正确的,可以加一些错误代码进行调试。

  评论这张
 
阅读(3666)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018