您的位置 首页 国产IC

GDB+GdbServer: ARM程序调试

内容摘要远程调试环境由宿主机GDB和目标机调试stub共同构成,两者通过串口或TCP连接。使用GDB标准程串行协议协同工作,实现对目标机上的

内容摘要长途调试环境由宿主机GDB和方针机调试stub一起构成,两者经过串口或TCP衔接。运用 GDB规范程串行协议协同作业,完结对方针机上的体系内核和上层运用的监控和调试功用。调试stub是嵌入式体系中的一段代码,作为宿主机GDB和方针机调试程序间的一个前言而存在。 就现在而言,嵌入式Linux体系中,首要有三种长途调试办法,别离适用于不同场合的调试作业:用ROM Monitor调试方针机程序、用KGDB调试体系内核和用gdbserver调试用户空间程序。这三种调试办法的差异首要在于,方针机长途调试stub 的存在办法的不同,而其规划思路和完结办法则是大致相同的。 而咱们最常用的是调试运用程序。便是选用gdb+gdbserver的办法进行调试。在许多状况下,用户需求对一个运用程序进行重复调试,特别是杂乱的程序。选用GDB办法调试,由于嵌入式体系资源有限性,一般不能直接在方针体系上进行调试,一般选用gdb+gdbserver的办法进行调试。

gdb的简略运用

GDB是GNU开源安排发布的一个强壮的UNIX下的程序调试东西。或许,各位比较喜爱那种图形界面办法的,像VC、BCB等IDE的调试,但假如你是在 UNIX渠道下做软件,你会发现GDB这个调试东西有比VC、BCB的图形化调试器更强壮的功用。所谓“寸有所长,尺有所短”便是这个道理。一般来说,GDB首要帮助你完结下面四个方面的功用: 1、发动你的程序,可以依照你的自定义的要求为所欲为的运转程序。
2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
3、当程序被停住时,可以检查此刻你的程序中所产生的事。
4、动态的改动你程序的履行环境。从上面看来,GDB和一般的调试东西没有什么两样,基本上也是完结这些功用,不过在细节上,你会发现GDB这个调试东西的强壮,咱们或许比较习惯了图形化的调试东西,但有时分,指令行的调试东西却有着图形化东西所不能完结的功用。让咱们逐个看来。
一个调试示例
—————— 源程序:tst.c 1 #include
2
3 int func(int n)
4 {
5 int sum=0,i;
6 for(i=0; i 7 {
8 sum+=i;
9 }
10 return sum;
11 }
12
13
14 main()
15 {
16 int i;
17 long result = 0;
18 for(i=1; i<=100; i++)
19 {
20 result += i;
21 }
22
23 printf(“result[1-100] = %d \\n”, result );
24 printf(“result[1-250] = %d \\n”, func(250) );
25 } 编译生成履行文件:(Linux下)
hchen/test> cc -g tst.c -o tst 运用GDB调试: hchen/test>gdbtst <---------- 发动GDB
GNUgdb5.1.1
Copyright 2002 Free Software Foundation, Inc.
GDBis free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type “show copying” to see the conditions.
There is absolutely no warranty forGDB. Type “show warranty” for details.
ThisGDBwas configured as “i386-suse-linux”…
(gdb) l <-------------------- l指令相当于list,从榜首行开端例出原码。
1 #include
2
3 int func(int n)
4 {
5 int sum=0,i;
6 for(i=0; i7 {
8 sum+=i;
9 }
10 return sum;
(gdb) <-------------------- 直接回车表明,重复上一次指令
11 }
12
13
14 main()
15 {
16 int i;
17 long result = 0;
18 for(i=1; i<=100; i++)
19 {
20 result += i;
(gdb) break 16 <-------------------- 设置断点,在源程序第16行处。
Breakpoint 1 at 0x8048496: file tst.c, line 16.
(gdb) break func <-------------------- 设置断点,在函数func()入口处。
Breakpoint 2 at 0x8048456: file tst.c, line 5.
(gdb) info break <-------------------- 检查断点信息。
Num Type Disp Enb Address What
1 breakpoint keep y 0x08048496 in main at tst.c:16
2 breakpoint keep y 0x08048456 in func at tst.c:5
(gdb) r <--------------------- 运转程序,run指令简写
Starting program: /home/hchen/test/tst Breakpoint 1, main () at tst.c:17 <---------- 在断点处停住。
17 long result = 0;
(gdb) n <--------------------- 单条句子履行,next指令简写。
18 for(i=1; i<=100; i++)
(gdb) n
20 result += i;
(gdb) n
18 for(i=1; i<=100; i++)
(gdb) n
20 result += i;
(gdb) c <--------------------- 持续运转程序,continue指令简写。
Continuing.
result[1-100] = 5050 <----------程序输出。 Breakpoint 2, func (n=250) at tst.c:5
5 int sum=0,i;
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p i <--------------------- 打印变量i的值,print指令简写。
$1 = 134513808
(gdb) n
8 sum+=i;
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p sum
$2 = 1
(gdb) n
8 sum+=i;
(gdb) p i
$3 = 2
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p sum
$4 = 3
(gdb) bt <--------------------- 检查函数仓库。
#0 func (n=250) at tst.c:5
#1 0x080484e4 in main () at tst.c:24
#2 0x400409ed in __libc_start_main () from /lib/libc.so.6
(gdb) finish <--------------------- 退出函数。
Run till exit from #0 func (n=250) at tst.c:5
0x080484e4 in main () at tst.c:24
24 printf(“result[1-250] = %d \n”, func(250) );
Value returned is $6 = 31375
(gdb) c <--------------------- 持续运转。
Continuing.
result[1-250] = 31375 <----------程序输出。 Program exited with code 027. <--------程序退出,调试完毕。
(gdb) q <--------------------- 退出gdb。
hchen/test>

gdb+gdbserver办法进行ARM程序调试

【摘要】:本文首要介绍了gdb+gdbserver相关的概念,然后介绍了其下载、编译、装置等进程;接着介绍了运用gdb+gdbserver调试运用程序的流程及实例等;最终剖析了下gdb+gdbserver装置进程中的常见问题。

【关键词】:gdb,gdbserver,长途调试

目录

一、gdb+gdbserver整体介绍… 1

二、源代码下载… 1

三、装备编译及装置下载… 1

四、gdb+gdbserver nfs调试流程… 2

五、怎么运用串口调试… 3

六、实战调试… 3

七、linux下装置gdbserver问题… 5

一、gdb+gdbserver整体介绍

长途调试环境由宿主机GDB和方针机调试stub一起构成,两者经过串口或TCP衔接。运用GDB规范程串行协议协同作业,完结对方针机上的体系内核和上层运用的监控和调试功用。调试stub是嵌入式体系中的一段代码,作为宿主机GDB和方针机调试程序间的一个前言而存在。

就现在而言,嵌入式Linux体系中,首要有三种长途调试办法,别离适用于不同场合的调试作业:用ROM Monitor调试方针机程序、用KGDB调试体系内核和用gdbserver调试用户空间程序。这三种调试办法的差异首要在于,方针机长途调试stub的存在办法的不同,而其规划思路和完结办法则是大致相同的。

而咱们最常用的是调试运用程序。便是选用gdb+gdbserver的办法进行调试。在许多状况下,用户需求对一个运用程序进行重复调试,特别是杂乱的程序。选用GDB办法调试,由于嵌入式体系资源有限性,一般不能直接在方针体系上进行调试,一般选用gdb+gdbserver的办法进行调试。

二、源代码下载

嵌入式Linux的GDB调试环境由Host和Target两部分组成,Host端运用arm-linux-gdb,Target Board端运用gdbserver。这样,运用程序在嵌入式方针体系上运转,而gdb调试在Host端,所以要选用长途调试(remote)的办法。进行GDB调试,方针体系有必要包含gdbserver程序(在主机上正对硬件渠道编译成功后下载到方针机上),宿主机也有必要装置GDB程序。一般Linux发行版中都有一个可以运转的GDB,但开发人员不能直接运用该发行版中的GDB来做长途调试,而要获取GDB的源代码包,针对arm渠道作一个简略装备,从头编译得到相应GDB。GDB的源代码包可以从

http://www.gnu.org/software/gdb/download/

http://ftp.gnu.org/gnu/gdb/ 211.95.105.202:3128可以上去的,一切的版别都有啊

http: //ftp.cs.pu.edu.tw/linux/sourceware/gdb/releases/下载

ftp://ftp.gnu.org/gnu/gdb

外网的ftp我常常上不去,国内常见的开源社区的下载频道一般都有下载的http://download.chinaunix.net/download/0004000/3482.shtml,最新版别为gdb-6.5.tar.bz2。下载到某个目录,笔者下载到/opt/。但要留意,gdb的版别需求和croostool相匹配。

三、装备编译及装置下载

下载完后,进入/opt/目录,装备编译进程如下:

#tar jxvfgdb-6.5-tar-bz2

#cdgdb-6.5

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

(–target装备gdb的方针渠道,–prefix装备装置途径,当然其他途径也可以,.跟下面装备共同即可,须在环境变量中声明,发动arm-linux-gdb需求,可更改/etc/profile或~/.bash_profile或~/.bashrc,增加export PATH=$PATH:/usr/local/arm-gdb/bin,这样可以找到途径)

#make

#make install

(生成arm-linux-gdb,并存入/usr/local/arm-gdb/bin/,查询承认下)

也可以发动arm-linux-gdb,若成功,则证明装置无误

进入gdb/gdbserver目录:

[root@dding gdbserver]# pwd

/opt/gdb-6.5/gdb/gdbserver

[root@dding gdbserver]#有必要在gdbserver目录下运转装备指令,此刻才干用相对途径

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

(–target=arm-linux表明方针渠道,–host表明主机端运转的是arm-linux-gdb,不需求装备—prefix,由于gdbserver不在主机端装置运转)

#make CC=/usr/local/arm/2.95.3/bin/arm-linux-gcc

(这一步要指定你自己的arm-linux-gcc的肯定方位,我试过相对的不可,提示make:arm-linux-gcc: Command not found,可好多人都用的相对途径,即直接赋值arm-linux-gcc,可采纳make时传递参数,也可以直接修正gdbserver目录下的Makefile文件中的环境变量CC)

没有过错的话就在gdbserver目录下生成gdbserver可履行文件,留意此刻要更改其特点,不然或许会呈现无法访问的状况,chmod 777 gdbserver将其更改为任何人都可以读写履行;运用arm-linux-strip指令处理一下gdbserver,将剩余的符号信息删去,可让elf文件更精简,一般在运用程序的最终发布时运用;然后把它烧写到flash的根文件体系分区的/usr/bin(在此目录下,体系可以主动找到运用程序,不然有必要到gdbserver地点目录下运转之),或经过nfs mount的办法都可以。只需确保gdbserver能在开发板上运转就行。

四、gdb+gdbservernfs调试流程

下面就可以用gdb+gdbserver调试咱们开发板上的程序了。在方针板上运转gdbserver,其实便是在宿主机的minicom下。我是在minicom下#mount 192.168.2.100:/ /tmp后做的(这儿参数-o nolock可以不加,不加这一步履行得反而更快些),hello和gdbserver都是坐落Linux根目录下,把主机根目录挂在到开发板的/tmp目录下。

要进行gdb调试,首要要在方针体系上发动gdbserver服务。在gdbserver地点目录下输入指令:

(minicom下)

#cd /tmp

#./gdbserver 192.168.2.100:2345 hello

192.168.2.100为宿主机IP,在方针体系的2345端口(你也可以设其他可用的值,当然有必要跟主机的gdb共同)敞开了一个调试进程,hello为要调试的程序(有必要-g参加调试信息)。

呈现提示:

Process /tmp/hello created: pid=80

Listening on port 2345

(另一个终端下)

#cd /

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

#arm-linux-gdbhello

最终一行显现:ThisGDBwas configured as “--host=i686-pc-linux-gnu,--target=arm-linux”…,假如不共同阐明arm-linux-gdb有问题

阐明此gdb在X86的Host上运转,可是调试方针是ARM代码。

(gdb) target remote 192.168.2.223:2345

(192.168.2.223为开发板IP)

呈现提示:

Remote debugging using 192.168.2.223:2345

[New thread 80]

[Switching to thread 80]

0x40002a90 in ??()

一起在minicom下提示:

Remote debugging from host 192.168.2.100

(gdb)

留意:你的端口号有必要与gdbserver敞开的端口号共同,这样才干进行通讯。树立链接后,就可以进行调试了。调试在Host端,跟gdb调试办法相同。留意的是要用“c”来履行指令,不能用“r”。由于程序现已在Target Board上面由gdbserver发动了。成果输出是在Target Board端,用超级终端检查。衔接成功,这时分就可以输入各种GDB指令如list、run、next、step、break等进行程序调试了。

以上针对经过nfs mount和tftp的办法,只能在主机上调试好后下载到开发板上运转,假如有过错要重复这个进程,繁琐不说,有些程序只能在开发板上调试。所以笔者选用了gdbserver的长途调试办法。期望对咱们调试程序有用!

五、怎么运用串口调试

假如你用串口1调试hello的话,你就要现在板子上运转指令:

gdbserver hello /dev/ttyS0(概况可以参阅gdbserver目录下的readme文件)

这时gdbserver就在等候gdb的应对信号了。

然后在pc机上运转指令:

xxx-linux-gdbhello

在xxx-linux-gdb里敲入入下指令:

set remotedevice /dev/ttyS0(这儿设置串口1)

set remote baud 9600(这儿设置串口波特率

set debug remote 1(可选)

target remote /dev/ttyS0

操作到这儿,gdb就应该和gdbserver联络上了。

六、实战调试

1.修改文件

# vi gdbtest.c

1 #include

2

3 int

4 func(int n){

5 int sum=0, i;

6 for (i=0; 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.下载文件到方针板: gdbtest和gdbserver

假定host pc ip:192.168.1.45

board ip:192.168.1.180

将文件复制到方针板上:

先将gdbtest和gdbserver两个文件复制到主机的/tftpboot目录下,此刻体系主机和方针机都有必要可以支撑nfs

在方针板的Linux中运转:

#mount 192.168.1.108:/tftpboot /mnt/nfs

#cd /mnt/nfs

#ls

看是否有gdbtest和gdbserver两个文件。

3.运转调试

client board:

#./gdbserver 192.168.1.45:1234 gdbtest //方针板上运转gdbtest监听端口1234

[root@AT91RM9200DKarm]$./gdbserver 192.168.0.12:2345 mainparacarm

./gdbserver: error in loading shared libraries: libthread_db.so.1: cannot open [root@AT91RM9200DKarm]$

host pc:

#cd /usr/local/arm-gdb/bin/以便可以运转arm-linux-gdb,可是无此必要,可在环境变量中设置此途径即可。

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

#./arm-linux-gdbgdbtest

(gdb)target remote 192.168.1.180:1234 //衔接到开发板成功后就可以

进行调试

(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本地调试办法相同

七、linux下装置gdbserver问题

toolchain version:gdb的版别或许和穿插编译器有很大的联系

gcc-3.3.2

glibc-2.2.5

binutils-2.15此为croostool 3.3.2

装置进程:
下载解压gdb-6.6
#cdgdb-6.6
#./configure –target=arm-linux –prefix=/usr/local/arm-gdb–v

#make&make install

OK,然后:

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

进入gdbserver目录:

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

#make CC=/usr/local/armv5l/3.3.2/bin/armv5l-linux-gcc

犯错:

/usr/local/armv5l/3.3.2/bin/armv5l-linux-gcc -c -Wall -g -O2 -I. -I. -I./../regformats -I./../../include -I../../bfd -I./../../bfdlinux-arm-low.c

linux-arm-low.c:35:21: sys/reg.h:没有那个文件或目录

make: *** [linux-arm-low.o]过错1

然后把/usr/include/sys/reg.h copy到/usr/local/armv5l-2.6.x/3.3.2/armv5l-linux/include/sys/reg.h,行将该文件复制到穿插编译器的include目录下,再make,显现过错:

/usr/local/armv5l/3.3.2/bin/armv5l-linux-gcc -c -Wall -g -O2 -I. -I. -I./../regformats -I./../../include -I../../bfd -I./../../bfd thread-db.c

thread-db.c: In function `thread_db_err_str:

thread-db.c:95: error: `TD_VERSION undeclared (first use in this function)

thread-db.c:95: error: (Each undeclared identifier is reported only once

thread-db.c:95: error: for each function it appears in.)

thread-db.c: In function `thread_db_get_tls_address:

thread-db.c:336: warning: implicit declaration of function `td_thr_tls_get_addr

thread-db.c:336: warning: cast to pointer from integer of different size

thread-db.c:340: warning: cast from pointer to integer of different size

make: *** [thread-db.o]过错1

本想持续fix error,可是感觉不太对,请问各位,是什么原因呢?

是不是CC的target写错了?应该是arm-linux仍是armv5l-linux?

1.

make: *** [linux-arm-low.o] Error 1

[root@dding gdbserver]#

[root@dding gdbserver]# gedit config.h

/* Define to 1 if you have the header file. */

/*define HAVE_SYS_REG_H 1 */

/*have no header file. so undefine 20070402 dding */

2.

thread-db.c: In function `thread_db_err_str:gdb6.5

thread-db.c:95: `TD_VERSION undeclared (first use in this function)

[root@dding gdbserver]# gedit config.h

94 #ifdef HAVE_TD_VERSION

95 case TD_VERSION:

96 return “version mismatch between libthread_db and libpthread”;

97 #endif

/* Define if TD_VERSION is available. */

/*#define HAVE_TD_VERSION 1 */

/*have no TD_VERSION. so undefine 20070402 dding */

gdb6.1没有此问题

3.

[root@AT91RM9200DKarm]$./gdbserver 192.168.0.12:2345 mainparacarmgdb6.5

./gdbserver: error in loading shared libraries: libthread_db.so.1: cannot open

[root@AT91RM9200DKarm]$./gdbserver 192.168.0.14:2345 mainparacarmgdb6.1

./gdbserver: error in loading shared libraries: libthread_db.so.1: cannot open shared object file: No such file or directory

我现已加了libthread_db.so.1同享库为什么还打不开呢????同享库和cpu类型有关吗?
gdbserver: error while loading shared libraries: libthread_db.so.1: cannot open
shared object file: No such file or director

****编译GDB的时分搞成静态的就好了.我想编译选项里应该有.要不你就在Makefile里加上CFLAGS += -static
LDFLAGS += -static
这两个的其间一个应该就可以了,不过仍是两个都加上吧.

***/lib there is no libthread_db.so.1 Can i use nfs to copy libthread_db.so.1 to /lib? But now i cannot find this file, and is there any for cross 3.3.2?

libpthread-0.8.so

libpthread.so libpthread.so.0 libresolv-2.1.3.so

libresolv.so.2 libstdc++.a.2.10.0libtermcap.so.2

[root@AT91RM9200DKarm]$cp libthread_db-1.0.so libthread_db.so.1

[root@AT91RM9200DKarm]$cp libthread_db.so.1 /lib/

[root@AT91RM9200DKarm]$./gdbserver 192.168.0.12:2345 mainparacarm

./gdbserver: /lib/libc.so.6: version `GLIBC_2.2 not found (required by /lib/li)

莫非现在的gdb6.5版别太高,需求内核版别和穿插编译器与之匹配?真实不可,就试试低版别的gdb

参阅文档

http://blog.chinaunix.net/u/27802/showart_211833.html

http://litttlebylittle.bokee.com/5803108.html

http://www.blogcn.com/u/93/99/litcatfish/index.html

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/ic/262379.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部