|
|
鄒思軼(syzou),西南交通大學在讀研究生整理提供<BR> 1. 概論<BR> 我們將學習使用gdb來調試通過一個通過串行線同PC相連的嵌入式系統(tǒng).<BR> Gdb可以調試各種程序,包括C、C++、JAVA、PASCAL、FORAN和一些其它的語言。包括GNU所支持的所有微處理器的匯編語言。<BR> 在gdb的所有可圈可點的特性中,有一點值得注意,就是當運行gdb的平臺(宿主機)通過串行端口(或網(wǎng)絡連接,或是其他別的方式)連接到目標板時(應用程序在板上運行),gdb 可以調試對應用程序進行調試。這個特性不光在將GNU工具移植到一個新的操作系統(tǒng)或微處理器時侯很有用,對于那些使用GNU已經(jīng)支持的芯片的嵌入式系統(tǒng)進行開發(fā)的設計人員來講,也是非常有用的。<BR> 當gdb被適當?shù)募傻侥硞嵌入式系統(tǒng)中的時候,它的遠程調試功能允許設計人員一步一步的調試程序代碼、設置斷點、檢驗內存,并且同目標交換信息。Gdb同目標板交換信息的能力相當強,勝過絕大多數(shù)的商業(yè)調試內核,甚至功能相當于某些低端仿真器。</P><P> 2.Gdb在嵌入式領域的功能實現(xiàn)<BR> 當調試一個遠端目標設備時,gdb依靠了一個調試stub來完成其功能。調試stub即是嵌入式系統(tǒng)中一小段代碼,它提供了運行gdb的宿主機和所調試的應用程序間的一個媒介。<BR> Gdb和調試stub通過GDB串行協(xié)議進行通信。GDB串行協(xié)議是一種基于消息的ASCII碼協(xié)議,包含了諸如讀寫內存、查詢寄存器、運行程序等命令。由于絕大多數(shù)嵌入式系統(tǒng)設計人員為了最好的利用他們手中特定的硬件的特征,總是自己編寫自己的stub。所以我們有必要清楚的了解一下gdb的串行通信協(xié)議。在后面我們會詳細介紹。</P><P> 為了設置斷點,gdb使用內存讀寫命令,來無損害地將原指令用一個TRAP命令或其它類似的操作碼(在此假定,被調試的應用程序是處在RAM中的,當然,如果stub有足夠好的性能,硬件也不錯的話,這個條件也不是必須的)代替,使得執(zhí)行該命令時,可以使得控制權轉移到調試stub手中去。在此時,調試stub的任務就是將當前場景傳送給gdb(通過遠程串行通信協(xié)議),然后從gdb處接收命令,該命令告訴了stub下一步該做什么。</P><P> 為了說明,下面的代碼是Hitachi SH-2處理器的一個TRAP異常處理程序:</P><P> /*將當前寄存器的值存儲到堆棧中*/<BR> /* 然后調用gdb_exception. */<BR> asm("<BR> .global _gdb_exception_32<BR> _gdb_exception_32:</P><P> /* 將堆棧指針和r14壓入堆棧*/<BR> mov.l r15, @-r15<BR> mov.l r14, @-r15</P><P> /*當執(zhí)行一個陷阱異常時,sh2 自動的將pc 和sr 放入堆棧 */<BR> /*所以我們必須調整我們給gdb的堆棧指針值,以此來說明這個特別的數(shù)據(jù) */<BR> /* 換言之,在該陷阱被執(zhí)行前,gdb想看看堆棧指針的值,*/<BR> /* 而不是陷阱被執(zhí)行當前時的值。*/<BR> /*所以,從我們剛壓入堆棧的sp值中減去8*/<BR> /*(pc和sr都是4個字節(jié)的 )*/</P><P> mov.l @(4,r15), r14<BR> add #8, r14<BR> mov.l r14, @(4,r15)</P><P> /*將其它寄存器值壓入堆棧 */<BR> mov.l r13, @-r15<BR> mov.l r12, @-r15<BR> mov.l r11, @-r15<BR> mov.l r10, @-r15<BR> mov.l r9, @-r15<BR> mov.l r8, @-r15<BR> mov.l r7, @-r15<BR> mov.l r6, @-r15<BR> mov.l r5, @-r15<BR> mov.l r4, @-r15<BR> mov.l r3, @-r15<BR> mov.l r2, @-r15<BR> mov.l r1, @-r15<BR> mov.l r0, @-r15<BR> sts.l macl, @-r15<BR> sts.l mach, @-r15<BR> stc vbr, r7<BR> stc gbr, r6<BR> sts pr, r5</P><P> /* 調用gdb_exception, 令其異常值=32 */<BR> mov.l _gdb_exception_target, r1<BR> jmp @r1<BR> mov #32, r4</P><P> .align 2<BR> _gdb_exception_target: .long _gdb_exception<BR> ");</P><P> /* 下面是一個從調試stub返回對某個應用程序的控制的樣例(針對Hitachi SH2)*/<BR> /*如果用C語言寫,那么該語句的原型為:*/<BR> /* void gdb_return_from_exception( gdb_sh2_registers_T registers );*/<BR> /* 總而言之,我們可以用同gdb_exception_nn把寄存器壓入堆棧同樣的方式*/<BR> /* 將其從堆棧中彈出。然而,通常返回指針同我們的返回堆棧指針不一樣。*/<BR> /*所以如果我們在拷貝pc和sr到返回指針之前將r15彈出的話,我們就回*/<BR> 丟失掉pc和sr。<BR> */ <BR> asm("<BR> .global _gdb_return_from_exception<BR> _gdb_return_from_exception:</P><P> /*恢復某些寄存器*/<BR> lds r4, pr<BR> ldc r5, gbr<BR> ldc r6, vbr<BR> lds r7, mach<BR> lds.l @r15+, macl<BR> mov.l @r15+, r0<BR> mov.l @r15+, r1<BR> mov.l @r15+, r2<BR> mov.l @r15+, r3<BR> mov.l @r15+, r4<BR> mov.l @r15+, r5<BR> mov.l @r15+, r6<BR> mov.l @r15+, r7<BR> mov.l @r15+, r8<BR> mov.l @r15+, r9<BR> mov.l @r15+, r10<BR> mov.l @r15+, r11<BR> mov.l @r15+, r12</P><P> /* 將pc和 sr彈出到應用程序的堆棧*/<BR> mov.l @(8,r15), r14<BR> mov.l @(16,r15), r13<BR> mov.l r13, @-r14<BR> mov.l @(12,r15), r13<BR> mov.l r13, @-r14</P><P> /* 完成恢復寄存器的工作*/<BR> mov.l @r15+, r13<BR> mov.l @r15+, r14<BR> mov.l @r15, r15</P><P> /*調整應用程序的堆棧,來說明pc, sr */<BR> add #-8, r15</P><P> /* ...返回到應用程序*/<BR> rte<BR> nop<BR> ");</P><P> <BR> 當處理器遇到了一個TRAP指令(該指令是由gdb 設置的,做斷點用)時,該指令使得處理器的當前場景轉向一個名為gdb_exception()的函數(shù)。最終,目標調用了gdb_return_from_exception()函數(shù),該函數(shù)恢復了處理器的場景并將控制權交給應用程序。</P><P> 遠程串行協(xié)議的步進命令稍微更有挑戰(zhàn)性些,特別當目標處理器不提供一個"跟蹤位"或類似的功能時。在這些情況下,唯一的替代辦法就是讓stub把將要執(zhí)行的指令反匯編。這樣它就會知道程序下一步要執(zhí)行到何處。<BR> 幸運的是,在gdb的源代碼中也提供了關于如何一些實現(xiàn)這些步近命令的建議。對于Hitachi SH-2芯片而言,在gdb/sh-stub.c文件中說明了函數(shù)doSStep()的使用,對于其它種類的芯片,函數(shù)的名字也差不多,請看文件gdb/i386-stub.c和gdb/m68k-stub.c</P><P> 3.gdb的其它功能 <BR> Gdb還可以求解在控制臺中輸入的任意的C表達式的值,包括包含有對遠端目標的函數(shù)功能調用的表達式。我們可以輸入如下命令:</P><P> print foo( sh_sci[current_sci]->smr.brg )</P><P> gdb就會將mr.brg的值傳送給foo(),并報告其返回值。<BR> 當然,gdb也可以反匯編代碼。只要可能的話,它還可以很好的為所需的數(shù)據(jù)提供等價的符號信息。例如,gdb用下列輸出:</P><P> jmp 0x401010 <main + 80></P><P> 告訴了我們,所顯示的地址與從函數(shù)main()的起始地址起偏移80個字節(jié)的地址相等。<BR> Gdb 可以顯示其自身和所調試的目標間的遠程串行調試信息,也可以將該信息記錄到日志文件中去。這些特性對于我們調試一個新的stub,了解stub是如何使用遠程串行協(xié)議來實現(xiàn)用戶對數(shù)據(jù)、程序內存、系統(tǒng)調用等等的需求是十分有用的。</P><P> Gdb擁有腳本語言,允許對目標自動的設置和檢測。該語言是對目標處理器獨立的,所以應用程序從一個目標處理器移植到另外的處理器時,腳本可以重用。</P><P> 最后,gdb還提供了跟蹤點的功能,該功能可以記錄某個運行程序的信息,而盡可能的不打斷程序收集數(shù)據(jù)。跟蹤點需要特別的調試stub來實現(xiàn)。 </P><P> 4.一個典型的gdb會話過程<BR> 現(xiàn)在我們已經(jīng)探討了gdb的通用功能,現(xiàn)在我們來看看gdb的執(zhí)行。下面給出了一個典型的gdb 調試會話過程。在該過程中,gdb初始化了同一個運行調試stub的遠端目標間的通信,然后下載程序,設置斷點,并運行該程序。當遇到斷點時,調試stub通知gdb,gdb然后就將其源代碼行顯示給用戶。接著,用戶顯示了一個變量,步近執(zhí)行一個指令,然后推出gdb 。<BR> 請注意,下面并未顯示用戶在使用gdb時所見到的內容。用戶所見到的是一個終端,顯示的內容都是用英文寫成的源代碼、要顯示的變量等等。但是,下面顯示的腳本說明了當用戶鍵入命令時在幕后發(fā)生的內容。 </P><P> 典型的gdb會話過程的描述</P><P> <br><A HREF="/editor/uploadfiles/learns01/200382910381371880.jpg" TARGET=_blank><IMG SRC="/editor/uploadfiles/learns01/200382910381371880.jpg" border=0 alt=按此在新窗口瀏覽圖片 onload="javascript:if(this.width>580)this.width=580"></A><BR> <br><A HREF="/editor/uploadfiles/learns01/200382910384964469.jpg" TARGET=_blank><IMG SRC="/editor/uploadfiles/learns01/200382910384964469.jpg" border=0 alt=按此在新窗口瀏覽圖片 onload="javascript:if(this.width>580)this.width=580"></A></P><P> 上圖中,左邊一欄顯示了gdb控制臺的一部分。在此用戶鍵入命令并監(jiān)視數(shù)據(jù)。右邊一欄顯示了一些使用GDB遠程串行協(xié)議在宿主機和嵌入式設備之間的通信消息。在方括號中是一些解釋信息。如果想清楚的了解這些信息的含義,請見附錄《GDB遠程串行協(xié)議》部分。</P><P> 5.Gdb調試stub的源代碼<BR> 雖然遠程軟件調試具有依賴于目標的特性,但是還是可以創(chuàng)建一個有高度的可移植性的調試stub,在不同的嵌入式處理器芯片之間可以被重用,而所需的修改最小。<BR> 有人已經(jīng)嘗試了這方面的工作。如果各位感興趣,可以去上網(wǎng)查閱相關的資料。例如<img align=absmiddle src=pic/url.gif border=0><a target=_blank href=http://sourceforge.net/projects/gdbstubs> http://sourceforge.net/projects/gdbstubs</a>。</P><P> 處理器特定的代碼包含在與處理器相關的文件名中,例如gdb_sh2*.c。我們可以針對我們特定的處理器下載相關的文件(例如gdb_m68k*.c),然后在用其替代我們機器上的相關內容。</P><P> 6.關于改造gdb來解決特定問題的考慮<BR> gdb使用了一個模塊化的體系結構來實現(xiàn),那么對它某些不適合我們需要的特性就可以很直接的加以處理。例如,如果我們的產品僅僅有一個通信端口,而它使用的并不是gdb的通信協(xié)議的話,那么,可以修改gdb,使得調試器的信息同我們產品已經(jīng)使用的信息包相匹配。</P><P> 類似地,如果我們的產品沒有串行端口,而有些別的通信接口(例如CAN端口),那么我們可以加強gdb的遠程通信功能,來適應該端口。<BR> 我們也可以修改gdb的工作方式使其同我們嵌入式應用程序更加的相容。例如,如果我們正在使用TRAPA #32來做些同gdb無關的工作,我們就可以改變gdb為了設置斷點而使用的操作碼,或者我們可以使用gdb來產生一個新的消息告訴我們的目標板開啟指令追蹤的功能或使能芯片內的斷點產生硬件。<BR> 文件gdb/remote.c包含了gdb的遠程串行協(xié)議的實現(xiàn)過程。對于研究gdb的模塊化的實現(xiàn)是如何允許我們快速的將其改造以適應特定的調試目標而言,該文件是個很好的起點。其它的文件,例如gdb/remote-hms.c 和gdb/remote-e7000.c,使用了該模塊化的結構來為諸如Hitachi, Motorola等公司的芯片的調試器和仿真器提供支持。<BR> 7.總結<BR> gdb對于調試目標(包括對其內存的使用,通信媒介等等方面)的可適應性使得它對于目標板的調試而言,常常是唯一的選擇?紤]到單芯片高集成度、基于IP的嵌入式產品的普及,情況更是如此。在今天,嵌入式設備的復雜性與日俱增,在進行新的設計時,其供選擇的技術的選擇也越來越多,要找到一個商業(yè)的開發(fā)產品是越來越困難了。<BR> 而使用GNU工具將是個很好的選擇。GNU工具對各種流行的嵌入式處理器的支持意味著,當我們正在使用的開發(fā)工具對我們將要在下一個設計中使用的處理器不支持時,我們可以減少尋找新的開發(fā)工具所帶來的危險。<BR>
|
|
狀 態(tài):
離線
公司簡介
產品目錄
|
|
公司名稱:
|
中華工控網(wǎng)
|
聯(lián) 系 人: |
客服中心
|
電 話: |
0755-26546361
|
傳 真: |
0755-26585268 |
地 址: |
深圳市南山區(qū)創(chuàng)業(yè)路現(xiàn)代城華庭1棟6A |
郵 編: |
518054 |
主 頁: |
|
|
|
|
|