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的原因。