1. 程式人生 > 其它 >riscv-xv6單步除錯1

riscv-xv6單步除錯1

  過了兩個月,現在準備重新看xv6的原始碼,除錯的時候卻死活記不起來自己當初是怎麼除錯的,遂明白寫部落格記錄的重要性,打算這次看原始碼的時候,把容易遺忘的東西都記錄下來,留待後觀吧。

xv6除錯方法

  在xv6原始碼有Makefile的路徑上,一個終端輸入

make cpus=1 qemu-gdb

  然後在另一個終端輸入

gdb-multiarch

  特別注意這裡用的是gdb-multiarch(花了好多時間就是找不到合適的gdb,MIT的教學視訊裡面的riscv64-linux-gnu-gdb在我的linux上找不到這玩意)。該路徑下有一個.gdbinit的初始化檔案,gdb-multiarch會讀取這個檔案然後自動連線之前的gdb,然後就可以正常除錯了。

  記得之前還遇到了因為許可權問題,gdb沒辦法讀取這個.gdbinit檔案而報錯,可能因為之前配置好了,這次就沒遇到這個問題了。

xv6的單步除錯

  從入口點entry.S的彙編程式碼開始。

_entry:
	# set up a stack for C.
        # stack0 is declared in start.c,
        # with a 4096-byte stack per CPU.
        # sp = stack0 + (hartid * 4096)
        la sp, stack0
        li a0, 1024*4
	csrr a1, mhartid
        addi a1, a1, 1
        mul a0, a0, a1
        add sp, sp, a0
	# jump to start() in start.c
        call start

  初始情況entry.S被載入到地址0x80000000。這裡的la是一條偽指令,由aupic和addi組合而成,實際效果相當於,sp = stack + pc。gdb顯示如下:
在這裡插入圖片描述
  在執行auipc指令之後,sp的值變為0x80009000,因此auipc指令的作用是 rd = sp + (立即數 << 12)。接著的li也是一條偽指令,在gdb中對應指令lui。lui指令的作用是rd = 立即數 << 12
  csrr偽指令用於讀取CSR到目的暫存器rd。mhartid感覺可以簡單地理解為cpu編號的標識?下面是文件中的描述。
在這裡插入圖片描述
實際上通過print可以知道此時mhartid=0。我想這個作用在於多個cpu啟動時為每個cpu建立一個不同的棧吧。

  總的來說,entry.S的彙編程式碼在進入start函式之前,設定了棧指標esp = 0x80000000 + stack0 + 4096 * mhartid。

小結關鍵詞:

gdb除錯核心方法,la指令,mhartid含義,aupic,lui指令。