打印

教你如何找到导致程序跑飞的指令(二)

[复制链接]
5307|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ifreecoding|  楼主 | 2012-2-29 00:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
由于论坛有字数限制,接上一篇“教你如何找到导致程序跑飞的指令(一)”,或者下载附件查看全文,或者登录我博客查看全文。

好了,ARM7内核的介绍到此结束,下面介绍cortex内核的,使用STSTM32TILM3S系列的同学们注意了,它们都是cortex内核的,下面的介绍你也许用得上。
Cortex内核与ARM7内核定位此种问题的思路完全是一样的,cortex内核的详细介绍请参考“底层工作者手册之嵌入式操作系统内核”中的5.1节。cortex内核有一些特殊,它在产生中断时会先将R0~R3R12LRPC以及XPSR8个寄存器压入当前的堆栈,然后才跳转到中断向量表执行中断服务程序,此时LR中保存的不是返回地址,而是返回时所使用的芯片模式和堆栈寄存器的标示,只能是0xFFFFFFF10xFFFFFFF9或者是0xFFFFFFFD3个值中的一个,如果你还认为LR中保存的是返回地址,并且是这么奇特的地址,估计你一定会晕了。
要找cortex内核芯片的返回地址就需要到栈中去找,前面不是说了么,进入中断前硬件会自动向当前栈压入8个寄存器,如下图所示:
图6

如果你看了2.3节和5.1节就应该知道cortexARM7内核都是一种递减满栈,意思是说压栈时栈指针向低地址移动,栈指针指向最后压入的数据。SPR13)寄存器就是栈寄存器,它里面保存的就是当前的栈指针,因此当cortex内核发生中断时,我们就可以根据SP指针来找到压入上述8个寄存器的地址,然后找到LR的位置,再从LR中找到返回地址,下面的这个例子是“底层工作者手册之嵌入式操作系统内核”中的6.1节的一个例子,
void TEST_TestTask1(void)
{
    while(1)
    {
        DEV_PutStrToMem((U8*)"\r\nTask1 is running! Tick is: %d",
                        MDS_SystemTickGet());

        DEV_DelayMs(1000);

        MDS_TaskDelay(250);


if(MDS_SystemTickGet() >= 2000)
        {

ADDRVAL(0xFFFFFFFF) = 0;
        }
    }
}
红色字体部分会触发一个异常,它会向0xFFFFFFFF这个地址写入0,也会触发一个异常中断,触发的异常会进入MDS_FaultIsrContext异常中断服务函数,在MDS_FaultIsrContext函数的入口地址打上断点,运行此程序,触发异常后如下图


图7

从图7左上侧窗口可以看到SP的值为0x20001258,那么我们在右下角的窗口找到0x20001258这块内存的地址,从0x20001258开始,每4个字节对应一个寄存器,依次为R0R1R2R3R12LRPCXPSR,其中红框的位置就对应着LR,从图中可以看到LR的值为0x1669,我们找到这个版本编译后的目标文件,使用objdump软件反汇编,如下图所 示:



图8

可以看到0x1669这个地址位于TEST_TestTask1函数里,与我们设计的一致。
这段代码是经过O2优化的,汇编指令对照到C指令上会有些费事,这里就不再讲解了,知道方法就好,剩下的自己研究。
这里面有2点说明一下,一是cortex内核支持双堆栈,如果使用双堆栈的话会复杂一点,这里为了简单的说明问题,我们只使用了其中的一个MSP,另外一个PSP没有使用,在这个例子里你只需要认为只有一个SP就可以了。另外一点是0x1669这个地址其实就是0x1668,因为cortex内核采用的是Thumb2指令集,该指令集要求指令的最后一个bit1,因此0x1668就变成了0x1669

上面介绍ARM7内核的时候我不是说过如果在FaultIsr函数里做一个打印功能就可以通过打印信息来定位这种问题么,其实在介绍cortex内核的这个例子中我就做了这个功能,具体的实现就先不介绍了,有兴趣的同学可以看我6.1节的介绍(2012.02.28,目前book还没写到6.1节),下面是出现异常时打印的一小段信息,从这段信息里我们可以看到SPR13)的数值为0x20001258,与图7的情况一样,那么在栈中从0x20001258这个地址向上找,找到栈中保存LR的位置,它的数值就是0x1669,与图7中的分析是一致的。
注意一点蓝色字体的R14是我这段打印程序还原过的,因此它与内存中的数值是一样的。

R15 = 0x00000536 R14 = 0x00001669
R13 = 0x20001258 R12 = 0x00000000
R11 = 0x00000000 R10 = 0x00000000 R9  = 0x00000000 R8  = 0x00000000
R7  = 0x00000000 R6  = 0x000003E8 R5  = 0x000007D0 R4  = 0x00000000
R3  = 0x0000008C R2  = 0x00000000 R1  = 0xE000ED04 R0  = 0x00000834
XPSR= 0x21000000
0x20001274: 0x21000000
0x20001270: 0x00000536
0x2000126C: 0x00001669
0x20001268: 0x00000000
0x20001264: 0x0000008C
0x20001260: 0x00000000
0x2000125C: 0xE000ED04
0x20001258: 0x00000834

更多信息,欢迎访问我的博客blog.sina.com.cn/ifreecoding

教你如何找到导致程序跑飞的指令.pdf

276.96 KB

沙发
supreme42| | 2012-2-29 09:34 | 只看该作者
非常有用,一直都疑惑怎么定位程序跑飞。

使用特权

评论回复
板凳
PXJ_520| | 2012-2-29 15:25 | 只看该作者
谢谢LZ分享

使用特权

评论回复
地板
liulangmao| | 2013-4-27 08:41 | 只看该作者
大师,吾等只有膜拜的份

使用特权

评论回复
5
xiaodongplayer| | 2013-4-27 08:58 | 只看该作者
学习学习

使用特权

评论回复
6
weiweiyixiao| | 2013-4-27 14:02 | 只看该作者
学习一下

使用特权

评论回复
7
拿起书本| | 2013-5-6 16:24 | 只看该作者
呵呵,居然看到讲汇编的**了,楼主不简单。顶了

使用特权

评论回复
8
hsh| | 2013-5-6 16:35 | 只看该作者
谢谢

使用特权

评论回复
9
hawksabre| | 2013-5-6 19:33 | 只看该作者
谢谢了   楼主   共享的资料很给力   很不错   谢谢了

使用特权

评论回复
10
14884036| | 2014-9-26 16:16 | 只看该作者
楼主厉害,赞一个,学习了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

68

帖子

3

粉丝