嵌入式Linux系統的GDB遠端偵錯實踐

來源:互聯網
上載者:User

   嵌入式Linux系統的GDB遠端偵錯實踐
摘要嵌入式Linux系統的研究和應用越來越熱針對如何完成系統調試工作的問題文章介紹了GDB遠端偵錯功能及其工作機制重點描述了使用GDB遠端偵錯技術在嵌入式Linux系統中調試各類程式的實踐樣本
1 引言

息技術迅猛發展個人數位助理掌上型電腦機頂盒等嵌入式產品成為市場熱點
Linux繼在案頭系統取得巨大成功之後又以其開放源碼容易定製和擴充多硬體平台支援和內建網路功能等優良秉性逐漸成為嵌入式系統的研究熱點和廣泛使用的
系統平台在嵌入式Linux系統中使用GDB(GNU
Debugger)的強大調試能力開發人員可以避免使用的價格昂貴的模擬器工具來跟蹤和偵錯工具由於嵌入式系統的軟硬體資源有限一般不可能在系統本地建立
GDB調試環境而是使用遠端偵錯這一GDB進階功能在宿主機上靈活地對運行在目標平台上的程式進行跟蹤調試
2 GDB的遠端偵錯功能
GDB是GNU免費提供的調試除錯工具可以用於C C++ Pascal和 Fortran等程式的跟蹤調試在嵌入式Linux系統中開發人員能夠在宿主機上使用GDB方便地以遠端偵錯的方式逐步執行目標平台上的程式碼設定斷點查看記憶體並同目標平台交換資訊
使
用GDB進行遠端偵錯時運行在宿主機上的GDB通過串口或TCP串連與運行在目標機上的調試插樁stub以GDB標準遠程串列協議協同工作從而實現對目標
機上的系統核心和上層應用的監控和調試功能調試stub是嵌入式系統中的一段代碼作為宿主機GDB和目標機偵錯工具間的一個媒介而存在GDB遠端偵錯結構
1所示 stub作業系統目標機上層應用宿主機GDB作業系統標準遠程串列協議
圖1 GDB遠端偵錯結構
為了監控和偵錯工具主機
GDB通過串列協議使用記憶體讀寫命令無損害地將目標程式原指令用一個Trap指令代替完成斷點設定動作當目標系統執行該Trap指令時stub可以順利獲
得控制權此時主機GDB就可以通過stub來跟蹤和偵錯目標機程式了調試stub會將當前情境傳送給主機GDB然後接收其控制命令stub按照命令在目標
系統上進行相應動作從而實現逐步執行讀寫記憶體查看寄存器內容顯示變數值等調試功能
GDB遠程串列協議是一種基於訊息的ASCII碼協議它定義讀寫資料的資訊控制被調試的程式並報告運行程式的狀態這些功能在目標機方由stub的相關功能函數實現而宿主機方則由GDB源檔案remote.c中的功能程式碼完成協議交換資料的格式如下
$<data>#[chksum]
其中<data>是ASCII碼十六進位字串[chksum]是一個位元組的十六進位校正和當發送資訊時接收方響應如下
+ 接收資料校正正確且接收方準備好接收下一個資料包
- 接收資料校正不正確發送方必須重發資料包
調試stub響應主機GDB資料的方式有兩種若訊息傳送正確則回送響應資料或OK否則返回由目標平台自己定義的錯誤碼並由GDB控制台向使用者報告通訊資料中的<data>包括了非常豐富的遠端偵錯的操作指令和狀態資訊完整的定義資訊可參考
GDB參考文檔的info-14中GDB Remote Serial Protocol 部分
3 遠端偵錯實踐

程調試環境由宿主機GDB和目標機調試stub共同構成兩者通過串口或TCP串連使用GDB標準遠程串列協議協同實現遠端偵錯功能宿主機環境的設定比較簡
單只要有一個可以運行GDB的系統內容一般選擇一個較好的Linux發行版即可但要注意開發人員不能直接使用該發行版中的GDB來做遠端偵錯而要擷取
GDB的源檔案包針對特定目標平台做一個簡單配置重新編鏈得到相應GDB
host> cd /tmp/gdb-5.2.1
host> ./configure --target=……
host> make
host> cp /tmp/gdb-5.2.1/gdb/gdb /usr/bin

中configure命令的target參數就指定了目標機的類型開發人員可根據所用目標平台從GDB說明文檔擷取該參數值這樣宿主機遠端偵錯環境就建立
好了剩下就是目標機stub的實現具體環境中目標stub的實現和使用方式則與硬體平台和應用場合相關就目前而言嵌入式Linux系統中主要有三種遠程調
試方法分別適用於不同場合的調試工作用ROM
Monitor偵錯目標機程式用KGDB調試系統核心和用GDBserver調試使用者空間程式這三種調試方法的區別主要在於目標機遠端偵錯stub的存在
形式的不同而其設計思路和實現方法則是大致相同的
3.1用ROM Monitor偵錯目標機程式
嵌入式Linux系統在核心運行前的狀態
中程式的裝載運行和調試一般都由ROM Monitor實現系統一加電包含了遠端偵錯stub的ROM
Monitor首先獲得系統控制權對CPU記憶體中斷串口網路等重要資源和外設進行初始化然後就可以下載運行和監控目標程式碼封裝括核心的裝載和引導也由它完成
基於ARM平台的嵌入式Linux系統中最常用的RedBootRed Hat Embedded Debug and
Bootstrap是一款功能相當強大的系統引導調試和管理工具其中包含了GDB遠端偵錯stub的完整實現串口和以太口的驅動TCP/IP相關協議的實
現目標系統的啟動和Flash裝置的管理等功能核心運行之前用RedBoot下載並偵錯目標機程式armboot的一個執行個體會話如下
目標板加電RedBoot運行在提示符下按’$’鍵進入調試stub狀態
ARM eCos // 部分RedBoot啟動資訊
RedBoot(tm) debug environment - built 15:49:04, Mar 27 2002
Copyright (C) 2000, Red Hat, Inc. ……
RedBoot> // 按’$’鍵進入調試stub狀態
RedBoot> Entering debug mode using GDB and stubs
宿主機運行GDB實現程式的下載和調試
[root@Host armboot-1.1.0]# gdb armboot
GNU gdb 5.2.1 // 部分GDB啟動資訊
Copyright 2002 Free Software Foundation, Inc.
Configured as "--host=i686-pc-linux-gnu --target=arm-pxa-linux-gnu"...
(gdb) set remotebaud 115200 // 設定串口傳輸速率
(gdb) target remote /dev/ttyS0 // 通過串口1串連目標機
Remote debugging using /dev/ttyS0
0x0000e2b8 in ?? ()
(gdb) load // 下載目標代碼至目標機記憶體
Loading section .text, size 0xbef8 lma 0xa3000000
Loading section .rodata, size 0x2f84 lma 0xa300bef8
Loading section .data, size 0xd24 lma 0xa300ee7c
Start address 0xa3000000, load size 64416
Transfer rate: 85888 bits/sec, 298 bytes/write.
(gdb) list serial.c:75 // 查看原始碼
70 */
71 void serial_init(bd_t *bd)
72 {
73 const char *baudrate;
74
75 if ((baudrate = getenv(bd, "baudrate")) != 0)
76 bd->bi_baudrate = simple_strtoul(baudrate, NULL, 10);
77
78 serial_setbrg(bd, bd->bi_baudrate);
79 }
(gdb) break 75 // 設定斷點
Breakpoint 1 at 0xa300b964: file serial.c, line 75.
(gdb) continue // 運行目標機程式至斷點處
Continuing.
Breakpoint 1, serial_init (bd=0xa30312e4) at serial.c:75
75 if ((baudrate = getenv(bd, "baudrate")) != 0)
(gdb) display baudrate // 顯示變數baudrate當前值
1: baudrate = 0xa30312e4 ""
(gdb) next // 跟蹤baudrate變數值
76 bd->bi_baudrate = simple_strtoul(baudrate, NULL, 10);
1: baudrate = 0xa300f392 "115200"
(gdb)
開發人員可以依靠GDB提供的強大調試和監控功能對運行在目標板上的程式進行即時跟蹤清晰地查看程式所使用的目標板資源的狀態如CPU寄存器記憶體值等等
3.2 用KGDB調試系統核心

統核心與硬體體系關係密切因而其調試stub的實現也會因具體目標平台的差異而存在一些不同嵌入式Linux的開源社區和開發團體針對大多數流行的目標平
台對Linux核心遠端偵錯stub給予了實現並以源碼補丁形式發布開發人員只需正確編鏈打好補丁的核心就可對核心代碼進行靈活的調試PC平台Linux
核心開發人員所熟知的KGDBRemote Kernel
Debugger就是這種實現形式該方法也同樣用在嵌入式Linux系統中如MontaVista的Deepak
Saxena主持開發的核心調試補丁就能夠很好地完成IOP3xxADI和IXP系列的目標平台上Linux核心的調試一個通過串口以遠程方式跟蹤
do_fork()核心功能的大致情境如下
(gdb) set remotebaud 115200 // 設定串口傳輸速率
(gdb) target remote /dev/ttyS0 // 通過串口1串連遠程目標
Remote debugging using /dev/ttyS0
……
(gdb) continue // 串連成功開始核心的啟動
Continuing.
Memory clock: 99.53MHz (*27) // 核心啟動資訊
Run Mode clock: 99.53MHz (*1)
……
VFS: Mounted root (nfs filesystem).
Freeing init memory: 76K
Program received signal SIGTRAP, // 中斷核心的運行以便設定斷點
Trace/breakpoint trap.
……
(gdb) list fork.c:622 // 查看核心原始碼
617 p->did_exec = 0;
618 p->swappable = 0;
619 p->state = TASK_UNINTERRUPTIBLE;
620
621 copy_flags(clone_flags, p);
622 p->pid = get_pid(clone_flags);
623
624 p->run_list.next = NULL;
625 p->run_list.prev = NULL;
626
(gdb) break 622 // 設定斷點
Breakpoint 1 at 0xc0116d50: file fork.c, line 622.
(gdb) continue // 恢複核心的運行直至斷點
Continuing.
Breakpoint 1, do_fork (clone_flags=17, stack_start=3221223548, regs=0xc7153fc4, stack_size=0) at fork.c:622
622 p->pid = get_pid(clone_flags);
(gdb) display p->pid // 顯示變數p->pid當前值
1: p->pid = 1152
(gdb) next 3 // 跟蹤get_pid()函數返回後變數p->pid的變化
624 p->run_list.next = NULL;
1: p->pid = 1181
(gdb) delete 1 // 刪除斷點
(gdb) continue // 恢複核心的運行
Continuing.
GDB的調試功能非常豐富和強大上例所示只是GDB遠端偵錯在系統核心調試中的一個最簡單的應用開發人員可以使用GDB提供的眾多功能對核心進行強有力的跟蹤調試
3.3 用GDBserver調試使用者空間程式
在Linux
核心已經正常啟動並執行基礎上使用GDBserver作為遠端偵錯stub的實現開發人員可以在宿主機上用GDB方便地監控目標機使用者空間程式的運行
GDBserver是GDB內建的針對使用者程式的遠端偵錯stub它具有良好的可移植性可交叉編譯到多種目標平台上運行因為有作業系統的支援它的實現要比
一般的調試stub簡單很多但作為以遠程方式調試使用者程式的目標方正是它的用武之處下面給出主機gdb和目標機gdbserver以TCP方式遠端偵錯目
標平台MiniGUI HelloWorld程式的會話過程其中192.195.150.140是宿主機192.195.150.164為目標機
目標機
[root@l2x target]# gdbserver 192.195.150.140:2345 mginit
Process mginit created: pid=72 // 等待宿主機串連
宿主機
[root@l2x host]# gdb mginit
…… // GDB版本配置資訊
(gdb) target remote 192.195.150.164:2345 // TCP方式串連目標機
Remote debugging using 192.195.150.164:2345
0x40002a90 in ?? () // 串連成功
目標機
Remote debugging from host 192.195.150.140 // 宿主機串連成功
宿主機
(gdb) break mginit.c:73 //設定斷點
Breakpoint 1 at 0x8bfc: file mginit.c, line 73.
(gdb) continue // 運行程式至設定斷點處
Continuing.
Breakpoint 1, MiniGUIMain (args=1, arg=0xbffffe14) at mginit.c:73
73 hMainWnd = CreateMainWindow (&CreateInfo);
(gdb) display CreateInfo // 查看變數
1: CreateInfo = {dwStyle = 671088640, spCaption = 0x8cd8 "Hello, world!",… }
(gdb) c // 運行至程式結束
Continuing.

Program exited normally. // 程式正常退出
目標機
Child exited with retcode = 0 // 程式運行返回
Child exited with status = 14 // 程式退出狀態
GDBserver exiting. // 聯調結束

開發嵌入式系統上層應用時由於宿主機和目標機的軟硬體環境存在或多或少的差異所以開發人員在宿主機上類比調通的程式往往並不能很好地運行於目標平台上運用
上述遠端偵錯方法則可以減少對類比調試的依賴在主機上以遠程方式像調試本地程式一樣十分方便地直接對運行在目標平台的程式進行監控調試從而提高開發品質和
效率縮短嵌入式系統應用的開發週期特別值得一提的是這種方式對於嵌入式GUI系統的調試是非常方便的宿主機運行調試器目標機運行待調試的GUI系統兩者在
各自的控制台處理輸入輸出互不干擾以串口或TCP方式進行通訊共同完成對GUI系統的調試這種調試工具和圖形系統與開發人員的同步互動在單機調試環境中實
現起來是比較麻煩的不僅需要虛擬圖形裝置以支援圖形系統的輸入輸出如Qt圖形庫中的QVFB就是一個虛擬FrameBuffer而且調試工具與圖形系統
間的互動則要通過Xterm等終端工具實現調試環境的搭建和調試的具體實施較為繁瑣但是效果卻不如遠端偵錯好
4 結束語
在嵌入式
Linux系統開發中GNU工具鏈是一個很好的選擇不但提供了對各種流行嵌入式處理器的良好支援而且開發人員可免費使用使得系統開發成本大大降低GNU工
具鏈中的GDB更是以其遠端調試方式適應了嵌入系統的特殊調試要求在實際開發中得到了最廣泛的應用我們在一款ARM系列實驗開發板上做嵌入式Linux
系統時就使用文章所述的GDB遠端偵錯方法很好的完成了核心運行前的代碼核心代碼核心基礎上使用者空間代碼的調試工作系統開發的工作效率得到了質的提高 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.