liteos 异常接管(十五)
1 概述
1.1 基本概念
异常接管是操作系统对在运行期间发生异常的情况进行处理的一系列动作,譬如打印异常发生时当前函数调用栈信息、 cpu现场信息、任务的堆栈情况等。
异常接管作为一种调测手段,可以在系统发生异常时提供给用户有用的异常信息,譬如异常的类型、发生异常时系统的状态等,方便用户定位分析问题。
Huawei LiteOS的异常接管,在系统发生异常时的处理动作是显示异常发生时正在运行的任务信息(包括任务名、任务号、堆栈大小等),以及cpu现场等信息。
- R11:可以用作通用寄存器,在开启特定编译选项时可以用作帧指针寄存器,可以用来实现栈回溯功能。
gcc默认将R11作为存储变量的通用寄存器使用,因而默认情况下无法使用FP的栈回溯功能。为支持调用栈解析功能,需要在编译参数中添加-fno-omit-frame-pointer选项,提示编译器将R11作为FP使用
- FP寄存器(Frame Point),帧指针寄存器,根据该寄存器可以实现追溯程序调用栈的功能,用来展示函数间的调用关系。
FP寄存器指向当前执行函数的栈回溯结构。返回的FP值是指向由调用了这个当前函数的函数(父函数)建立的栈回溯结构的指针。而这个结构中的返回FP值是指向调用了父函数的函数的栈回溯结构的指针,以此类推。
当运行发生异常时,系统打印FP寄存器内容,用户可以据此追溯函数间的调用关
系,帮助定位异常的原因。
堆栈分析原理如图1所示。
图中不同颜色的寄存器表示不同的函数,通过FP寄存器,栈回溯到了异常函数的父函数,从而使调用关系更清楚,方便用户定位问题。
1.2 调用栈关系
在上图1,可以看到函数调用过程中,栈帧寄存器的保存;因此可以按照规律对栈进行解析就可以推出函数调用执行关系,具体步骤如下:
- 获取当前FP寄存器的值。
- FP寄存器减去4字节得到当前PC值。通过PC值可以参考elf文件或者编译生成asm文件得到函数名称。
- FP寄存器减去24字节,得到上次函数的调用栈帧的起始地址; FP寄存器减去16字节得到上次函数调用结束时SP的地址,那么FP到SP之间的栈就是一个函数调用的栈帧。
- 通过每一层栈帧中的PC指针,就知道函数调用的关联。
2 开发指导
2.1 功能
异常接管为用户提供以下几种异常类型:
异常名称 | 描述 | 值 |
---|---|---|
OS_EXCEPT_UNDEF_INSTR | 未定义的指令异常 | 1 |
OS_EXCEPT_SWI | 软中断异常 | 2 |
OS_EXCEPT_PREFETCH_ABORT | 预指取指令异常 | 3 |
OS_EXCEPT_DATA_ABORT | 数据中止异常 | 4 |
OS_EXCEPT_FIQ | FIQ异常 | 5 |
2.2 开发流程
异常接管一般的定位步骤如下:
- 打开编译器编译后生成的.asm 文件。
- 搜索PC指针在.asm中的位置。
- 根据LR值查找对应的调用函数。
- 重复步骤3,找到异常的任务函数。
具体的定位方法会在编程实例中举例说明。
3 注意事项
- 要查看调用栈信息,必须添加编译选项宏-fno-omit-frame-pointer支持stack frame,否则编译默认是关闭FP寄存器.
4 编程实例
4.1 实例描述
使用panic 命令手动触发了一个软中断异常,异常函数为LOS_Panic,下面两个代码test_panic 为触发异常命令函数,另一个为异常调用栈打印信息.
uwExcType 2为软中断异常。
定位步骤如下:
- 打开编译器编译后生成的 xxx.asm 文件。
- 搜索PC指针 80121234 在asm文件位置(去掉0x)。
- 根据 LR值查找对应的调用函数。
- g_RunningTask 为当前异常时任务函数
UINT32 test_panic(UINT32 argc, CHAR **args)
{
LOS_Panic("*****Trigger an exception\n");
return;
}
Huawei LiteOS# panic
*****Trigger an exception
uwExcType = 2
puwExcBuffAddr pc = 0x80121234
puwExcBuffAddr lr = 0x80121234
puwExcBuffAddr sp = 0x80e63400
puwExcBuffAddr fp = 0x80e6340c
*******backtrace begin*******
traceback 0 -- lr = 0x80138d04
traceback 0 -- fp = 0x80e635d4
traceback 1 -- lr = 0x80138d88
traceback 1 -- fp = 0x80e635e4
traceback 2 -- lr = 0x801247d4
traceback 2 -- fp = 0x80e635f4
traceback 3 -- lr = 0x801217c4
traceback 3 -- fp = 0x11111111
R0 = 0x1c
R1 = 0x800dba3a
R2 = 0x1b
R3 = 0xfe
R4 = 0x80e634a0
R5 = 0x0
R6 = 0x800cc7f8
R7 = 0x7070707
R8 = 0x8080808
R9 = 0x9090909
R10 = 0x10101010
R11 = 0x80e6340c
R12 = 0x1b
SP = 0x80e63400
LR = 0x80121234
PC = 0x80121234
CPSR = 0x60000013
g_pRunningTask->pcTaskName = shellTask
g_pRunningTask->uwTaskPID = 6
g_pRunningTask->uwStackSize = 12288