COM/C++ Programming – the modern way

For a new project I’ve been working on I was forced into working with the world of C++ and COM for a sizable portion of it.  In my past life I’d previously worked on some large-ish projects involving COM (office interop in particular), but never on a fresh codebase from the ground up.

SPT - x86 Release

Read more about SPT here

I've compiled the latest build of SPT for x86.  All functionality should be working fine, but since I don't do much x86 debugging it hasn't been as thoroughly tested as the x64 build.  Let me know if you run into any issues.

This is actually a later build than the x86 version and has some enhanced features, like !findtimers to dump all the active timer objects in the process and enhanced output for some commands.  I'll get the x64 version update posted soon as well.

Download it here

SPT Series Part 0 - Supporting methods

Before I begin talking about how I've implemented some of the commands in SPT, I need to talk about some of the supporting methods that make doing things much easier.  The IXCLRDataProcess/Dacp*Request API is not very user friendly and very verbose, by creating wrappers around them, we can spend more time building extensions and less time worrying about implementation.

The first thing we need to do is get an instance of an IXCLRDataProcess.  This is the core interface we'll be using for everything.  See my previous posts for more information on it.  Conveniently, WinDBG has a semi-undocumented IoCtrl request to give us an instance of this object.  It internally handles creating an ICLRDataTarget implementation, finding and loading the correct mscordacwks dll, and calling CLRDataCreateInstance for you.  Using it is simple, the IoCtrl request code is documented, so we simply need to make a request and call Ioctl. (Note: Ioctl is defined in wdbgexts.h)

HRESULT InitIXCLRDataFromWinDBG(IXCLRDataProcess **ppDac)
{
    WDBGEXTS_CLR_DATA_INTERFACE ixDataQuery;

    ixDataQuery.Iid = &__uuidof(IXCLRDataProcess);
    if (!Ioctl(IG_GET_CLR_DATA_INTERFACE, &ixDataQuery, sizeof(ixDataQuery)))
    {
        return E_FAIL;
    }

    *ppDac = (IXCLRDataProcess*)ixDataQuery.Iface;
   
    return S_OK;
}

Getting the managed System.Threading.Thread instance for a native thread object (ThreadObj)

There are times when I’ve needed to find the managed thread object backing the native object output in !threads.  The way I used to get it was to dump all thread objects (!dumpheap -mt <thread MT>) and match the managed thread Id field with the output from !threads.  However, there’s a better way. 

Building a mixed-mode stack walker - Part 1

A project I’ve been working on recently is a tool to capture the stack trace of all running threads in a process. The tool is used in response to a monitoring event to gather information about the process at the time of the event firing. Gathering this information needs to be fast (sub-second, preferably < 100ms), so using CDB, loading SOS (or sosex) and running ~*e!clrstack or ~*e!mk or similar wasn’t an option, since it takes far too long. Also, as a secondary goal I wanted to be able to allow this to operate on a dump file as well as a live process, and also be as non-invasive as possible. That ruled out using the CLR profiling APIs or MDbg (as a side note, it seems like MDbg tends to randomly kill OS handles in the process it’s attached to).

Pagination


© 2023. All rights reserved.