前言
本文以一個簡單的實例介紹RISC-V指令異常的調(diào)試過程,思路都是一樣的,遇到其他情況時分析過程也類似。
相關內(nèi)容參考《riscv-privileged-20211203.pdf》
過程
現(xiàn)象是程序執(zhí)行后進入了異常中斷,可以通過GDB的bt命令看到
#12 0x02002e9c in exception () at src/lib/riscv/src/exception.c:55
#13 0x02002b40 in is_exception ()
Backtrace stopped: frame did not save the PC
(gdb)
既然是進入了異常中斷,那么就需要確認到底是什么異常,
這可以通過mcause寄存器查看
(gdb) info reg mcause
mcause 0x2 0x2
(gdb)
可以看到是非法指令異常
那么我們就搜索文檔的Illegal instruction可以查看到所有可能導致Illegal instruction的原因。
我們搜到以下信息,即mtval寄存器保存了異常指令,mepc指向了異常指令
可以看到mepc的內(nèi)容是0,那么猜測應該是函數(shù)指針未初始化直接調(diào)用導致的
(gdb) info reg mtval
mtval 0x0 0x0
(gdb) info reg mepc
mepc 0x0 0x0
(gdb)
到這里基本就確認了方向了,可以重點看哪些地方有函數(shù)指針,或者逐步注釋函數(shù),或者逐步斷點定位即可。
這里很快就確認了是
是如下代碼導致
int xxx_ioctl(unsigned int dev_id, unsigned int cmd, void *data)
{
if (dev_id >= xxx_drv.dev_num)
return -1;
return xxx_drv.ops.ioctl(&(xxx_drv.dev[dev_id]), cmd, data);
}
查看函數(shù)指針正好是0
(gdb) p xxx_drv.ops.ioctl
$1 = (int (*)(struct xxx_dev_s *, unsigned int, void *)) 0x0
(gdb)
回溯代碼確認了是某個外設沒有初始化成功則這個回調(diào)函數(shù)沒有初始化。原因就定位了。
總結
對于異常的調(diào)試可以參考手冊《riscv-privileged-20211203.pdf》,從異常原因入手,逐漸反推,確認異常觸發(fā)點然后確定原因。
審核編輯:湯梓紅
-
指令
+關注
關注
1文章
611瀏覽量
35812 -
調(diào)試
+關注
關注
7文章
589瀏覽量
34064 -
命令
+關注
關注
5文章
696瀏覽量
22109 -
RISC-V
+關注
關注
45文章
2322瀏覽量
46592
發(fā)布評論請先 登錄
相關推薦
評論