liteos 異常接管(十五)

1 概述

1.1 基本概念

異常接管是操做系統對在運行期間發生異常的狀況進行處理的一系列動做,譬如打印異常發生時當前函數調用棧信息、 cpu現場信息、任務的堆棧狀況等。shell

異常接管做爲一種調測手段,能夠在系統發生異常時提供給用戶有用的異常信息,譬如異常的類型、發生異常時系統的狀態等,方便用戶定位分析問題。編程

Huawei LiteOS的異常接管,在系統發生異常時的處理動做是顯示異常發生時正在運行的任務信息(包括任務名、任務號、堆棧大小等),以及cpu現場等信息。函數

  • R11:能夠用做通用寄存器,在開啓特定編譯選項時能夠用做幀指針寄存器,能夠用來實現棧回溯功能。

gcc默認將R11做爲存儲變量的通用寄存器使用,於是默認狀況下沒法使用FP的棧回溯功能。爲支持調用棧解析功能,須要在編譯參數中添加-fno-omit-frame-pointer選項,提示編譯器將R11做爲FP使用操作系統

  • FP寄存器(Frame Point),幀指針寄存器,根據該寄存器能夠實現追溯程序調用棧的功能,用來展現函數間的調用關係。

FP寄存器指向當前執行函數的棧回溯結構。返回的FP值是指向由調用了這個當前函數的函數(父函數)創建的棧回溯結構的指針。而這個結構中的返回FP值是指向調用了父函數的函數的棧回溯結構的指針,以此類推。指針

當運行發生異常時,系統打印FP寄存器內容,用戶能夠據此追溯函數間的調用關
系,幫助定位異常的緣由。code

堆棧分析原理如圖1所示。blog

圖中不一樣顏色的寄存器表示不一樣的函數,經過FP寄存器,棧回溯到了異常函數的父函數,從而使調用關係更清楚,方便用戶定位問題。開發

1.2 調用棧關係

在上圖1,能夠看到函數調用過程當中,棧幀寄存器的保存;所以能夠按照規律對棧進行解析就能夠推出函數調用執行關係,具體步驟以下:編譯器

  1. 獲取當前FP寄存器的值。
  2. FP寄存器減去4字節獲得當前PC值。經過PC值能夠參考elf文件或者編譯生成asm文件獲得函數名稱。
  3. FP寄存器減去24字節,獲得上次函數的調用棧幀的起始地址; FP寄存器減去16字節獲得上次函數調用結束時SP的地址,那麼FP到SP之間的棧就是一個函數調用的棧幀。
  4. 經過每一層棧幀中的PC指針,就知道函數調用的關聯。

2 開發指導

2.1 功能

異常接管爲用戶提供如下幾種異常類型:it

異常名稱 描述
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 開發流程

異常接管通常的定位步驟以下:

  1. 打開編譯器編譯後生成的.asm 文件。
  2. 搜索PC指針在.asm中的位置。
  3. 根據LR值查找對應的調用函數。
  4. 重複步驟3,找到異常的任務函數。

具體的定位方法會在編程實例中舉例說明。

3 注意事項

  • 要查看調用棧信息,必須添加編譯選項宏-fno-omit-frame-pointer支持stack frame,不然編譯默認是關閉FP寄存器.

4 編程實例

4.1 實例描述

使用panic 命令手動觸發了一個軟中斷異常,異常函數爲LOS_Panic,下面兩個代碼test_panic 爲觸發異常命令函數,另外一個爲異常調用棧打印信息.

uwExcType 2爲軟中斷異常。

定位步驟以下:

  1. 打開編譯器編譯後生成的 xxx.asm 文件。
  2. 搜索PC指針 80121234 在asm文件位置(去掉0x)。
  3. 根據 LR值查找對應的調用函數。
  4. 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
相關文章
相關標籤/搜索