读书人

WINCE data abort 内核调试异常分析

发布时间: 2013-03-25 15:43:04 作者: rapoo

WINCE data abort 内核调试错误分析

1、 出错信息:PC=c01cf8ec(gwes.dll+0x0004f8ec) RA=c01cf8e4(gwes.dll+0x0004f8e4) SP=d1e9fde0, BVA=00001002

Gwes.map文件:

……………………………………………………………………………………………………

……………………………………………………………………………………………………

0001:0004e50c ?GlobalFindAtomW_I@Atom_t@@SAGGPBG@Z 1004f50c f gwes_lib:atom.obj

0001:0004e600 ?GlobalGetAtomName@Atom_t@@SAPAGG@Z 1004f600 f gwes_lib:atom.obj

0001:0004e650 ?InitializeUspCE@@YAXXZ 1004f650 f gwes_lib:uspceinit.obj

0001:0004e844 ??0TimerEntry_t@@QAA@PAVMsgQueue@@PAUHWND__@@IIP6AX1IIK@ZPAX_N@Z 1004f844 f gwes_lib:timer.obj

0001:0004e8c4 ?IsValidTimerEntry@TimerEntry_t@@QAA_NXZ 1004f8c4 f gwes_lib:timer.obj

0001:0004e940 ?TimerQueuesRemoveSingleEvent@TimerEntry_t@@SAPAU1@PAUHWND__@@IPAVMsgQueue@@@Z 1004f940 f gwes_lib:timer.obj

0001:0004ea38 ?TimerQueuesRemoveAllMsgQueueOrHwnd@TimerEntry_t@@SAXPAVMsgQueue@@PAUHWND__@@@Z 1004fa38 f gwes_lib:timer.obj

0001:0004eb24 ?SetTimerCommon@TimerEntry_t@@CAIPAUHWND__@@IIP6AX0IIK@ZPAX_N@Z 1004fb24 f gwes_lib:timer.obj

0001:0004ec8c ?TestAndReset@TimerEntry_t@@QAA_N_NPAPAUHWND__@@PAIPAP6AXPAU2@IIK@ZPAJ@Z 1004fc8c f gwes_lib:timer.obj

0001:0004ecdc ?IsFired@TimerEntry_t@@QAA_NXZ 1004fcdc f gwes_lib:timer.obj

0001:0004ece4 ?SetTimer_I@TimerEntry_t@@SAIPAUHWND__@@IIP6AX0IIK@ZPAX@Z 1004fce4 f gwes_lib:timer.ob

Solution:PC=c01cf8ec(gwes.dll+0x0004f8ec) 中0x0004f8ec-00001000=0004e8ec,然后找与之最近的地址,如上在0004e8c4 和0004e940之间,那就是0004e8c4 为开始地址的函数中,那就是这个函数中有问题:IsValidTimerEntry@TimerEntry_

后面的地址1004f8c4 是由0004e8c4 加上1000000再加上00001000得来的

再看下面例子:

今天调试evc程序,总是出现几个莫名奇妙的错误如下:

Data Abort: Thread=8795c908 Proc=80becdf0 'OnLine.exe'

AKY=00000801 PC=03fa006c(coredll.dll+0x0002006c) RA=50616548(???+0x50616548) BVA=18332421 FSR=00000001

FMD_OEMIoControl::Not supported IOCtl : 0x10303FF

FMD_OEMIoControl::Not supported IOCtl : 0x10303FF

或者

Data Abort: Thread=866593e4 Proc=80becd00 'ONLINE.EXE'

AKY=00000401 PC=03fa006c(coredll.dll+0x0002006c) RA=50616548(???+0x50616548) BVA=162f2021 FSR=00000001

Assertion Failed: OnLine: File wincore.cpp, Line 1152

Data Abort: Thread=8795c908 Proc=80becd00 'ONLINE.EXE'

AKY=00000401 PC=03f9fb04(coredll.dll+0x0001fb04) RA=160bf4d8(ONLINE.EXE+0x000af4d8) BVA=2a3b14e9 FSR=00000001

FMD_OEMIoControl::Not supported IOCtl : 0x10303FF

Data Abort: Thread=8795c908 Proc=80becd00 'ONLINE.EXE'

AKY=00000401 PC=03f9fb04(coredll.dll+0x0001fb04) RA=160bf4d8(ONLINE.EXE+0x000af4d8) BVA=2a3b14e9 FSR=00000001

Data Abort: Thread=8795c908 Proc=80becd00 'ONLINE.EXE'

AKY=00000401 PC=03f9fb04(coredll.dll+0x0001fb04) RA=160bf4d8(ONLINE.EXE+0x000af4d8) BVA=2a3b14e9 FSR=00000001

FMD_OEMIoControl::Not supported IOCtl : 0x10303FF

查看coredll.map,

0001:0001e52c HeapCreate 1001f52c f coredll_ALL:heap.obj

0001:0001e668 Int_HeapCreate 1001f668 f coredll_ALL:heap.obj

0001:0001e6c8 CeHeapCreate 1001f6c8 f coredll_ALL:heap.obj

0001:0001ebf4 HeapReAlloc 1001fbf4 f coredll_ALL:heap.obj

0001:0001ec14 HeapAlloc 1001fc14 f coredll_ALL:heap.obj

0001:0001ec34 HeapAllocTrace 1001fc34 f coredll_ALL:heap.obj

0001:0001ec88 Int_HeapAlloc 1001fc88 f coredll_ALL:heap.obj

0001:0001eee8 HeapFree 1001fee8 f coredll_ALL:heap.obj

0001:0001ef08 Int_HeapFree 1001ff08 f coredll_ALL:heap.obj

0001:0001f0e0 HeapSize 100200e0 f coredll_ALL:heap.obj

0001:0001f100 Int_HeapSize 10020100 f coredll_ALL:heap.obj

发现coredll.dll+0x0002006c对应的函数为:

0x0002006c-00001000=0x0001F06C,那么对应的起始函数为 Int_HeapFree ,堆资源释放问题,

同理,coredll.dll+0x0001fb04对应的函数为: CeHeapCreate,堆资源创建问题。

追踪程序发现:plastSaveTime = new char[mea_TotalNumber*7+14],在初始化时mea_TotalNumber =0,

导致实际申请容量与想要使用的不一致,这样操作plastSaveTime 时,操作到别的堆空间了,导致释放别的堆资源出错。

2、

如何定位WinCE产生Data Abort错误的位置

在调试WinCE程序的时候,有时候会碰到Data Abort的异常,系统会在调试控制台输出如下类似信息:

Exception 'Data Abort' (4): Thread-Id=03d3000e(pth=83a9e024), Proc-Id=00400002(pprc=81d48308) 'NK.EXE', VM-active=00fa000a(pprc=83a20ecc) 'explorer.exe'

PC=c0883660(s3c2440disp.dll+0x00003660) RA=a014f780(???+0xa014f780) SP=d2e8fc58, BVA=00000000

对于按Release编译的程序,需要一些额外的工作才能找到产生错误的地方,下面描述了如何根据错误提示信息定位错误代码的过程:

让编译器产生map和cod文件

设置WINCEMAP和WINCECOD两个环境变量,然后重新编译整个项目,我是在BAT文件中加入这两行代码:

set WINCEMAP=1

set WINCECOD=1

计算错误产生的地址

错误产生在s3c2440disp.dll内部,打开文本文件s3c2440disp.map(与s3c2440disp.dll在同一目录),在文件头中,"Preferred load address is 10000000"指出Rav地址为0x10000000,将其与错误产生的偏移地址0x00003660相加,得到Rva+Base地址为0x10003660(0x10000000 + 0x00003660)

找出错误来自哪个文件哪个函数

在s3c2440disp.map文件中,根据Rva+Base地址,得知错误产生于s3c2440disp.obj中的S3C2440DISP::CursorOff成员函数内部

0001:00002274 ?CursorOn@S3C2440DISP@@QAAXXZ 10003274 f s3c2440disp.obj

0001:00002578 ?CursorOff@S3C2440DISP@@QAAXXZ 10003578 f s3c2440disp.obj

0001:000026f4 ?SetPointerShape@S3C2440DISP@@UAAJPAVGPESurf@@0HHHH@Z 100036f4 f s3c2440disp.obj

计算错误在函数中的偏移地址

CursorOff函数起始地址为0x10003578,错误指令在代码中的偏移为0xE8 (0x10003660 - 0x10003578)

找到错误出自哪行代码

打开文件s3c2440disp.cod文件(与s3c2440disp.obj在同一目录),定位到CursorOff函数偏移0xE8处(0x10003660 - 0x10003578, 错误地址-函数开始地址),即可找到了错误发生的汇编代码和对应的C源代码

; 624 : {

; 625 : break;

; 626 : }

; 627 :

; 628 : ptrLine[x * (m_colorDepth >> 3)] = cbsLine[(x - m_CursorRect.left) * (m_colorDepth >> 3)];

000d0 e59430c0 ldr r3, [r4, #0xC0]

000d4 e59420e4 ldr r2, [r4, #0xE4]

000d8 e1a001a3 mov r0, r3, lsr #3

000dc e0463002 sub r3, r6, r2

000e0 e0227093 mla r2, r3, r0, r7

000e4 e021e690 mla r1, r0, r6, lr

000e8 e5d23000 ldrb r3, [r2]

000ec e5c13000 strb r3, [r1]

(错误行的汇编代码表明CPU在读入cbsLine指针指向的数据时发生了异常,经过调试,最终得知错误产生是因为某些情况下cbsLine指针无效而导致Data Abort异常)

读书人网 >WinCE

热点推荐