本文轉(zhuǎn)自公眾號,歡迎關(guān)注關(guān)于
RISC-V指令異常調(diào)試實(shí)例 (qq.com)
前言
本文以一個簡單的實(shí)例介紹RISC-V指令異常的調(diào)試過程,思路都是一樣的,遇到其他情況時分析過程也類似。
相關(guān)內(nèi)容參考《riscv-privileged-20211203.pdf》
過程
現(xiàn)象是程序執(zhí)行后進(jìn)入了異常中斷,可以通過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)
既然是進(jìn)入了異常中斷,那么就需要確認(rèn)到底是什么異常,
這可以通過mcause寄存器查看
(gdb) info reg mcause
mcause 0x2 0x2
(gdb)
可以看到是非法指令異常
那么我們就搜索文檔的Illegal instruction可以查看到所有可能導(dǎo)致Illegal instruction的原因。
我們搜到以下信息,即mtval寄存器保存了異常指令,mepc指向了異常指令
可以看到mepc的內(nèi)容是0,那么猜測應(yīng)該是函數(shù)指針未初始化直接調(diào)用導(dǎo)致的
(gdb) info reg mtval
mtval 0x0 0x0
(gdb) info reg mepc
mepc 0x0 0x0
(gdb)
到這里基本就確認(rèn)了方向了,可以重點(diǎn)看哪些地方有函數(shù)指針,或者逐步注釋函數(shù),或者逐步斷點(diǎn)定位即可。
這里很快就確認(rèn)了是
是如下代碼導(dǎo)致
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)
回溯代碼確認(rèn)了是某個外設(shè)沒有初始化成功則這個回調(diào)函數(shù)沒有初始化。原因就定位了。
總結(jié)
對于異常的調(diào)試可以參考手冊《riscv-privileged-20211203.pdf》,從異常原因入手,逐漸反推,確認(rèn)異常觸發(fā)點(diǎn)然后確定原因。
審核編輯:湯梓紅
-
指令
+關(guān)注
關(guān)注
1文章
607瀏覽量
35692 -
調(diào)試
+關(guān)注
關(guān)注
7文章
578瀏覽量
33923 -
命令
+關(guān)注
關(guān)注
5文章
683瀏覽量
22011 -
RISC-V
+關(guān)注
關(guān)注
45文章
2270瀏覽量
46125
發(fā)布評論請先 登錄
相關(guān)推薦
評論