trace32 还原堆栈调用信息
https://blog.csdn.net/wuzengfengjing1/article/details/80926859
通过死机时刻的寄存器查看是最容易入手的;
R13是当前栈顶,存储的堆栈地址,即SP;R14是LinkLR,即子程序的返回地址,也叫LR;R15就是程序寄存器PC
首先查看R14附近的汇编找到fatal 原因,如通过blx跳转到R3时,R3赋给PC后变为0,造成死机;
然后查看R3值的来源,如R6通过ldr传给R3,查看R6地址处的汇编得到被踩坏的context name;
通过查看R14地址处的汇编查到当前执行的接口func A
通过R13地址处的汇编code,找到其返回函数R14的位置,进而在汇编中找到其点用者函数B
根据func B的栈顶指针及汇编找到其返回函数的地址,通过地址找到func C
通过func C的汇编找到其返回函数地址,通过地址找到func D
所以最后的回调函数list为D->C->B->A
于是就知道程序是在运行0x8055C6A的这条指令出现了问题;
这条指令是将R3的值给到PC就出错了。从前面可以看到R3是0xAA8AAAB,将这个值给到PC,考虑到是thumb指令,于是给的就是0xAA8AAAA,这确实和当前死掉的时候PC的值一样;
结果查看0xAA8AAAAA处都不是指令,都是全零的东西,怪不得会造成系统死机;
从如下可知R3值从R6得到的。
从如下查到R6的来源,那么就是g_mp3_context的位置被踩坏了;
通过linkLR知道当前执行的接口是lightduer_mp3_codec_callback;
该接口的开始会进行压栈的操作,即将R0~R6、R14压进去,由此可以知道上一步的LinkLR是指向哪里的;
根据SP的位置mp3_codec_decoder_hisr_handler的调用者是mp3_codec_request_data_to_share_buffer;
接下来mp3_codec_request_data_to_share_buffer接口也有压栈操作;
很明显现在LR不对了;
这是因为在mp3_codec_decoder_hisr_handler里面还有对SP的减数操作,减去了0x14;
根据SP的位置mp3_codec_decoder_hisr_handler的调用者是mp3_codec_task_main;
接下来mp3_codec_task_main接口也有压栈操作
根据SP的位置mp3_codec_task_main的LinkLR是prvTaskExitError;
prvTaskExitError正常是不会运行到的;
于是就推算完成整个调用栈:
mp3_codec_task_main
—》mp3_codec_decoder_hisr_handler
—》mp3_codec_request_data_to_share_buffer
---》lightduer_mp3_codec_callback
----》因为pc指向不对引发死机;
========================================
3、 BLX 指令
BLX 指令的格式为:
BLX 目标地址
BLX 指令从ARM 指令集跳转到指令中所指定的目标地址,并将处理器的工作状态有ARM 状态切换到Thumb 状态,该指令同时将PC 的当前内容保存到寄存器R14 中。因此,当子程序使用Thumb 指令集,而调用者使用ARM 指令集时,可以通过BLX 指令实现子程序的调用和处理器工作状态的切换。
同时,子程序的返回可以通过将寄存器R14 值复制到PC 中来完成。
==============================================
(1)…ldr指令:(load装载) 外存—>>>内存
ldr 指令传数据(将数据传入寄存器) 无论是否是立即数,都可以进行传
格式:ldr 寄存器,=数字
若数字式立即数:ldr 指令(ldr 寄存器,=数字)和 mov指令功能相同(mov 寄存器, #数字)
若数字不是立即数:要想传数据只能选择ldr 指令
====================================