MANAGED DEBUGGING with WINDBG. Breaking on an Exception. Part 1
Hi all,
This post is a continuation of MANAGED DEBUGGING with WINDBG. Managed Heap. Part 5.
BREAKING ON AN EXCEPTION. Part 1
We can only break on exceptions when doing live debugging, but many of the commands explained here can be used when doing dump analysis, too.
· Exceptions we may get in .NET applications:
§ CLR exception (0xe0434f4d).
§ Stack Overflow exception (0x800703e9).
§ Access Violation (0xc0000005).
§ Integer divide-by-zero exception (0xc0000094).
§ ...
§ Fatal Execution Engine Error (<address of failure>). This normally indicates a bug in CLR or NT Heap corruption when doing P/Invoke with not big enough buffers. The address associated to this exception will tell us where in the code the issue happened.
The debugger will break by default when the process raises most of these exception types, but not on CLR exceptions, for instance.
In ASP.NET, if exceptions are raised in managed threads and they are unhandled, Global Error Handle catches them. But if they are raised in another thread like Timer or Finalizer threads, we will crash the process (it will be recycled).
· We can break on any CLR exception:
When our code raises a CLR exception, we see the following line in the debugger:
(1728.1f58): CLR exception - code e0434f4d (first chance)
Unmanaged world doesn’t know about specific CLR exception types, so all of them are raised with the same exception code: 0xe0434f4d.
As we’ve seen, WinDbg won’t break on any CLR exception by default, as they may be expected. We can break on all CLR exceptions with any of these commands:
0:000> sxe clr
0:000> sxe 0xe0434f4d
And when we break we’ll see something like this:
0:000> g
(1728.1f58): C++ EH exception - code e06d7363 (first chance)
(1728.1f58): CLR exception - code e0434f4d (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=002de8e0 ebx=e0434f4d ecx=00000001 edx=00000000 esi=002de968 edi=0047c600
eip=77a1b09e esp=002de8e0 ebp=002de930 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000212
KERNEL32!RaiseException+0x58:
77a1b09e c9 leave
· We can break on a specific CLR exception type:
If we know the exact exception type, we can do the following:
0:004> !StopOnException -create System.IndexOutOfRangeException 1
Breakpoint set
0:004> !soe -create System.IndexOutOfRangeException 1
Breakpoint set
And when we break we’ll see something like this:
0:000> g
(1728.1f58): C++ EH exception - code e06d7363 (first chance)
(1728.1f58): CLR exception - code e0434f4d (first chance)
'System.IndexOutOfRangeException hit'
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
...
77a1b09e c9 leave
We can also stop only on those exceptions which type derives from a given one:
0:004> !soe -derived -create System.SystemException 1
Breakpoint set
· When we break, we can inspect the CLR exception:
Let’s take a look to the call stack of the thread which raised the exception when the debugger breaks:
0:000> kpL
ChildEBP RetAddr
002de930 79f071ac KERNEL32!RaiseException(unsigned long dwExceptionCode = 0xe0434f4d, unsigned long dwExceptionFlags = 1, unsigned long nNumberOfArguments = 1, unsigned long * lpArguments = 0x002de968)+0x58
002de990 79f9293a mscorwks!RaiseTheExceptionInternalOnly(class Object * throwable = 0x01940e4c, int rethrow = 0, int fForStackOverflow = 0)+0x2a8
002de9c8 7a129a34 mscorwks!UnwindAndContinueRethrowHelperAfterCatch(class Frame * pEntryFrame = 0x002dea20, class Exception * pException = 0x004d2aa8)+0x70
002dea68 00b81aad mscorwks!JIT_RngChkFail(void)+0xb0
002deab0 00b819fe WindowsApplication1!WindowsApplication1.Form1.PlayWithArray(<HRESULT 0x80004001>)+0x55
KERNEL32!RaiseException raises the generic CLR exception (0xe0434f4d) to the unmanaged world, but the specific exception we are getting is the one that mscorwks!RaiseTheExceptionInternalOnly raises. We can inspect that specific exception as any other .NET object:
0:000> !DumpObj 0x0195fe94
...
0:000> !do 0x0195fe94
Name: System.IndexOutOfRangeException
MethodTable: 79117f8c
EEClass: 79117f1c
Size: 72(0x48) bytes
(C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Fields:
MT Field Offset Type VT Attr Value Name
790fd8c4 40000b5 4 System.String 0 instance 00000000 _className
7910ebc8 40000b6 8 ...ection.MethodBase 0 instance 00000000 _exceptionMethod
790fd8c4 40000b7 c System.String 0 instance 00000000 _exceptionMethodString
790fd8c4 40000b8 10 System.String 0 instance 01935108 _message
79116114 40000b9 14 ...tions.IDictionary 0 instance 00000000 _data
790fdf04 40000ba 18 System.Exception 0 instance 00000000 _innerException
790fd8c4 40000bb 1c System.String 0 instance 00000000 _helpURL
790fd0f0 40000bc 20 System.Object 0 instance 00000000 _stackTrace
790fd8c4 40000bd 24 System.String 0 instance 00000000 _stackTraceString
...
79102290 40000c1 38 System.Int32 0 instance -2146233080 _HResult
790fd8c4 40000c2 30 System.String 0 instance 00000000 _source
...
0:000> !do 01935108
Name: System.String
MethodTable: 790fd8c4
EEClass: 790fd824
Size: 102(0x66) bytes
(C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: Index was outside the bounds of the array.
Fields:
...
Or we can inspect the exception in a more user friendly way:
0:000> !PrintException 0x0195fe94
...
0:000> !pe 0x0195fe94
Exception object: 0195fe94
Exception type: System.IndexOutOfRangeException
Message: Index was outside the bounds of the array.
InnerException: <none>
StackTrace (generated):
<none>
StackTraceString: <none>
HResult: 80131508
We can save some time if we directly inspect the last thrown exception on the current thread:
0:000> !pe
Exception object: 0195fe94
Exception type: System.IndexOutOfRangeException
Message: Index was outside the bounds of the array.
InnerException: <none>
StackTrace (generated):
<none>
StackTraceString: <none>
HResult: 80131508
Next post: MANAGED DEBUGGING with WINDBG. Breaking on an Exception. Part 2.
Index: MANAGED DEBUGGING with WINDBG. Introduction and Index.
Regards,
Alex (Alejandro Campos Magencio)
Comments
- Anonymous
May 04, 2011
Is it also possible to stop on all exceptions but a specific type?I have some code here which throws lots of exceptions of a specific type but catches them. I am looking for another problem which is not analyzed yet, so I need all other exceptins. - Anonymous
May 04, 2011
This command will make Windbg to break on all .NET exceptions except System.IndexOutOfRangeException:sxe -c "!soe System.IndexOutOfRangeException 3; .if(@$t3==1) {g} .else { !pe }" clrI hope it helps.