現在看一下問題的解決方法。在我看來,需要修改gdb遠程調試內核時單步命令的語義。有兩個方向。
1.在gdb上修改。在處理用戶的n與s命令時不是發送協議中的s命令,而是分兩步。首先確定下一條指令的開始位置(或者下一行源程序對應的指令的開始位置)。對於有些RISC機器機器指令固定為某個長度,那麼確定這個位置比較簡單,但是對於像x86這樣的變長指令的體系結構就需要稍微麻煩一點(需要確定當前指令的長度等)。然後假如第一步確定的地址是naddr。現在像處理用戶的tbreak *naddr一樣處理就可以了,接著發送繼續運行命令c就可以了。
2.在qemu的gdb stub上修改協議命令s的處理方法。接收到s命令後不是讓虛擬CPU進入單步執行狀態,而是確定在沒有中斷的情況下,下一條指令的位置(注意對於當前是跳轉指令的情況處理比較復雜),然後在這個位置設置臨時斷點,在虛擬CPU到達這個斷點進入gdb stub後立即將其取消。
這兩種處理方法中,我認為1比較好,實現起來清晰明了,但是需要對gdb的代碼比較熟悉。2方法比較復雜,尤其是在當前指令是跳轉指令時,不太容易確定臨時斷點的位置。另外作為暫時的權宜之計,我們可以只使用tbreak +offset來代替n與s命令。