Sunday, August 22, 2010

DILE feature: loading modules from memory dump files

One of the main reasons why I started to work on dump-debugging support for DILE is that I thought I could add a little twist to it once again.

The problem
If you're using VS2010 for analyzing a dump file then you'll run into a quite serious problem very quickly: if VS can't find the original source code and pdb file of the modules then it will show you only the disassembled x86 code. This can really make life difficult as it's quite difficult to map back those x86 instructions to your actual code to figure out which line caused a problem etc.

The solution
DILE has had a very interesting feature for ages: it can load dynamically generated assemblies from the memory of a debuggee process. What this means is that if your application generates assemblies on-the-fly via Reflection.Emit (compiled RegExes do the same or the XSLT compiler if an XSLT file contains C# code) then DILE can load that assembly and treat it as any other assembly even if it's never saved on the hard disk. And of course, all the usual features like breakpoints, stepping etc also work with such dynamic assemblies.
So obviously I wanted to do the same with dump files since they usually contain the full memory of the debuggee, including loaded modules. Fortunately it was quite easy to modify the code to load modules from the memory of the debuggee process (i.e. from the dump file) instead of looking for them on the hard disk. Although fixing the UI wasn't trivial but that's a long story. :-)

Usage
If you download the latest weekly build of DILE and load a dump file in it then you will notice that there's a new menu item in all context menus related to modules: "Add module to project from memory dump". If you click on this option then DILE will read the module from the dump file and not from your local hard drive.

Why is this cool?
As a result you don't have to worry anymore about what version of your application crashed when you created the dump file, you don't have to know what patches were applied on your application/3rd party components/.NET Framework and most importantly you don't have to have exactly the same version of all components on your machine when you're dump debugging. DILE will show you the state of your application _exactly_ as it was when the dump file was created. And that makes finding bugs a lot easier. :-)

Update:
The Screenshots
Alex suggested in the comments section adding screenshots to this post which is definitely a good idea. I used to upload files to FreeWebTown but let's say... I'm not really satisfied with them. They simply deleted my account without any warning so all the files that I had there are lost. Unfortunately I don't have backups as well because over the years I had a few unplanned hard disk crashes etc.
Anyway... I've realized that I can also upload files to SourceForge. I trust them more. :-)
So, the screenshots:



Opening a memory dump file

Loading module from the memory dump file in the Modules Panel



Loading module from the memory dump file in the Call Stack Panel

Loading module from the memory dump file in the Object Viewer

Labels: , ,

Sunday, August 01, 2010

Dump-debugging in DILE

I have spent the last few weeks on trying to get dump debugging working in DILE. At last, I have something that is working quite well. However, I have to warn everyone who wants to try the latest weekly build: I had to modify quite a lot of things (especially in the UI) and as a result I might have broken features that affect "live" debugging as well. So, I strongly recommend using the latest build really only for experimenting.

Enough of excuses. Here is what you get if you give the latest version a try.

Save memory dump
If you click on the File menu then you will see that there's a new item called "Save memory dump". This feature allows you to dump the memory of any (managed or unmanaged) process. Under the hood it's really just a call to a Win32 function to create the memory dump file.
Usage:
1. Click File -> Save memory dump...
2. Enter the Id of the target process or select it using the Browse... button.
3. Select a dump type. You can find detailed description of what these flags mean in MSDN. In most cases, leaving the default selection is perfectly fine.
4. Select the location where the memory dump file will be saved.
5. Click Save. You're done.

Rules:
- You can dump the memory of both managed and unmanaged processes.
- The target process doesn't have to be paused or being debugged. (although taking a memory dump of a process that is running doesn't sound very useful)
- The result memory dump file is completely standard. You can load it in VS2010, WinDbg, DILE or any other debugger.

Load memory dump
This is the really interesting bit. Once you have a dump file, you can copy it to any machine, load it in DILE and check the status of the target process as it was when you made the dump. DILE is using the same API as VS2010 so you get the same features (more or less).
Usage:
1. Click File -> Load memory dump...
2. Select your dump file and click Open.
3. At this point DILE switches into a state that is very similar to what you get when you pause a live process.

Rules:
- Only .NET 4.0 target processes are supported.
- You can see threads, modules, call stack, local variables, arguments and current exception. You can inspect variables using the Object Viewer, switch between threads and frames in the call stack and so on. So you get all the usual features.
- Obviously, you can't step in the code or run the process as there's no live process.
- For now, assemblies are loaded from your hard disk and not from the memory dump. Therefore if an assembly is not exactly at the same location as it was on the original computer then you will have to help DILE and load it manually. (I'll try to fix this later.)
- Unfortunately you can't evaluate method calls.

The latter is quite a serious limitation and I know VS2010 supports it. I think, VS uses a so called "IL interpreter" but I couldn't find any information about it. I'm afraid it's not a proper public API but rather a feature in VS2010 that is not exposed to anyone else. I've already asked about it in an MS forum and currently my question is assigned to Jon Langdon (PM of the debugger team) but I haven't received any reply yet. So, please vote on my thread, perhaps it will help me to get an answer faster. :)

Anyway, that's what I have for now. Have fun with DILE and dump-debugging. And as always, please let me know if you find any bug related to memory dump or live debugging. Or anything else. :)

Labels: ,