Did you know that you can use SOS from within Visual Studio 2005, not just from WinDbg?
It has been previously discussed in a couple of places but most people don’t know it is possible to do that.

“Why should I use the SOS extension from within Visual Studio?”, you are probably asking.
The answer is quite simple.

Visual Studio is a rich debugger that shows us most of the information we want to know but it doesn’t show us a few important things like the actual size of an object and all of its references and who is referencing our object. While these things are not straight forward in Visual Studio, they are very easy to accomplish in SOS. For example, you can run the following command in SOS:

  • !objsize – to find out the actual size of the object and all of its referenced objects
  • !gcroot – to find who is referencing our object
  • !dumpheap – to see what’s all the stuff that we have on the heap. By using the -gen [generation number] parameter with !dumpheap, we can see all the objects that are currently in that generation
  • !SyncBlk – find out which managed locks are locked at the moment (I’ve talked about it before)

So, how do we actually do that?

Well, the first thing you need to do is enable “unmanaged debugging” by going to the “Project Properties” -> “Debugging” -> “Enable Unmanaged Debugging”.

After doing that, you can stop somewhere in your program, open the “Immediate” window (Debug -> Windows -> Immediate) and type:

.load sos

This will load the SOS extension. From there on you have most of the commands of the SOS extension at your disposal.
You might need to set the symbols path by calling .sympath, just like you would do in WinDbg.

An added bonus to this whole thing is that it also works on Visual Studio 2003, so you get to use it even with .NET Framework 1.1.

Yun Jin has this piece about the different special threads in the CLR on his blog.
It coverts the different special threads in both the .NET Runtime as well as the open source Rotor shared source implementation.

It’s a bit of an old post, but I just found it. It has a nice summary of all the different special threads that the CLR creates in various stages and situation.

Some of the threads being mentioned there include:

  • The Finalizer thread. We discussed this a while back in the post about the blocked finalizer thread issues.
  • The Debugger helper thread
  • Concurrent GC thread – Used in a non server GC scenario and enables to collect garbage without freezing up the application.
  • Server GC threads – The specialized GC threads used in the server GC (one per logical, not physical, CPU)

Interesting stuff.

I wanted to notify the Israeli audience of this blog that I’ll be giving a lecture titled “Production and Post Mortem Debugging in .NET using WinDbg” on the Israeli Visual Basic User Group (IVBUG) led by Jackie Goldstein.

This is mainly an overview lecture that will include an introduction to production and post mortem debugging using .NET, some talk about .NET internals, so we will know what we are looking at in WinDbg and some proven methodologies for common issues in production environment that can be easily found, traced, identified and debugging using only WinDbg.

The lecture will take place on March 1st, 2006 at 18:00 at

Microsoft Israel
2 Hapnina St.
Floor 0, Dekel Room

You’ll need to confirm your attendance by Emailing to IVBUG AT renaissance.co.il (replace AT with @ sign).

Hope to see you there!

Francisco Martinez has some interesting tools that he developed to make it a bit easier to develop to .NET application to Mono using Visual Studio .NET.

These tools allow you to create a makefile from a Visual Studio project file enabling you to build the project in a complete Mono environment as well as import and export MonoDevelop project files from and into Visual Studio Project files.
It will also enable you to run your compiled code under Mono instead of the Microsoft .NET Runtime directly from the Visual Studio IDE.

I’ve been following the Mono project since its inception and it has come a long way since.

I know there are (and are going to be) a lot of legal issues that can do a lot of problems in regards to the project, but I still think its a necessary and welcome addition to the development platforms available on the different Linux flavors and UN*X operating systems.

I wonder if someone is planning to write a WinDbg extension to handle Mono 😉
Though I’m not sure there will be a lot of market for it. People will probably use the Microsoft .NET Runtime for Windows development and/or deployment and Mono for a Non Windows development / Deployment.

I guess only time will tell 🙂

Yesterday I got a question to my Email from David Douglass, a reader of this blog.
David asked me how can he see the threads waiting on a certain managed lock and that he was trying to accomplish that using WinDbg and the SOS that shipped with .NET Framework 2.0.

I told David that he should use the !SyncBlk command and that I talked about it in a previous post but never actually used it in .NET Framework 2.0. I also suggested that if he is still having problems I’ll look into it a bit more using the sample I provided in the previous post.

Before I had a chance to do anything, David replied saying that he checked this issue with Tess Ferrandez (Tess is an Escalation Engineer in the PSS (Product Support Services) at Microsoft) and that the answer he got was that the version of SOS shipped with .NET Framework 2.0 does not have the ability to show on each managed lock which threads are waiting on it like the SOS that shipped in newer version of WinDbg.

When typing !help SyncBlk in WinDbg (after load the SOS extension of .NET 2.0 of course) the help states that there is a way to verify that, but it requires a bit of disassembling.

I think I found a better way of doing that and I’ll present it here. The code is based on the sample from the post about identifying dead lock in managed code and you can download the source code from here.

The sample I use here basically deadlocks two thread which are both waiting on resources held by the other thread.

Runing !SyncBlk shows me this:

Index SyncBlock MonitorHeld Recursion Owning Thread Info SyncBlock Owner
12 0017a6a4 3 1 0018a1b0 efc 5 01371c38 System.Object
13 0017a6d4 3 1 00189df0 19f4 4 01371c2c System.Object
Total 13
ComClassFactory 0
Free 1

We see here that thread “efc” is the owner of the lock on SyncBlock 01371c38 and thread “19f4” is the owner of the lock on 01371c2c.
If we want to check which lock thread “efc” is trying to acquire all we need to do is run “~~[efc]kv” (do mind that I use kv to see the arguments being passed to the methods) and we should look for the method “mscorwks!JIT_MonEnterWorker_Portable“. If I’m not mistaken (and I do hope I’m not 😉 ), the first argument (the number showing on the “Args” column) should be the SyncBlock we are trying to acquire.

So in our case, on thread “efc” we should see that the first args of is “mscorwks!JIT_MonEnterWorker_Portable” 01371c2c.

I have not contacted anyone from Microsoft to validate my claims here (yet) but I will update the post if necessary.

Just a reminder: Do mind that when you will run the sample the addresses and thread number will probably be different.

If you are stuck in a problem or have a question, feel free to Email me to eran AT sandler . co . il and I’ll do my best to supply you with an answer.

According to this post in Jochen Kalmach’s blog, the new (beta) version of WinDbg – that I’ve mentioned earlier in a couple of posts support mini real dumps.

This means that instead of taking a full memory dump (its not actually full because you don’t take the kernel space) which can be up to the size of the current process (and in server applications it can reach to a few hundreds of MB), you can take a small, light weight mini dump that contains only minimal information such as call stacks.

This previously worked in unmanaged environments but from this version it also works on managed and mixed environments.

I’m still trying to find the original source of this information (Jochen, can you help on this? 🙂 ), but after tracking Jochen’s blog for a while he does know what he is doing.

Jochen was kind enough (again) to post a comment in the previous post that there are at least 3 major issues with the new version of WinDbg.

You can find some of the issues here, here and here.

It seems that all problems stem from the fact that this version was not marked as beta.

I personally didn’t have time to test the new version with some custom extensions, but the responses I’ve been seeing in the newsgroups are a bit too aggressive.

I would like to send a bit kudos to all of the WinDbg team and congratulate them on their work.
If you know (or not), WinDbg is the most used debugger within Microsoft and with such a small team they are doing a heck of a job.

There is no need to panic too much and be too blunt about it. I’m sure each and every one of the team members of WinDbg will be more than happy to address any issues that may be caused in the new beta version.

This is a product like any other product and perhaps by moving to a releases model that is similar to the CTPs of the new parts in Vista would be a bit better.

Release more and release often to a small community that will help the team test and achieve a better test matrix coverage. No need to bitch about it if each and every one of us can lend a hand/computer/head/OS or two.

I just hope some of the WinDbg team members see this post… 🙂

Jochen Kalmbach was kind enough (thanks Jochen!) to point in a comment to my previous post that release is a BETA version of WinDbg.
He also pointed out this post in the WinDbg newsgroup that confirms this information.

Sorry for not finding this out just now, but it seems the only place that the word “beta” was written was in the “redist.txt” file in the installation folder.

It seems that some code Jochen wrote doesn’t work with the new version of DbgHelp.dll so there are a few things you should watch out in betas…
I personally like to live on the bleeding edge when it comes to WinDbg so I usually do care if a version is a beta or not. On the other hand, I can sympathize with Jochen’s frustration about using a new beta version and finding out something is broken…

Oh well… I’m sure this will get fixed very soon.

I just wish WinDbg releases were a bit more often than every 6 to 9 months.

A new version of WinDbg (version was released a couple of days ago.
Download it from here.

You can read some of the highlights of the new version here.

For some reason, the only SOS.dll that comes with this release (as in previous releases) is for .NET Framework 1.1 only, so there is no new SOS.dll for .NET Framework 2.0 yet.

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 – – 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.