Windbg QuickStart guide (Part 4 - Debugging unexpected program behavior)
First Chance Exceptions
Let’s assume I have written some really ugly code like what you see here:
1: int i = 0;
2: try
3: {
4: i = int.Parse(args[0]);
5: }
6: catch
7: {
8: Console.WriteLine("Invalid Argument");
9: }
10: Console.WriteLine(i);
When the user executes the program with invalid arguments, all he will see is an error that the argument is invalid, let’s execute the program with “1”, the user is expecting the output to be 1, but he gets a zero, yet there is no error or exception.
In this case you need to catch the first chance exception, i.e. you want to break when an exception happens even if it is handled in the code.
To break on first change exception you use the sx command, From MSDN documentation:
The sx* commands control the action that the debugger takes when an exception occurs in the application that is being debugged, or when certain events occur.
In this case we want to break on an exception, so we use sxe and since we are interested in CLR exceptions we do sxe clr
0:000> sxe clr
0:000> g
Once I enter my input I see this:
(182c.163c): CLR exception - code e0434352 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=001aedc4 ebx=00000005 ecx=00000005 edx=00000000 esi=001aee84 edi=00000001
eip=7613b9bc esp=001aedc4 ebp=001aee14 iopl=0 nv up ei pl nz ac po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000212
KERNELBASE!RaiseException+0x58:
7613b9bc c9 leave
If I do !pe – this is what I get:
0:000> !pe
Exception object: 02563754
Exception type: System.FormatException
Message: Input string was not in a correct format.
InnerException: <none>
StackTrace (generated):
<none>
StackTraceString: <none>
HResult: 80131537
To see the stack, I do !clrstack
0:000> !clrstack
OS Thread Id: 0x163c (0)
Child SP IP Call Site
001aeed8 7613b9bc [HelperMethodFrame: 001aeed8]
001aef94 6be0d5b4 System.Number.StringToNumber(System.String, System.Globalization.NumberStyles, NumberBuffer ByRef, System.Globalization.NumberFormatInfo, Boolean) [f:\dd\ndp\clr\src\BCL\System\Number.cs @ 1029]
001aefbc 6b41bad2 System.Number.ParseInt32(System.String, System.Globalization.NumberStyles, System.Globalization.NumberFormatInfo) [f:\dd\ndp\clr\src\BCL\System\Number.cs @ 712]
001af088 6b48bc20 System.Int32.Parse(System.String) [f:\dd\ndp\clr\src\BCL\System\Int32.cs @ 140]
001af094 002e008a BuggyApp.Program.Main(System.String[]) [d:\Projects\BuggyApp\Program.cs @ 15]
001af23c 6f5855e2 [GCFrame: 001af23c]
Another way to do this is to tell the debugger the execute !pe and !clrstack immediately after seeing the exception:
This is the debugger input:
0:000> sxe -c "!pe;!clrstack" clr
0:000> g
(828.d2c): C++ EH exception - code e06d7363 (first chance)
(828.d2c): CLR exception - code e0434352 (first chance)
Exception object: 025e2268
Exception type: System.IndexOutOfRangeException
Message: Index was outside the bounds of the array.
InnerException: <none>
StackTrace (generated):
<none>
StackTraceString: <none>
HResult: 80131508
OS Thread Id: 0xd2c (0)
Child SP IP Call Site
0028ed84 7613b9bc [HelperMethodFrame: 0028ed84]
0028edf4 00320082 *** WARNING: Unable to verify checksum for BuggyApp.exe
BuggyApp.Program.Main(System.String[]) [d:\Projects\BuggyApp\Program.cs @ 15]
0028ef9c 6f5855e2 [GCFrame: 0028ef9c]
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0028ec44 ebx=00000005 ecx=00000005 edx=00000000 esi=0028ed04 edi=00000001
eip=7613b9bc esp=0028ec44 ebp=0028ec94 iopl=0 nv up ei pl nz ac pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000216
KERNELBASE!RaiseException+0x58:
7613b9bc c9 leave
Breaking on unexpected module load
Another common scenario is when a dll is loaded and you have no idea who is loading it, in this case you want to break when a dll is loaded
0:000> sxe ld mydll
0:000> g
When the module is loaded
ModLoad: 6f580000 6fc03000 C:\path\mydll.dll
eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=7efdd000 edi=003cf400
eip=77d7fc42 esp=003cf2d4 ebp=003cf328 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!NtMapViewOfSection+0x12:
77d7fc42 83c404 add esp,4
Now you can check the stack to see who is responsible for loading it
Placing a managed breakpoint
!Name2EEMicrosoft_TeamFoundation_Framework_Server!Microsoft.TeamFoundation.Framework.Server.TeamFoundationApplication
!DumpMT -MD 000007ff0030fe28 <-- From the output of the previous command
!bpmd -md 000007ff0030fd50 <-- From the output of the previous command
Hope you find that helpful, feel free to post any questions!
Comments
Anonymous
March 15, 2012
Did you mean to do the following? i = int.Parse(args[0]); Instead of just int.Parse(args[0]); ? In any case, I love learning about windbg. Thanks for this series!Anonymous
March 15, 2012
Hi Matt, thanks for the correction, I fixed the post:) Feel free to let me know if there is anything you would like to see covered in this series:)Anonymous
April 22, 2012
Hi, I wanted to know if we can take full memory dump of a single module (say a loaded driver) using windbg kernel debugging.Anonymous
June 27, 2012
Hi abhijit , I don't know of a way to do that.Anonymous
June 28, 2016
Just wanted to say thank you for your Windbg 'tutorials', they have proved most helpful in my gaining a fundamental understanding of debugging and Windbg.