文档首页/ LiteOS/ 内核/ 异常接管/ 问题定位实例
更新时间:2021-07-08 GMT+08:00
分享

问题定位实例

在某ARM32平台上通过错误释放内存,触发系统异常。系统异常被挂起后,能在串口中看到异常调用栈打印信息和关键寄存器信息,如下所示,其中excType表示异常类型,此处值为4表示数据终止异常,其它数值可以查看芯片手册。通过这些信息可以定位到异常所在函数和其调用栈关系,为分析异常原因提供第一手资料。

excType: 4
taskName = MNT_send
taskId = 6
task stackSize = 12288
excBuffAddr pc = 0x8034d3cc
excBuffAddr lr = 0x8034d3cc
excBuffAddr sp = 0x809ca358
excBuffAddr fp = 0x809ca36c
*******backtrace begin*******
traceback 0 -- lr = 0x803482fc
traceback 0 -- fp = 0x809ca38c
traceback 1 -- lr = 0x80393e34
traceback 1 -- fp = 0x809ca3a4
traceback 2 -- lr = 0x8039e0d0
traceback 2 -- fp = 0x809ca3b4
traceback 3 -- lr = 0x80386bec
traceback 3 -- fp = 0x809ca424
traceback 4 -- lr = 0x800a6210
traceback 4 -- fp = 0x805da164

定位步骤如下:

  1. 打开编译后生成的 asm 反汇编文件(默认生成在Huawei_LiteOS/out/<platform>目录下,其中的platform为具体的平台名)。
  2. 搜索PC指针 8034d3cc 在asm文件中的位置(去掉0x)。

    PC地址指向发生异常时程序正在执行的指令。在当前执行的二进制文件对应的asm文件中,查找PC值8034d3cc,找到当前CPU正在执行的指令行,得到如下图所示结果。

    从图中可以看到:

    1. 异常时CPU正在执行的指令是ldrh r2, [r4, #-4]。
    2. 异常发生在函数osSlabMemFree中。

    结合ldrh指令分析,此指令是从内存的(r4-4)地址中读值,将其load到寄存器r2中。再结合异常时打印的寄存器信息,查看此时r4的值。下图是异常时打印的寄存器信息,可以看到,r4此时值是0xffffffff。

    显然,r4的值超出了内存范围,故CPU执行到该指令时发生了数据终止异常。根据汇编知识,从asm文件可以看到,r4是从r1 mov过来,而r1是函数第二个入参,于是可以确认,在调用osSlabMemFree时传入了0xffffffff(或-1)这样一个错误入参。

    接下来,需要查找谁调用了osSlabMemFree函数。

  3. 根据 LR链接寄存器值 查找调用栈。

    从异常信息的backtrace begin开始,打印的是调用栈信息。在asm文件中查找backtrace 0对应的LR,如下图所示。

    可见,是LOS_MemFree调用了osSlabMemFree。依此方法,可得到异常时函数调用关系如下:MNT_buf_send(业务函数) -> free -> LOS_MemFree -> osSlabMemFree。

    最终,通过排查业务中MNT_buf_send实现,发现其中存在错误使用指针的问题,导致free了一个错误地址,引发上述异常。

相关文档