RISC-V指令异常调试实例

描述

本文转自公众号,欢迎关注关于

RISC-V指令异常调试实例 (qq.com)

前言

本文以一个简单的实例介绍RISC-V指令异常的调试过程,思路都是一样的,遇到其他情况时分析过程也类似。

相关内容参考《riscv-privileged-20211203.pdf》

过程

现象是程序执行后进入了异常中断,可以通过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的原因。

RISC-V

我们搜到以下信息,即mtval寄存器保存了异常指令,mepc指向了异常指令

RISC-V

RISC-V

可以看到mepc的内容是0,那么猜测应该是函数指针未初始化直接调用导致的

(gdb) info reg mtval


mtval 0x0      0x0


(gdb) info reg mepc


mepc 0x0      0x0


(gdb)

到这里基本就确认了方向了,可以重点看哪些地方有函数指针,或者逐步注释函数,或者逐步断点定位即可。

这里很快就确认了是

是如下代码导致

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);


}

查看函数指针正好是0

(gdb) p xxx_drv.ops.ioctl


$1 = (int (*)(struct xxx_dev_s *, unsigned int, void *)) 0x0


(gdb)

回溯代码确认了是某个外设没有初始化成功则这个回调函数没有初始化。原因就定位了。

总结

对于异常的调试可以参考手册《riscv-privileged-20211203.pdf》,从异常原因入手,逐渐反推,确认异常触发点然后确定原因。

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分