[panic] 一個kernel panic錯誤分析的例子


1.首先從log分析,可以看到最后掛在mdrv_HDMI_GetSourceSelect + 0x8c處。

<4>[ 5022.810137] [<ffffff8000ffcd74>] mdrv_HDMI_GetSourceSelect+0x8c/0x118 [utpa2k]

<4>[ 5022.810877] [<ffffff8000f7eae8>] HDMIRxIoctl+0x650/0xa78 [utpa2k]

<4>[ 5022.811552] [<ffffff8000e7ff14>] UtopiaIoctl+0x3c/0xb0 [utpa2k]

<4>[ 5022.812276] [<ffffff8000ff92a4>] MDrv_HDMI_GetTimingInfo+0x54/0x1c0 [utpa2k]

<4>[ 5022.812949] [<ffffff8000fb1b78>] MApi_XC_PCMonitor_U2+0xc30/0x17b0 [utpa2k]

<4>[ 5022.813577] [<ffffff8000f9e1cc>] _PCMONITORIoctl+0x174/0x22d0 [utpa2k]

<4>[ 5022.814171] [<ffffff8000fab4b0>] XCIoctl+0xc8/0xe28 [utpa2k]

<4>[ 5022.814650] [<ffffff8000e7ff14>] UtopiaIoctl+0x3c/0xb0 [utpa2k]

<4>[ 5022.815160] [<ffffff8000f8908c>] MApi_XC_PCMonitor_EX+0x64/0xf8 [utpa2k]

<4>[ 5022.815181] [<ffffff8002778d6c>] MI_DISP_IMPL_XC_InitDisplayOut+0x46c/0x818 [xcker]

<4>[ 5022.815642] [<ffffff8000e879d4>] MsOS_MPool_Remove_PA2VARange+0x14c/0x4a0 [utpa2k]

<4>[ 5022.815653] [<ffffff80080ee0f4>] kthread+0xec/0x100

<4>[ 5022.815660] [<ffffff8008084910>] ret_from_fork+0x10/0x40

2.因為panic位置是utp2k.ko,所以對應code在utopia中。進入utopia目錄,找到函數mdrv_HDMI_GetSourceSelect在mdrv_hdmi.c中。

3.找到mdrv_hdmi.o,對其進行反匯編:/mtkeda/dtv/msttools/arm/Linaro/gcc-linaro-4.9/2014.11-x86_64_aarch64-elf/bin/aarch64-none-elf-objdump –D –S ./modules/xc/drv/xc/mdrv_hdmi.o > mdrv_hdmi.asm。

4.在mdrv_hdmi.asm中找到mdrv_HDMI_GetSourceSelect + 0x8c.

 

 

可以看到異常位置對應c code中的

 

5.分析錯誤原因。

a. panic時,寄存器信息如下:

<4>[ 5022.807976] pc : [<ffffff8000ffcd74>] lr : [<ffffff8000ffcd60>] pstate: 20000145

<4>[ 5022.807978] sp : ffffffc040a1b9c0

<4>[ 5022.807982] x29: ffffffc040a1b9c0 x28: 0000000000000001

<4>[ 5022.807989] x27: 0000000000000000 x26: 0000000000000000

<4>[ 5022.807994] x25: 0000000000000002 x24: 0000000000000002

<4>[ 5022.808000] x23: ffffffc040a1bb60 x22: 000000000000001f

<4>[ 5022.808006] x21: 00000000000000b0 x20: ffffff8008fac688

<4>[ 5022.808011] x19: ffffff800c6d5180 x18: 0000000000000000

<4>[ 5022.808017] x17: 0000000000000000 x16: 0000000000000000

<4>[ 5022.808022] x15: 000000007ffff000 x14: 0000007fffffffff

<4>[ 5022.808028] x13: ffffffc0452b1000 x12: 0000000000000000

<4>[ 5022.808034] x11: ffffff8008fbc000 x10: 00000000000008a0

<4>[ 5022.808039] x9 : ffffffc040a1bb40 x8 : ffffffc040a1bbd0

<4>[ 5022.808045] x7 : 0000000000000000 x6 : ffffffc040a1b910

<4>[ 5022.808051] x5 : ffffffc073633090 x4 : 0000000000000000

<4>[ 5022.808056] x3 : ffffff8008122df8 x2 : ffffff800c6d2000

<4>[ 5022.808062] x1 : 00000000000000b0 x0 : 00000000000000b0

b. panic時,執行的指令為:

 

madd為匯編的乘和運算,xd = xn1 * xn2 + xn3;

因此有:

x1 = 0xb0;

x2 = ffffff800c6d2000;

x19 = 0x48;

x19 = x1 * x19 + x2 = 0xb0 * 0x48 + ffffff800c6d2000;

c. 對*(x19 + 455) = *w0時出錯,因此可能是x19地址不合法。而x19不合法則可能是上面的計算出現異常。

對照C語言和匯編可以看到。

 

X19=0x48表示stHDMIPollingInfo的機構提大小,而x1=0xb0表示HDMI_GET_PORT_SELECT(enInputPortType)的計算結果,x2=ffffff800c6d2000表示pHDMIRxResourcePrivate的起始地址,#455表示ucHDMIInfoSource的offset。

在上面計算中,僅0xb0是可變項,也是傳入參數轉換而來,因此可能是0xb0溢出。

d. HDMI_GET_PORT_SELECT的定義如下:

 

其中INPUT_PORT_DIV0=80,因此a = 80 + 0xb0 = 256, a在匯編中為x1, x1的取值為uxtb w1, w19,所以a為uchar類型,而uchar類型的256即是0,做a-INPUT_PORT_DVI0的目的是為了得到0~3 4個input DVI source,因為stHDMIPollingInfo只有4組數據。

 

因此HDMI_GET_PORT_SELECT(enInputPortType)的值只能為0,1,2,3。

 

0xb0的結果會使程序越界讀取數據,因此會出現內存越界的錯誤,需要檢查輸入值不是80~83的原因。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM