gdb的简单使用和gdb+gdbserver方式进行ARM程序调试
生活随笔
收集整理的這篇文章主要介紹了
gdb的简单使用和gdb+gdbserver方式进行ARM程序调试
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
gdb的簡單使用
GDB是GNU開源組織發(fā)布的一個強大的UNIX下的程序調(diào)試工具。或許,各位比較喜歡那種圖形界面方式的,像VC、BCB等IDE的調(diào)試,但如果你是在 UNIX平臺下做軟件,你會發(fā)現(xiàn)GDB這個調(diào)試工具有比VC、BCB的圖形化調(diào)試器更強大的功能。所謂“寸有所長,尺有所短”就是這個道理。一般來說,GDB主要幫忙你完成下面四個方面的功能:? ?? ?1、啟動你的程序,可以按照你的自定義的要求隨心所欲的運行程序。
? ???2、可讓被調(diào)試的程序在你所指定的調(diào)置的斷點處停住。(斷點可以是條件表達式)
? ???3、當(dāng)程序被停住時,可以檢查此時你的程序中所發(fā)生的事。
? ???4、動態(tài)的改變你程序的執(zhí)行環(huán)境。從上面看來,GDB和一般的調(diào)試工具沒有什么兩樣,基本上也是完成這些功能,不過在細節(jié)上,你會發(fā)現(xiàn)GDB這個調(diào)試工具的強大,大家可能比較習(xí)慣了圖形化的調(diào)試工具,但有時候,命令行的調(diào)試工具卻有著圖形化工具所不能完成的功能。讓我們一一看來。
一個調(diào)試示例
—————— 源程序:tst.c? ?? ? 1 #include?
? ?? ?2
? ?? ?3 int func(int n)
? ?? ?4 {
? ?? ?5? ?? ?? ? int sum=0,i;
? ?? ?6? ?? ?? ? for(i=0; i cc -g tst.c -o tst 使用GDB調(diào)試: hchen/test> gdb tst? ?
2
3? ?? ?? ?int func(int n)
4? ?? ?? ?{
5? ?? ?? ?? ?? ???int sum=0,i;
6? ?? ?? ?? ?? ???for(i=0; i
gdb+gdbserver方式進行ARM程序調(diào)試
【摘要】:本文首先介紹了gdb+gdbserver相關(guān)的概念,然后介紹了其下載、編譯、安裝等過程;接著介紹了利用gdb+gdbserver調(diào)試應(yīng)用程序的流程及實例等;最后分析了下gdb+gdbserver安裝過程中的常見問題。
【關(guān)鍵詞】:gdb,gdbserver,遠程調(diào)試
目錄
一、gdb+gdbserver總體介紹... 1
二、源代碼下載... 1
三、配置編譯及安裝下載... 1
四、gdb+gdbserver nfs調(diào)試流程... 2
五、如何利用串口調(diào)試... 3
六、實戰(zhàn)調(diào)試... 3
七、linux下安裝gdbserver問題... 5
一、gdb+gdbserver總體介紹
遠程調(diào)試環(huán)境由宿主機GDB和目標機調(diào)試stub共同構(gòu)成,兩者通過串口或TCP連接。使用 GDB標準程串行協(xié)議協(xié)同工作,實現(xiàn)對目標機上的系統(tǒng)內(nèi)核和上層應(yīng)用的監(jiān)控和調(diào)試功能。調(diào)試stub是嵌入式系統(tǒng)中的一段代碼,作為宿主機GDB和目標機調(diào)試程序間的一個媒介而存在。?
就目前而言,嵌入式Linux系統(tǒng)中,主要有三種遠程調(diào)試方法,分別適用于不同場合的調(diào)試工作:用ROM Monitor調(diào)試目標機程序、用KGDB調(diào)試系統(tǒng)內(nèi)核和用gdbserver調(diào)試用戶空間程序。這三種調(diào)試方法的區(qū)別主要在于,目標機遠程調(diào)試stub 的存在形式的不同,而其設(shè)計思路和實現(xiàn)方法則是大致相同的。?
而我們最常用的是調(diào)試應(yīng)用程序。就是采用gdb+gdbserver的方式進行調(diào)試。在很多情況下,用戶需要對一個應(yīng)用程序進行反復(fù)調(diào)試,特別是復(fù)雜的程序。采用GDB方法調(diào)試,由于嵌入式系統(tǒng)資源有限性,一般不能直接在目標系統(tǒng)上進行調(diào)試,通常采用gdb+gdbserver的方式進行調(diào)試。
二、源代碼下載
嵌入式Linux的GDB調(diào)試環(huán)境由Host和Target兩部分組成,Host端使用arm-linux-gdb,Target Board端使用gdbserver。這樣,應(yīng)用程序在嵌入式目標系統(tǒng)上運行,而gdb調(diào)試在Host端,所以要采用遠程調(diào)試(remote)的方法。進行GDB調(diào)試,目標系統(tǒng)必須包括gdbserver程序(在主機上正對硬件平臺編譯成功后下載到目標機上),宿主機也必須安裝GDB 程序。一般Linux發(fā)行版中都有一個可以運行的GDB,但開發(fā)人員不能直接使用該發(fā)行版中的GDB來做遠程調(diào)試,而要獲取GDB的源代碼包,針對arm 平臺作一個簡單配置,重新編譯得到相應(yīng)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
外網(wǎng)的ftp我經(jīng)常上不去,國內(nèi)常見的開源社區(qū)的下載頻道通常都有下載的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配置安裝路徑,當(dāng)然其他路徑也可以, .跟下面配置一致即可,須在環(huán)境變量中聲明,啟動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時傳遞參數(shù),也可以直接修改gdbserver目錄下的Makefile文件中的環(huán)境變量CC)
沒有錯誤的話就在gdbserver目錄下生成gdbserver可執(zhí)行文件,注意此時要更改其屬性,否則可能會出現(xiàn)無法訪問的情況,chmod 777 gdbserver將其更改為任何人都可以讀寫執(zhí)行;使用arm-linux-strip命令處理一下gdbserver,將多余的符號信息刪除,可讓elf文件更精簡,通常在應(yīng)用程序的最后發(fā)布時使用;然后把它燒寫到flash的根文件系統(tǒng)分區(qū)的/usr/bin(在此目錄下,系統(tǒng)可以自動找到應(yīng)用程序,否則必須到gdbserver所在目錄下運行之),或通過nfs mount的方式都可以。只要保證gdbserver能在開發(fā)板上運行就行。
四、gdb+gdbserver nfs調(diào)試流程
下面就可以用gdb+gdbserver調(diào)試我們開發(fā)板上的程序了。在目標板上運行 gdbserver,其實就是在宿主機的minicom下。我是在minicom下#mount 192.168.2.100:/ /tmp后做的(這里參數(shù)-o nolock可以不加,不加這一步執(zhí)行得反而更快些),hello和gdbserver都是位于Linux根目錄下,把主機根目錄掛在到開發(fā)板的/tmp 目錄下。?
要進行g(shù)db調(diào)試,首先要在目標系統(tǒng)上啟動gdbserver服務(wù)。在gdbserver所在目錄下輸入命令:?
(minicom下)
#cd /tmp
#./gdbserver 192.168.2.100:2345 hello
192.168.2.100為宿主機IP,在目標系統(tǒng)的2345端口(你也可以設(shè)其他可用的值,當(dāng)然必須跟主機的gdb一致)開啟了一個調(diào)試進程,hello為要調(diào)試的程序(必須-g加入調(diào)試信息)。?
出現(xiàn)提示:?
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 “--host=i686-pc-linux-gnu,--target=arm-linux”...,如果不一致說明arm-linux-gdb有問題
說明此gdb在X86的Host上運行,但是調(diào)試目標是ARM代碼。
(gdb) target remote 192.168.2.223:2345
(192.168.2.223為開發(fā)板IP)
出現(xiàn)提示:?
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開啟的端口號一致,這樣才能進行通信。建立鏈接后,就可以進行調(diào)試了。調(diào)試在Host端,跟gdb調(diào)試方法相同。注意的是要用“c”來執(zhí)行命令,不能用“r”。因為程序已經(jīng)在Target Board上面由gdbserver啟動了。結(jié)果輸出是在Target Board端,用超級終端查看。連接成功,這時候就可以輸入各種GDB命令如list、run、next、step、break等進行程序調(diào)試了。?
以上針對通過nfs mount和tftp的方式,只能在主機上調(diào)試好后下載到開發(fā)板上運行,如果有錯誤要反復(fù)這個過程,繁瑣不說,有些程序只能在開發(fā)板上調(diào)試。所以筆者采用了gdbserver的遠程調(diào)試方式。希望對大家調(diào)試程序有用!
五、如何利用串口調(diào)試
如果你用串口1調(diào)試hello的話,你就要現(xiàn)在板子上運行命令:?
gdbserver hello /dev/ttyS0 (詳情可以參考gdbserver目錄下的readme文件)
這時gdbserver就在等待gdb的應(yīng)答信號了。?
然后在pc機上運行命令:?
xxx-linux-gdb hello?
在xxx-linux-gdb里敲入入下命令:?
set remotedevice /dev/ttyS0(這里設(shè)置串口1)?
set remote baud 9600 (這里設(shè)置串口波特率)?
set debug remote 1(可選)?
target remote /dev/ttyS0?
操作到這兒,gdb就應(yīng)該和gdbserver聯(lián)系上了。?
六、實戰(zhàn)調(diào)試
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
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
假設(shè) host pc ip:192.168.1.45
? ???board? ?ip:192.168.1.180? ??
將文件拷貝到目標板上:
先將gdbtest和gdbserver兩個文件拷貝到主機的/tftpboot目錄下,此時系統(tǒng)主機和目標機都必須能夠支持nfs
在目標板的Linux中運行:
#mount 192.168.1.108:/tftpboot /mnt/nfs
#cd /mnt/nfs
#ls
看是否有g(shù)dbtest和gdbserver兩個文件。
3.運行調(diào)試
client board:
#./gdbserver 192.168.1.45:1234 gdbtest??// 目標板上運行g(shù)dbtest 監(jiān)聽端口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,但是無此必要,可在環(huán)境變量中設(shè)置此路徑即可。
#copy gdbtest /usr/local/arm-gdb/bin/? ?// 將前面編譯的文件gdbtest拷貝到此目錄
#./arm-linux-gdb gdbtest
(gdb)target remote 192.168.1.180:1234? ?// 連接到開發(fā)板 成功后就可以
進行調(diào)試? ?? ?? ?? ???
(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函數(shù)
(gdb) next
(gdb) quit
建立連接后進行g(shù)db遠程調(diào)試和gdb本地調(diào)試方法相同
七、 linux下安裝gdbserver問題
toolchain version:? ?gdb的版本可能和交叉編譯器有很大的關(guān)系
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
本想繼續(xù)fix error,但是感覺不太對,請問各位,是什么原因呢?
是不是CC的target寫錯了?應(yīng)該是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@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
我已經(jīng)加了libthread_db.so.1共享庫為什么還打不開呢????共享庫和cpu類型有關(guān)嗎??
gdbserver: error while loading shared libraries: libthread_db.so.1: cannot open?
shared object file: No such file or director
****編譯GDB的時候搞成靜態(tài)的就好了.我想編譯選項里應(yīng)該有. 要不你就在Makefile里加上CFLAGS += -static
LDFLAGS += -static
這兩個的其中一個應(yīng)該就可以了,不過還是兩個都加上吧.
***/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 版本太高,需要內(nèi)核版本和交叉編譯器與之匹配?實在不行,就試試低版本的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
本文來自ChinaUnix博客,如果查看原文請點: http://blog.chinaunix.net/u2/88438/showart_1755820.html
GDB是GNU開源組織發(fā)布的一個強大的UNIX下的程序調(diào)試工具。或許,各位比較喜歡那種圖形界面方式的,像VC、BCB等IDE的調(diào)試,但如果你是在 UNIX平臺下做軟件,你會發(fā)現(xiàn)GDB這個調(diào)試工具有比VC、BCB的圖形化調(diào)試器更強大的功能。所謂“寸有所長,尺有所短”就是這個道理。一般來說,GDB主要幫忙你完成下面四個方面的功能:? ?? ?1、啟動你的程序,可以按照你的自定義的要求隨心所欲的運行程序。
? ???2、可讓被調(diào)試的程序在你所指定的調(diào)置的斷點處停住。(斷點可以是條件表達式)
? ???3、當(dāng)程序被停住時,可以檢查此時你的程序中所發(fā)生的事。
? ???4、動態(tài)的改變你程序的執(zhí)行環(huán)境。從上面看來,GDB和一般的調(diào)試工具沒有什么兩樣,基本上也是完成這些功能,不過在細節(jié)上,你會發(fā)現(xiàn)GDB這個調(diào)試工具的強大,大家可能比較習(xí)慣了圖形化的調(diào)試工具,但有時候,命令行的調(diào)試工具卻有著圖形化工具所不能完成的功能。讓我們一一看來。
一個調(diào)試示例
—————— 源程序:tst.c? ?? ? 1 #include?
? ?? ?2
? ?? ?3 int func(int n)
? ?? ?4 {
? ?? ?5? ?? ?? ? int sum=0,i;
? ?? ?6? ?? ?? ? for(i=0; i cc -g tst.c -o tst 使用GDB調(diào)試: hchen/test> gdb tst? ?
2
3? ?? ?? ?int func(int n)
4? ?? ?? ?{
5? ?? ?? ?? ?? ???int sum=0,i;
6? ?? ?? ?? ?? ???for(i=0; i
gdb+gdbserver方式進行ARM程序調(diào)試
【摘要】:本文首先介紹了gdb+gdbserver相關(guān)的概念,然后介紹了其下載、編譯、安裝等過程;接著介紹了利用gdb+gdbserver調(diào)試應(yīng)用程序的流程及實例等;最后分析了下gdb+gdbserver安裝過程中的常見問題。
【關(guān)鍵詞】:gdb,gdbserver,遠程調(diào)試
目錄
一、gdb+gdbserver總體介紹... 1
二、源代碼下載... 1
三、配置編譯及安裝下載... 1
四、gdb+gdbserver nfs調(diào)試流程... 2
五、如何利用串口調(diào)試... 3
六、實戰(zhàn)調(diào)試... 3
七、linux下安裝gdbserver問題... 5
一、gdb+gdbserver總體介紹
遠程調(diào)試環(huán)境由宿主機GDB和目標機調(diào)試stub共同構(gòu)成,兩者通過串口或TCP連接。使用 GDB標準程串行協(xié)議協(xié)同工作,實現(xiàn)對目標機上的系統(tǒng)內(nèi)核和上層應(yīng)用的監(jiān)控和調(diào)試功能。調(diào)試stub是嵌入式系統(tǒng)中的一段代碼,作為宿主機GDB和目標機調(diào)試程序間的一個媒介而存在。?
就目前而言,嵌入式Linux系統(tǒng)中,主要有三種遠程調(diào)試方法,分別適用于不同場合的調(diào)試工作:用ROM Monitor調(diào)試目標機程序、用KGDB調(diào)試系統(tǒng)內(nèi)核和用gdbserver調(diào)試用戶空間程序。這三種調(diào)試方法的區(qū)別主要在于,目標機遠程調(diào)試stub 的存在形式的不同,而其設(shè)計思路和實現(xiàn)方法則是大致相同的。?
而我們最常用的是調(diào)試應(yīng)用程序。就是采用gdb+gdbserver的方式進行調(diào)試。在很多情況下,用戶需要對一個應(yīng)用程序進行反復(fù)調(diào)試,特別是復(fù)雜的程序。采用GDB方法調(diào)試,由于嵌入式系統(tǒng)資源有限性,一般不能直接在目標系統(tǒng)上進行調(diào)試,通常采用gdb+gdbserver的方式進行調(diào)試。
二、源代碼下載
嵌入式Linux的GDB調(diào)試環(huán)境由Host和Target兩部分組成,Host端使用arm-linux-gdb,Target Board端使用gdbserver。這樣,應(yīng)用程序在嵌入式目標系統(tǒng)上運行,而gdb調(diào)試在Host端,所以要采用遠程調(diào)試(remote)的方法。進行GDB調(diào)試,目標系統(tǒng)必須包括gdbserver程序(在主機上正對硬件平臺編譯成功后下載到目標機上),宿主機也必須安裝GDB 程序。一般Linux發(fā)行版中都有一個可以運行的GDB,但開發(fā)人員不能直接使用該發(fā)行版中的GDB來做遠程調(diào)試,而要獲取GDB的源代碼包,針對arm 平臺作一個簡單配置,重新編譯得到相應(yīng)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
外網(wǎng)的ftp我經(jīng)常上不去,國內(nèi)常見的開源社區(qū)的下載頻道通常都有下載的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配置安裝路徑,當(dāng)然其他路徑也可以, .跟下面配置一致即可,須在環(huán)境變量中聲明,啟動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時傳遞參數(shù),也可以直接修改gdbserver目錄下的Makefile文件中的環(huán)境變量CC)
沒有錯誤的話就在gdbserver目錄下生成gdbserver可執(zhí)行文件,注意此時要更改其屬性,否則可能會出現(xiàn)無法訪問的情況,chmod 777 gdbserver將其更改為任何人都可以讀寫執(zhí)行;使用arm-linux-strip命令處理一下gdbserver,將多余的符號信息刪除,可讓elf文件更精簡,通常在應(yīng)用程序的最后發(fā)布時使用;然后把它燒寫到flash的根文件系統(tǒng)分區(qū)的/usr/bin(在此目錄下,系統(tǒng)可以自動找到應(yīng)用程序,否則必須到gdbserver所在目錄下運行之),或通過nfs mount的方式都可以。只要保證gdbserver能在開發(fā)板上運行就行。
四、gdb+gdbserver nfs調(diào)試流程
下面就可以用gdb+gdbserver調(diào)試我們開發(fā)板上的程序了。在目標板上運行 gdbserver,其實就是在宿主機的minicom下。我是在minicom下#mount 192.168.2.100:/ /tmp后做的(這里參數(shù)-o nolock可以不加,不加這一步執(zhí)行得反而更快些),hello和gdbserver都是位于Linux根目錄下,把主機根目錄掛在到開發(fā)板的/tmp 目錄下。?
要進行g(shù)db調(diào)試,首先要在目標系統(tǒng)上啟動gdbserver服務(wù)。在gdbserver所在目錄下輸入命令:?
(minicom下)
#cd /tmp
#./gdbserver 192.168.2.100:2345 hello
192.168.2.100為宿主機IP,在目標系統(tǒng)的2345端口(你也可以設(shè)其他可用的值,當(dāng)然必須跟主機的gdb一致)開啟了一個調(diào)試進程,hello為要調(diào)試的程序(必須-g加入調(diào)試信息)。?
出現(xiàn)提示:?
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 “--host=i686-pc-linux-gnu,--target=arm-linux”...,如果不一致說明arm-linux-gdb有問題
說明此gdb在X86的Host上運行,但是調(diào)試目標是ARM代碼。
(gdb) target remote 192.168.2.223:2345
(192.168.2.223為開發(fā)板IP)
出現(xiàn)提示:?
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開啟的端口號一致,這樣才能進行通信。建立鏈接后,就可以進行調(diào)試了。調(diào)試在Host端,跟gdb調(diào)試方法相同。注意的是要用“c”來執(zhí)行命令,不能用“r”。因為程序已經(jīng)在Target Board上面由gdbserver啟動了。結(jié)果輸出是在Target Board端,用超級終端查看。連接成功,這時候就可以輸入各種GDB命令如list、run、next、step、break等進行程序調(diào)試了。?
以上針對通過nfs mount和tftp的方式,只能在主機上調(diào)試好后下載到開發(fā)板上運行,如果有錯誤要反復(fù)這個過程,繁瑣不說,有些程序只能在開發(fā)板上調(diào)試。所以筆者采用了gdbserver的遠程調(diào)試方式。希望對大家調(diào)試程序有用!
五、如何利用串口調(diào)試
如果你用串口1調(diào)試hello的話,你就要現(xiàn)在板子上運行命令:?
gdbserver hello /dev/ttyS0 (詳情可以參考gdbserver目錄下的readme文件)
這時gdbserver就在等待gdb的應(yīng)答信號了。?
然后在pc機上運行命令:?
xxx-linux-gdb hello?
在xxx-linux-gdb里敲入入下命令:?
set remotedevice /dev/ttyS0(這里設(shè)置串口1)?
set remote baud 9600 (這里設(shè)置串口波特率)?
set debug remote 1(可選)?
target remote /dev/ttyS0?
操作到這兒,gdb就應(yīng)該和gdbserver聯(lián)系上了。?
六、實戰(zhàn)調(diào)試
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
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
假設(shè) host pc ip:192.168.1.45
? ???board? ?ip:192.168.1.180? ??
將文件拷貝到目標板上:
先將gdbtest和gdbserver兩個文件拷貝到主機的/tftpboot目錄下,此時系統(tǒng)主機和目標機都必須能夠支持nfs
在目標板的Linux中運行:
#mount 192.168.1.108:/tftpboot /mnt/nfs
#cd /mnt/nfs
#ls
看是否有g(shù)dbtest和gdbserver兩個文件。
3.運行調(diào)試
client board:
#./gdbserver 192.168.1.45:1234 gdbtest??// 目標板上運行g(shù)dbtest 監(jiān)聽端口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,但是無此必要,可在環(huán)境變量中設(shè)置此路徑即可。
#copy gdbtest /usr/local/arm-gdb/bin/? ?// 將前面編譯的文件gdbtest拷貝到此目錄
#./arm-linux-gdb gdbtest
(gdb)target remote 192.168.1.180:1234? ?// 連接到開發(fā)板 成功后就可以
進行調(diào)試? ?? ?? ?? ???
(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函數(shù)
(gdb) next
(gdb) quit
建立連接后進行g(shù)db遠程調(diào)試和gdb本地調(diào)試方法相同
七、 linux下安裝gdbserver問題
toolchain version:? ?gdb的版本可能和交叉編譯器有很大的關(guān)系
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
本想繼續(xù)fix error,但是感覺不太對,請問各位,是什么原因呢?
是不是CC的target寫錯了?應(yīng)該是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@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
我已經(jīng)加了libthread_db.so.1共享庫為什么還打不開呢????共享庫和cpu類型有關(guān)嗎??
gdbserver: error while loading shared libraries: libthread_db.so.1: cannot open?
shared object file: No such file or director
****編譯GDB的時候搞成靜態(tài)的就好了.我想編譯選項里應(yīng)該有. 要不你就在Makefile里加上CFLAGS += -static
LDFLAGS += -static
這兩個的其中一個應(yīng)該就可以了,不過還是兩個都加上吧.
***/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 版本太高,需要內(nèi)核版本和交叉編譯器與之匹配?實在不行,就試試低版本的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
本文來自ChinaUnix博客,如果查看原文請點: http://blog.chinaunix.net/u2/88438/showart_1755820.html
總結(jié)
以上是生活随笔為你收集整理的gdb的简单使用和gdb+gdbserver方式进行ARM程序调试的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LINUX操作系统手机刷机包制作、修改方
- 下一篇: diff patch制作补丁打补丁