Since .NET 2.0 is released for about a month, I think its time for me to cover a few new commands that exists in the SOS.dll WinDbg extension that comes with .NET 2.0.
First of all, the current version of WinDbg – 18.104.22.168 – has an SOS.dll that can only work with .NET 1.1, so even if you do load it and try it out it will not find any .NET data in the processes since the internal .NET structures in .NET 2.0 have changed.
To start using the SOS.dll that comes with .NET 2.0 issues the following commands:
.load C:\<Windows Home Directory>\Microsoft.NET\Framework\v2.0.50727\sos.dll
If you are performing a live debug (you have attached to the process), in newer WinDbg versions you can use the following commands
.loadby sos mscorwks
This command will load the sos.dll near the mscorwks.dll that is currently loaded in the process.
Usually newer versions of WinDbg (I always recommend running the latest version of WinDbg 😉 ) contains a newer version of SOS.dll, so you should prefer to use the SOS.dll provided with WinDbg, although currently, the only SOS.dll that supports .NET 2.0 is located in the Framework’s directory, near the mscorwks.dll.
New and interesting commands
- !dumparray – Dumps the content of an array.
The .NET 1.1 version of SOS.dll had a !dumpcollection method which usually didn’t work for me, so it nice to have something that will dump arrays.
- !printexception – If a parameter is given, it will dump that exception, if no parameter is given, it will dump the last exception on the stack.
In .NET 1.1 version of SOS.dll one had to dump the stack objects, find one that is an exception and print it using !dumpobj. Now, all one has to do is call !dumpexception and the last managed exception on the current thread’s stack will be printed out.In addition to that, !dumpexception can now parse the _stackTrace field, which is a binary array if the _stackTraceString is not filled.
!printexception will also notify you if there are nested exceptions (exceptions being thrown inside a catch handler). If you want to see those as well, use the -nested parameter.
- !bpmd – Sets a breakpoint on managed code.
Setting a breakpoint on a managed code prior to .NET 2.0 was very tricky. I covered this issue in a previous post.
In that older post I only covered settings a breakpoint on an already JITed method. Setting a breakpoint on a non-JITed method is even harder. !bpmd will cover all of these aspects.To set the breakpoint all you need to do is provide the module name and method name, or the MethodDesc handle (if you have it).
!bpmd also works on generic types. If a breakpoint is set on a generic type it will break on all derived types.
The only way to set a breakpoint on managed code with ease before .NET 2.0 was to use CorDbg (which I covered in an previous post as well).
- !StopOnException – stops on a particular managed exception.
This functionality was only supported in CorDbg prior to .NET 2.0. Now, instead of breaking on every CLR exception you can specify a specific .NET exception type, such as System.ApplicationException.
- !DumpIL – Dumps the IL code of a method.
This was previously very hard to do. In .NET 2.0 one can always dump the IL code of a method (even at runtime).
The main advantage here is to debug dynamic methods which are built on the fly. Its also useful for dynamically generated types (using Reflection.Emit).
As in previous version of SOS.dll, you can type !help <CommandName> to get detailed help and sometimes examples on that specific commands.