Melis系统崩溃问题分析以及解决思路

Melis系统崩溃问题分析以及解决思路

在使用Melis 系统开发时,会经常遇到系统崩溃死机的问题,对于此类问题大家总是避之不及, 分析原因, 一方面是此类问题涉及到CPU异常模式架构,需要用户对arm CPU架构具有较深的技术储备。另一方面,异常处理代输出的调试信息不够直观,不太友好的调试界面使用户失去了直面问题的勇气。 所以一般情况下的解决思路都是回避问题,通过不断修改业务代码来试错. 这种解决思路不但效率低下,而且很有可能没有找到根本问题,为将来留下隐患. 下面推荐一种直接分析此类问题的思路, 供参考。

预备知识(以ARM9为例,ARMV5TE指令集)

在初始化阶段 Melis将异常向量的入口映射到了0xffff0000开始的高地址.
在程序中的实现如下图, 通过链接脚本的操作,这些代码将被放置在0xffff0000地址运行.
这里写图片描述

问题场景

处理器进入异常模式一般有三种情况:

  • 非法指令,对应异常入口0xFFFF0004
  • 取指异常, 对应异常入口0xFFFF000C
  • 数据存取异常, 对应异常入口0xFFFF0010

本文对以上三种异常死机的情况分析类似,所以就以数据存取异常分析为例介绍整个分析过程.

Crash现场

Crash现场打印寄存器如下图,下面演示如何利用DS5倒推出死机位置,定位导致死机的代码.
这里写图片描述

###分析过程###

  • 第一步,定位异常入口, 从打印信息可以很明显看出,这是一条数据存取异常, 所以对应的异常入口地址应该是0xFFFF0010. 异常时刻寄存器已经全部打印出来,实际上可以通过将图中所有寄存器值恢复到CPU的寄存器堆中,使时光倒流回异常发生的时刻. 但是这里有一个问题, 上图的寄存器打印信息是目前melis2.0异常处理输出,较Melis1.0提供了更多的寄存器现场信息. 针对1.0是无法通过恢复打印寄存器的方式找回死机现场的. 本文针对Melis1.0.

  • 第二步, 修改异常入口, 由于异常处理代码本身会破坏寄存器现场,所以,在判断完异常处理类型,从而定位到异常入口后,我们修改异常入口,使CPU在异常处进入死循环,不再往下执行,这样做的目的是保留异常前最后时刻的寄存器现场,便于恢复, 见下图红色部分.
    这里写图片描述

  • 第三步, 重新编译内核, 下载运行.

  • 第四步, DS-5 Attach到目标平台. 可以看到,CPU已经在异常入口处进入死循环,此时的寄存器由于没有被异常处理程序破坏,仍然保留了异常前的状态,只要使CPU恢复之前的状态,就能找到问题点.
    这里写图片描述

  • 第五步, 恢复现场, 恢复现场, 现场恢复包括 1,处理器模式恢复,可以恢复lr, sp, cpsr. 2.通用寄存器恢复,由于现场没有被破坏,所以无需恢复通用寄存器,只需要恢复cpsr, 和lr即可。

这里写图片描述
这里写图片描述

这里要注意的是PC指针的恢复, 按照 newPC =lr -4的原则,恢复寄存器为0xc200d9f0

这里写图片描述

现场恢复后, 可以得到更多的关于死机点的信息,例如调用堆栈,源文件,函数,行号等等。 从中得到, 死机的原因是melis_init_thread函数中访问了非法地址:0xdeadbeec, 从而导致CPU进入到异常模式.

这里写图片描述

以上就是针对此类问题的总体思路,当然实际情况可能远比例子复杂。 即便如此,我们也能从中找到一些规律。 找到规律 是解决问题的第一步,规律不一定表示某种必然, 有时候随机也是一种规律,在错综复杂的问题现场中总有稳定的因素存在,这个时候如上的方法也是适用的。

猜你喜欢

转载自blog.csdn.net/tugouxp/article/details/78265995