The Debugger Extension, Part 2: A Use Case & The Problem Setup
November 23rd, 2005

The Debugger Extension

Now that we have a feel for the difficulty of the task, we should probably stop for a moment and reflect. Do we really want to go through with this?

Why would you want to go to all the trouble of writing your own extension? Especially with the SOS extension around, this may seem like an awful lot of effort if you are working with managed code. I would tend to agree, but I have found a few situations where writing an extension was helpful.

The best example I have revolves around a centralized framework for accessing the ASP.NET Cache in a web application, which I authored and which my company is currently using. Each cached item is accompanied by our own metadata. Writing an extension that understood this structure and was able to aggregate cache statistics made it easier to analyze dumps of high-memory situations when thousands of these objects are present. I can only offer my own experience here, but I’m sure many developers have similar functionality.

I think that the arguments for writing an extension become more compelling once you have developed a certain amount of your own framework for doing so (I will try to share some of mine here). It is also a very instructive activity—you can learn a great deal about the way the CLR works by getting your hands dirty.

Now that I’ve hopefully convinced you that this will be a worthwhile activity, let’s come up with a very stupid piece of C# code to study.


    enum Colors : int
    {
        Red = 0,
        Green = 1,
        Blue = 2,
        Purple = 3
    }

    class ArbitraryType
    {
        private Colors _color;
        private int _id;

        public ArbitraryType(Colors c, int id)
        {
            _color = c;
            _id = id;
        }
    }

  

Our job will be to print out statistics about the “Colors” of the ArbitraryTypes in memory.

Before we can do that, we will have to do some investigation so that we understand exactly what we’re looking for. That will be the subject of the next post.


The Debugger Extension, Part 1: What Is a DbgEng Extension?
November 22nd, 2005

The Debugger Extension

A better question to start off might be: “what is DbgEng?” Frequent visitors may have seen me refer to WinDbg and the Debugging Tools for Windows somewhat interchangably. There are actually two other debuggers in the package called CDB and NTSD. CDB, NTSD, and WinDbg are all written on top of the same debugger engine, implemented in dbgeng.dll.

An extension for the debugger engine is a dll with a specific set of exported functions. Commands that are callable from the debugger are implemented as additional exported functions. SOS, SieExtPub, and other modules I may have mentioned before are all debugger extensions in this vein. The full syntax for calling an extension function from within the debugger is:

![module].[function] [arguments]

The extension module name is only really necessary if there is a naming collision. For example, if you have several extensions loaded that all define a !help function, you can call the !help function in Son of Strike by typing !SOS.help.

The basics of Writing a Debugger Extension

The DbgEng API is a set of COM interfaces that allow you to interact with both the debugger and the process or crash dump being debugged. It’s a little difficult to find documentation for the interfaces online, but the help files that come with the debugging tools are reasonably complete. The header files in the SDK fill in the remaining gaps. You can get some information from this PowerPoint document.

Understanding the COM interfaces is definitely the simplest aspect of writing an extension, at least from the perspective of developers who have been spending their lives writing code in user mode—not even to mention those accustomed to managed code and Visual Studio. DbgEng requires that your extension be built using the Windows Driver Development Kit (DDK) build environment. One thing I would definitely recommend is DDKBUILD, a freeware batch file that allows you to use the DDK build environment from a Visual Studio makefile project.

As you can see, writing an extension remains something of an arcane activity. Eran Sandler has threatened to create a framework for writing managed debugger extensions, and I hope he does. That would be cool.

It has recently become at least slightly easier to create extensions, in terms of language if not environment. In the most recent debugger update, I found this in the release notes:

New EngExtCpp C++ extension framework … This is a Developer Preview, and APIs are subject to change.

This is the framework I will be using. After setting up the sources, makefile, .def file, and .rc file for my project (I recommend just copying and editing these from one of the debugger SDK samples), all I need to do to create a working—but useless—extension is to define two files.


    // ------------------------------------------------------
    // dmext.h
    //
    #pragma once
    #include "engextcpp.hpp"

    class EXT_CLASS : public ExtExtension
    {
    public:
        EXT_CLASS();
        EXT_COMMAND_METHOD(foo);
    };

    // ------------------------------------------------------
    // dmext.cpp
    //
    #include "stdafx.h"
    #include "dmext.h"

    EXT_DECLARE_GLOBALS();

    EXT_CLASS::EXT_CLASS()
    {
    }

    EXT_COMMAND(foo, "Sample extension command", "")
    {
        this->Out("Hello World.\n");
    }

  

In the next post, after I plead with you for a while that this is still a good idea, we’ll set up a sample problem set to work with.


Exceptions are not a Control Mechanism
November 22nd, 2005

This is a partial debugger trace of an extremely popular and widespread application, used in commercial software by thousands of developers at hundreds of companies including Microsoft. This was happening when the program was functioning normally.

(1230.1234): C++ EH exception - code e06d7363 (first chance)
(1230.1234): C++ EH exception - code e06d7363 (first chance)
(1230.1234): C++ EH exception - code e06d7363 (first chance)
ModLoad: 5c060000 5c072000   C:\WINDOWS\system32\SRCLIENT.DLL
ModLoad: 692c0000 692ee000   C:\WINDOWS\System32\Wbem\framedyn.dll
(1230.1234): Unknown exception - code 80010105 (first chance)
(1230.1234): C++ EH exception - code e06d7363 (first chance)
(1230.1234): Unknown exception - code 80010105 (first chance)
(1230.1234): C++ EH exception - code e06d7363 (first chance)
(1230.1234): C++ EH exception - code e06d7363 (first chance)
(1230.1234): C++ EH exception - code e06d7363 (first chance)
(1230.1254): Unknown exception - code 80010108 (first chance)
ModLoad: 76bb0000 76bb4000   C:\WINDOWS\System32\SFC.DLL
(1230.1234): C++ EH exception - code e06d7363 (first chance)
(1230.1234): Unknown exception - code 8001010e (first chance)
ModLoad: 76bb0000 76bb4000   C:\WINDOWS\System32\SFC.DLL
ModLoad: 5c060000 5c072000   C:\WINDOWS\system32\SRCLIENT.DLL
ModLoad: 692c0000 692ee000   C:\WINDOWS\System32\Wbem\framedyn.dll
(1230.1234): C++ EH exception - code e06d7363 (first chance)
(1230.1234): Unknown exception - code 80010012 (first chance)

I had an A/V problem with this utility that I was trying to debug - this was made basically impossible by the fact that the program was continuing after dozens of other access violations. People, you really are not supposed to do this. I won’t say what application this is, but I will say that I am not going to be using it in the future.