gdb+gdbserver的方式進行ARM程序調試

gdb+gdbserver的方式進行ARM程序調試


【摘要】:本文首先介紹了gdb+gdbserver相關的概念,然後介紹了其下載、編譯、安裝等過程;接着介紹了利用gdb+gdbserver調試應用程序的流程及實例等;最後分析了下gdb+gdbserver安裝過程中的常見問題。

 

【關鍵詞】:gdbgdbserver,遠程調試

 

目錄

一、gdb+gdbserver總體介紹

二、源代碼下載

三、配置編譯及安裝下載

四、gdb+gdbserver nfs調試流程

五、如何利用串口調試

六、實戰調試

七、linux下安裝gdbserver問題

 

一、gdb+gdbserver總體介紹

遠程調試環境由宿主機GDB和目標機調試stub共同構成,兩者通過串口或TCP連接。使用 GDB標準程串行協議協同工作,實現對目標機上的系統內核和上層應用的監控和調試功能。調試stub是嵌入式系統中的一段代碼,作爲宿主機GDB和目標機調試程序間的一個媒介而存在。

就目前而言,嵌入式Linux系統中,主要有三種遠程調試方法,分別適用於不同場合的調試工作:用ROM Monitor調試目標機程序、KGDB調試系統內核和用gdbserver調試用戶空間程序。這三種調試方法的區別主要在於,目標機遠程調試stub 的存在形式的不同,而其設計思路和實現方法則是大致相同的。

而我們最常用的是調試應用程序。就是採用gdb+gdbserver的方式進行調試。在很多情況下,用戶需要對一個應用程序進行反覆調試,特別是複雜的程序。採用GDB方法調試,由於嵌入式系統資源有限性,一般不能直接在目標系統上進行調試,通常採用gdb+gdbserver的方式進行調試。

二、源代碼下載

嵌入式LinuxGDB調試環境由HostTarget兩部分組成,Host端使用armlinuxgdbTarget Board端使用gdbserver。這樣,應用程序在嵌入式目標系統上運行,而gdb調試在Host端,所以要採用遠程調試(remote)的方法。進行GDB調試,目標系統必須包括gdbserver程序(在主機上正對硬件平臺編譯成功後下載到目標機上),宿主機也必須安裝GDB 程序。一般Linux發行版中都有一個可以運行的GDB,但開發人員不能直接使用該發行版中的GDB來做遠程調試,而要獲取GDB的源代碼包,針對arm 平臺作一個簡單配置,重新編譯得到相應GDBGDB的源代碼包可以從

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

http://ftp.gnu.org/gnu/gdb/   211.95.105.2023128可以上去的,所有的版本都有啊

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 jxvf gdb-6.5-tar-bz2

#cd gdb-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+gdbserver nfs調試流程

下面就可以用gdb+gdbserver調試我們開發板上的程序了。在目標板上運行 gdbserver,其實就是在宿主機的minicom下。我是在minicom#mount 192.168.2.100:/ /tmp後做的(這裏參數-o nolock可以不加,不加這一步執行得反而更快些)hellogdbserver都是位於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-gdb hello

最後一行顯示:This GDB was configured as “--hosti686pclinuxgnu,--targetarmlinux”...,如果不一致說明arm-linux-gdb有問題

說明此gdbX86Host上運行,但是調試目標是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命令如listrunnextstepbreak等進行程序調試了。

以上針對通過nfs mounttftp的方式,只能在主機上調試好後下載到開發板上運行,如果有錯誤要反覆這個過程,繁瑣不說,有些程序只能在開發板上調試。所以筆者採用了gdbserver的遠程調試方式。希望對大家調試程序有用!

五、如何利用串口調試

如果你用串口1調試hello的話,你就要現在板子上運行命令:

gdbserver hello /dev/ttyS0 (詳情可以參考gdbserver目錄下的readme文件)

這時gdbserver就在等待gdb的應答信號了。

然後在pc機上運行命令:

xxx-linux-gdb hello

 

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 <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.下載文件到目標板: gdbtestgdbserver

假設 host pc ip:192.168.1.45

     board   ip:192.168.1.180   

將文件拷貝到目標板上:

先將gdbtestgdbserver兩個文件拷貝到主機的/tftpboot目錄下,此時系統主機和目標機都必須能夠支持nfs

在目標板的Linux中運行:

#mount 192.168.1.108:/tftpboot /mnt/nfs

#cd /mnt/nfs

#ls

看是否有gdbtestgdbserver兩個文件。

3.運行調試

client board

#./gdbserver 192.168.1.45:1234 gdbtest  // 目標板上運行gdbtest 監聽端口1234

 

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

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

 

host pc

#cd /usr/local/arm-gdb/bin/ 以便能夠運行arm-linux-gdb,但是無此必要,可在環境變量中設置此路徑即可。

#copy gdbtest /usr/local/arm-gdb/bin/   // 將前面編譯的文件gdbtest拷貝到此目錄

#./arm-linux-gdb gdbtest

(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
#cd gdb-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./../../bfd linux-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,但是感覺不太對,請問各位,是什麼原因呢?

是不是CCtarget寫錯了?應該是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 <sys/reg.h> header file. */

/*define HAVE_SYS_REG_H 1  */

/*have no  <sys/reg.h> 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@AT91RM9200DK arm]$./gdbserver 192.168.0.12:2345 mainparacarm  gdb6.5

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

 

[root@AT91RM9200DK arm]$./gdbserver 192.168.0.14:2345 mainparacarm  gdb6.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.0     libtermcap.so.2

 

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

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

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

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

 

難道目前的gdb 6.5 版本太高,需要內核版本和交叉編譯器與之匹配?實在不行,就試試低版本的gdb

 

轉載

http://blog.csdn.net/sailor_8318/archive/2008/04/16/2295583.aspx

參考文檔

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章