Saturday, April 23, 2011

WinDbg:手把手教你看C++ Exception

不管是用WinDbg打開一個Dump File或是Live Debug,如果遇到的是C++ Exception的話,WinDbg就會丟出C++ EH exception的訊息。

(abc.2dc): C++ EH exception - code e06d7363 (first/second chance not available)
eax=073bee80 ebx=03bb12f0 ecx=00000000 edx=00000000 esi=073bef08 edi=0000005c
eip=7c812afb esp=073bee7c ebp=073beed0 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
kernel32!RaiseException+0x53:
7c812afb 5e              pop     esi
0:055> kn
 # ChildEBP RetAddr  
00 073beed0 78158e89 kernel32!RaiseException+0x53
01 073bef08 647050a6 msvcr80!_CxxThrowException+0x46 [f:\dd\vctools\crt_bld\self_x86\crt\prebuild\eh\throw.cpp @ 161]

如果丟出來的exception不是標準函式庫裡面的exception object的話,用!analyze -v也沒辦法幫你對到exception的資訊。這時候,你可以試著按照以下的步驟操作,找出exception class。

0:055> .exr -1
ExceptionAddress: 7c812afb (kernel32!RaiseException+0x00000053)
   ExceptionCode: e06d7363 (C++ EH exception)
  ExceptionFlags: 00000001
NumberParameters: 3
   Parameter[0]: 19930520
   Parameter[1]: 073bef28
   Parameter[2]: 647261ac

首先,先用".exr -1"印出目前EXCEPTION_RECORD的資訊。根據_CxxThrowException丟出的例外結構,Parameter[0]會是一個0x19930520的Magic Number,表示這是一個C++ exception。而Parameter[1]會是exception object address。至於Parameter[2],存放了_s__ThrowInfo結構的address,裡面會有C++ exception class的資訊,我們需要先看看exception object到底是什麼class type。

0:055> dt msvcr80!_s__ThrowInfo 647261ac
   +0x000 attributes       : 0
   +0x004 pmfnUnwind       : 0x64705cf0     void  testDLL!TestDbException::~TestDbException+0
   +0x008 pForwardCompat   : (null) 
   +0x00c pCatchableTypeArray : 0x647261a0 _s__CatchableTypeArray

知道class type後,就可以傾印出exception object的資訊,看看到底是什麼原因丟出C++ exception。

0:055> dt testDLL!TestDbException 073bef28  
   +0x000 __VFN_table : 0x64722524 
   +0x004 m_nType         : 1
   +0x008 m_iErrorCode     : 0n-536570191

參考資料:

No comments: