Life as a developer at Red Gate has many opportunities! One moment you’re finishing off code in the first release of a new tool and then you move into the .NET division to work with a group of talented but scary-looking individuals. What do you get to work on? A tool for allowing you to debug de-compiled source code in other assemblies than your own, from within Visual Studio.
As a developer there’s a lot to understand when you use the .NET framework and third-party component libraries. You can read the documentation and experiment with API functions, but there’s nothing better for improving your understanding of them than seeing the code and following through as it does its work. Using this tool, you will get to see the code for handling particular corner cases and the many subtle points which are never covered in documentation and are hard to deduce from a static view of the code. For example, I’ve already looked at how ASP.NET queries are processed and how the Windows Forms library interacts with the Windows message loop. With a better understanding of the behaviour of the code, when you find problems in a library, you have a better chance of any workaround not just working in a couple of cases that you’ve had time to test, but all the time.
I’m convinced that programming is an exploratory activity, and that this is a great tool for helping with the exploration.
This will work by adapting the Reflector de-compilation technology and using it to produce a .pdb file that links this generated code to the original assembly. A .PDB file is used by Visual Studio, and stores debugging information about a .NET module such as a list of all symbols in a module with their addresses, the name of the file and the line on which the symbol was declared. Bart talked a little about this project before and Andrew Hunter, aka the master of the dark arts, has been working on it for a while as a background project.
There’s a long way to go, but we’ve started to push harder at this project. As a developer, it’s an incredibly liberating experience to be able to step through the .NET framework at long last. In the past, I too have stared into the haystack of source code using Reflector. Reflector is great, but to understand the behaviour of a system it would be even better if one could see the code paths that are commonly taken and typical values for variables in the various stack frames.
So in this project, there are two sets of tasks to do. Obviously the de-compilation to source and the production of the .pdb file is one of them; the second is to integrate the production into Visual Studio to make it easy for the developer to select the assemblies that they wish to step through.
We can start with a simple project that calls into the framework code.
Hitting F5 runs some code in an add-in before the application starts that scans the solution to find all of the assemblies that are referenced. These are presented to the user, who may choose those that should have a .pdb and source code generated for them. Here I have simply selected the mscorlib.dll
In case you haven’t guessed, this dialog is a placeholder until the proper design is put into place.
Pressing “ok”, dismisses the dialog and Visual Studio walks to the breakpoint that I cunningly preset earlier.
The add-in generated source code and produced a .pdb file. Visual Studio’s search path was also modified to make the .pdb file available, so when we press F11 (to step into), we find ourselves inside the de-compiled code for the .NET framework with the locals window showing the value of the local variable, which Reflector has chosen to name “value”.
Stepping into and onwards, we get further into the framework where we can look at more interesting locals.
We can even set breakpoints.
Given that Reflector supports Visual Basic, after some recent work by Alex, we can instead choose to see the de-compilation in Visual Basic.
At present, there’s even some support for working at the IL level.
Of course the debugging experience isn’t seamless. We probably won’t go to the trouble of scoping the locals, so that only live local variables are displayed, and it isn’t always possible for Visual Studio to calculate the variable values when you are stepping through optimised code. Also Edit and continue will not be supported. However you can change the variable values in the locals window and set the next statement so the user can change the code path.
How close is this to a real product? It is some way off yet, and there are still some unanswered questions as to how well we can generate a .pdb for optimised and obfuscated code. We’re making progress though, and the results are encouraging. Builds are popping out of the build server and unit tests are transitioning between red and green at quite a rate.
And I’m having a great time working on it too!