本期內容如下:
GDB除錯概述編譯和安裝QEMU除錯演示在之前的01-05章我們講解了RISC-V ISA相關的知識,對RISC-V也已經有個基本的瞭解,為了加深對RISC-V ISA的理解,光做到看還是不夠的,我們還需要動手去編寫彙編程式碼。
GDB工具用於除錯編譯後的程式碼;QEMU用於模擬RISC-V處理器,這樣我們就可以不需要具體硬體就可以除錯我們的彙編程式碼,對於學習十分方便。
如果,有些人需要在具體硬體上進行模擬除錯,我今後還會寫一篇文章,介紹如何使用JTAG在linux上進行硬體除錯的文章,還請關注。
一、GDB除錯概述
GNU symbolic debugger,簡稱「GDB 偵錯程式」,是 Linux 平臺下最常用的一款程式偵錯程式。GDB 編譯器通常以 gdb 命令的形式在終端(Shell)中使用。作為程式設計師,編寫和除錯程式是必備的技能,為此學好gdb是十分有必要的,還請讀者自行查閱相關文件,在這裡就不對gdb功能進行過多展開了。
在RISC-V的開發過程中,我們用的gdb工具被包含在工具鏈中,檔名類似於riscv-none-embed-gdb。在這裡我們簡單瞭解一下gdb的基本指令。
riscv-none-embed-gdb 執行檔名稱 ---------------gdb載入符號檔案,用於後續的除錯run ----------------此命令使程式開始執行更多指令參見圖1.
圖1 GDB常用指令
二、編譯,安裝和使用QEMU
由於不同的linux發行版本,在軟體上相容性可能會存在一些問題,這裡僅介紹如何在linux上,進行RISC-V的QEMU編譯和安裝,並沒有提供已經編譯好的qemu-riscv32,我這裡採用的作業系統為deepin-v20,其他linux系統編譯和安裝方法類似。
2.1 QEMU編譯和安裝
具體步驟如下:
sudo apt install libpixman-1-devgit clone https://github.com/riscv/riscv-qemu.gitcd riscv-qemu/git checkout riscv-qemu-3.0./configuremake -j4sudo make install
當一切都安裝完成後,我們執行qemu-riscv32 --version應當能夠看到如圖2所示的內容。
圖2 qemu-riscv32 版本資訊
2.2 qemu-riscv32的使用
qemu-riscv32指令常用格式如下:qemu-riscv32 程式名稱 -nographic
如我們已經有一個已經編譯好的riscv32 程式hello,為了在qemu中執行程式,只需要執行如下指令即可。
qemu-riscv32 hello -nographic
如果我們希望聯合riscv-none-embed-gdb,並透過qemu實現除錯,我們可以使用如下指令讓qemu支援gdb單步除錯功能。qemu-riscv32 -singlestep -g 埠號 程式名 -nographic
如需要對上邊的hello程式進行除錯,我們選的通訊埠為112233,此時指令如下:
qemu-riscv32 -singlestep -g 112233 hello -nographic
三、除錯演示
3.1 編寫彙編檔案hello.S檔案,
該檔案主要實現兩個數相加,加數1放入a1,加數2放入a2,結果a0
.global _start_start: li a1,23 li a2,18 add a0,a1,a2loop: j loop
3.2 編寫Makefile檔案
Makefile檔案主要是為了方便今後的程式碼編譯,不需要每次都輸入很長的編譯指令,僅需執行make,即可完成程式的編譯。
CC:=riscv-none-embed-gccXFLAGS+= -save-temps -nostdlib -nostartfiles -ffreestanding -static all: $(CC) $(XFLAGS) -g -o hello hello.Sclean: rm -rf *.o
riscv-none-embed-gcc為我選用的工具鏈的編譯器名稱,如果你的編譯器為其他,請做相應的修改,gcc是可以直接編譯彙編指令的當然你也可以使用riscv-none-embed-as進行編譯。
3.3 編寫模擬器啟動指令碼sim
sim指令碼不是必須的,之所以這樣寫是為了方便今後快速用qemu載入編譯後的程式,方便除錯exe_name為要執行的程式,這裡實行./sim hello就實現了載入hello程式到qemu模擬器的操作。
function help(){echo "Please input applicantion !"echo "==========="echo "sim exe_name"}function main(){if [ "$1" == "" ];then help returnfiqemu-riscv32 -singlestep -g 12345 $1 nographic}main $1
3.4 完成各檔案的編寫
所有檔案編寫完後,我們將看到如圖3所示的hello工程目錄結構。
圖3 hello檔案目錄
3.5 編譯hello.S檔案
執行make指令,將看到hello檔案被建立了
圖4 make後的檔案列表
3.6 開啟qemu-riscv32模擬器
執行sim hello,qemu-riscv32將會載入hello程式
圖5 執行sim hello操作
3.7 開啟riscv32的gdb工具
1.執行riscv-none-embed-gdb hello,該指令將會把hello檔案載入到gdb中;
2.在gdb控制檯中執行target remote localhost:12345 連線qemu-riscv32模擬器;
3.前兩步完成後便可以開始除錯hello程式了。
圖6 開啟gdb並連結qemu模擬器
3.8 除錯hello程式
具體除錯的過程參見如下gdb除錯log,
Copyright (C) 2019 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.Type "show copying" and "show warranty" for details.This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=riscv-none-embed".Type "show configuration" for configuration details.For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>.For help, type "help".Type "apropos word" to search for commands related to "word"...Reading symbols from hello... (gdb) target remote localhost:12345Remote debugging using localhost:12345_start () at hello.S:44 li a1,23(gdb) list1 .align 42 .global _start3 _start:4 li a1,235 li a2,186 add a0,a1,a2 789 loop:10 j loop(gdb) break 7Breakpoint 1 at 0x1006a(gdb) break 3Breakpoint 2 at 0x10062: file hello.S, line 5.(gdb) nextBreakpoint 2, _start () at hello.S:55 li a2,18(gdb) next6 add a0,a1,a2 (gdb) nextloop () at hello.S:1010 j loop(gdb) info registers ra 0x0 0x0sp 0xffffcda0 0xffffcda0gp 0x0 0x0tp 0x0 0x0t0 0x0 0t1 0x0 0t2 0x0 0fp 0x0 0x0s1 0x0 0a0 0x29 41a1 0x17 23a2 0x12 18a3 0x0 0a4 0x0 0a5 0x0 0a6 0x0 0a7 0x0 0s2 0x0 0s3 0x0 0s4 0x0 0s5 0x0 0s6 0x0 0s7 0x0 0s8 0x0 0s9 0x0 0s10 0x0 0s11 0x0 0t3 0x0 0t4 0x0 0t5 0x0 0t6 0x0 0--Type <RET> for more, q to quit, c to continue without paging--cpc 0x10068 0x10068 <loop>
從gdb除錯過程中可以看到a0的值為41,a1為23,a2為18,也就是說a0=a1+a2,和我們的彙編程式一樣。
至此,一個可以模擬和除錯RISC-V環境就已經搭建完畢了,今後我們便可以在這個環境下學習具體的彙編指令了,透過gdb的info registers指令我們可以實時檢視到RISC-V處理器的所有暫存器資料。