GDB Remote Serial Protocol —— RSP协议解析
簡介
GDB Remote Serial Protocol——GDB的標準遠程通信協議。
當你已經熟悉你的處理器是如何處理斷點和其他異常時,再了解一點基本的遠程穿行通信協議的知識,你就可以在你的嵌入式平臺上實現與主機GDB的通信。(即遠程調試)
協議定義
GDB RemoteSerial Protocol(RSP)是一種簡單的,通過串口線、網絡等至少支持半雙工通信的媒介進行ASCII消息傳輸的協議。
RSP包以$符號作為數據包的開始,后跟一個或多個用于組成要發送的消息的ASCII字節,并以#作為數據包的結束。再#后,還有兩個16進制的ASCII字符作為要發送的消息的校驗和。一個完整的RSP協議數據包如下:
$m4015bc,2#5a
消息的接收方會立即返回‘+’表示正確接收數據,或‘-’表示沒有正確接收數據。當返回‘-’時,GDB會將錯誤碼返回給用戶,并無條件掛起GDB進程。
目標機按接收到的指令次序,依次將信息輸出在GDB的console中。除非GDB進程中有其他的命令正在執行,否則來自目標機的信息將會在任意時刻輸出在console中。
RSP必須實現的命令
根據功能劃分,可將GDB發送來的信息,分成三種命令:寄存器相關(register-)、內存相關(memory-based)和程序控制命令。
寄存器相關
主要是對寄存器進行讀、寫操作。
讀寄存器組:(“g”)
eg:$g#67
當GDB想獲取當前目標機的寄存器信息時,就會像目標機發送(“g”)命令,目標機會返回如下信息:
+$123456789abcdef0…#xx
(Register 0 的值為0x12345678,1 的值為0xabcdef0….等等)
目標機根據平臺的大小端返回相應的字節流,關于大小端的定義,可以在目標平臺的gdb宏文件中找到,eg:gdb/config/<arch>tm-<arch>.h (不同版本可能不一樣,我就沒找到)
寫寄存器組:(“G”)
eg:$G123456789abcdef0…#xx
(設置register0 的值為0x12345678,1 為 0xabcdef0…等等)
使用這個命令,GDB會在程序恢復運行前,按照平臺的字節序將數據存儲在相應的寄存器中。同時目標平臺也會回應給GDB反饋信息,如成功返回+$OK#9a。
寫寄存器:(“P”)
eg:$p10=0040149c#b3
(設置16號寄存器的值為0x40149c)
當GDB僅僅想設置一個或二個寄存器時,GDB會發送這條指令(代替(“G”)命令)給目標機。寄存器的號與讀寫寄存器組的號是一樣的。同時,若成功,目標機會返回+$OK#9a。
內存相關
讀內存:(“m”)
eg: $4015bc,2#5a
(從0x4015bc這個地址開始讀2個字節的數據)
GDB發送的讀命令會確定局部變量和全局變量的值,并用斷點指令替代opcode,及其他用戶需要的信息。GDB是知道目標平臺的大小端的,因此目標機只需返回字符流即可,GDB會適當的對它們進行重組。
目標機的調試樁根據目標機的數據寬度對讀寫內存指令進行了優化,例如日立SH-2處理器的外設配置寄存器只能通過16位/32位進行讀寫。因此,在任何時刻,調試樁都只用16位/32位進行訪問。目標機會返回如下信息:
+$2f86#-06
寫內存:(“M”)
eg:M4015cc,2:c320#6d
(向地址0x4015cc寫入數據0xc320)
如果正確,目標機返回+$OK#9a。
程序控制命令
程序控制命令是GDB用來控制被調試程序行為的命令。相對寄存器相關命令和內存相關命令,控制命令的實現難度大些。
獲取最后的信號(“?”)
eg:$?#3f
這個命令用來確定目標是如何達到當前的狀態的。接收到的響應同最后的信號(“last signal”),后面會介紹。
單步命令(“s”)
eg:$s#73
當GDB想讓目標精確的執行一條匯編指令時,GDB會向目標機發送這條命令。(用戶在GDB的console中輸入step和stepi),接收到的響應見continue。
繼續命令(“c”)
eg:$C#63
當用戶在console下執行continue命令時,GDB回向目標機發送此命令。目標機成功解析此命令后,GDB會釋放控制權,使被調試目標機全速運行。
調試樁除了返回“+”消息包,表示正確收到信息外,不會立即響應step和continue命令。相反,只有當下一個斷點到達時,被請求的指令已經執行完(ste,p時的情況),一個異常發生,或者程序退出時,樁才進行響應。
有兩種方式響應這些命令:一種是簡單的(“last signal”),另一種是多用途的(“expedited response”)。
Last Signal 響應(“S”)
eg:+$050#b8
這是最簡單的響應lastsignal(“?”)step和continue命令。“05”可以用作使用POSIX標準的signal函數的任意信號值的響應。“5”是斷點異常,“10”是總線錯誤,等等。
快速響應(Expeditedresponse (“T”))
eg:$T0510:1238;F:FFE0…#xx
這條信息將最后的信號響應(例子是“05”)和一些GDB可能立刻會讀取的寄存器進行結合。為了在代碼單步執行時,提高GDB調試性能,這條信息使GDB直接獲取該寄存器的值(通常是PC和狀態寄存器),避免發出讀寄存器的命令。
寄存器號的格式與讀寫寄存器命令相同。在這個例子中,寄存器16(hex 10)的值是0x1238,寄存器15(F hex)的值為0xffe0。
其他命令:
Console 輸出(“O“)——可自定義的
eg:$0x48656c6cf2c20776f726c64210a#55
(在GDB console中輸出“Hello, world!\n“)
這個命令允許調試樁向GDBconsole發送文本信息。文本會被按照16進制顯示在console中,并且GDB會一直輸出信息,直到它遇到(‘\n’, 0xa)字符。
這個信息通常是由目標機發起,GDB絕不會發送一個console output信息給目標機。
空響應(““)
當目標機調試樁遇見一個它不支持或不理解的命令時,它將返回空響應。這允許GDB選擇一個替代命令如果另一個命令是有效的。
eg:<an unrecognized command>
目標機響應:+$#00
錯誤響應(“E“)
當目標機調試樁在執行命令時遇到一個錯誤時,它將會給GDB返回錯誤信息。例如總線錯誤或進行非法地址訪問時,會生成這樣的錯誤。
eg:<a command that produces an error>
目標機響應:+$E01##
在GDB中沒有任何預定義的錯誤碼,因此當GDB接收到錯誤信息時,會將錯誤信息輸出在console中,并且掛起當前進程。
總結
以上是生活随笔為你收集整理的GDB Remote Serial Protocol —— RSP协议解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浅谈cpu.idle和cpu.load
- 下一篇: javascript中如何求数组的平均值