前言
本文以一个实例分享RISC-V的Store AMO access fault异常的调试过程。Store AMO access fault主要发生在非法地址访问时(栈溢出,指针异常等)。
过程
现象是程序运行时进入了异常中断,如下
使用bt回溯可以看到进入了异常处理函数exception ()
(gdb) bt
......
#6 0x02002eb2 in exception () at src/lib/riscv/src/exception.c:55
#7 0x00000000 in ?? ()
Backtrace stopped: frame did not save the PC
(gdb)
那么首先想到的是确认异常原因
查看异常寄存器:info reg mcause
可以看到异常原因是0x07
对应的是Store/AMO access fault 异常,这是一个写数据时的异常.
那么接下来就要确认写哪个地方的数据错误了呢?
我们可以通过info reg mtval 查看mtval寄存器看到。
写0x28382ad0时产生了异常.
那么什么时候写这个地址导致了异常呢,之前bt已经看不到回溯的地方了。
我们可以使用数据断点来监控
设置数据断点 watch *(unsigned int*)0x28382ad0
重新加载程序运行 load
c运行
看到断点停在了memset函数处,这印证了我们前面分析的是写数据导致的问题
继续bt查看
我们找到对应的代码处
看下memset的参数,如果看不到可以在memset前打断点重新运行
最终确认确实是栈初始化时写0x28382ad0这个地址的内容错误,原因是不具备写属性导致异常
(gdb) p pxStack
$8 = (StackType_t *) 0x28382ad0
(gdb)
当然为什么这个地址不能写和这里没关系了,是另外一回事了,是我们的环境DDR的问题。
总结
以上是一个分析实例的过程,遇到类似问题可以参考。有几个关键点一是确认异常原因,异常访问的地址,然后通过数据断点确认什么时候访问了这个地址,到此基本就确认问题了,后面就顺藤摸瓜了。