Debugger commands (dt, ??) that make my life easier (part 4)

Today I will cover how to look at type information from the command line of windbg/kd. You can do all of this in the UI with a mouse, but that takes too long ;). I like to keep my hands on the keyboard and not move around. More importantly, by learning the command line way, you can embed commands to execute in a breakpoint statement so that every time the bp is hit, you get all of your information displayed for you without any additional typing. I am going to cover the "dt" and "??" commands.

Here is a C++ program which I will use in demonstrating these commands. Before executing any of the commands, I set a bp on the "return 0;" statement and I am now at that point in the program.

 #include <windows.h>
#include <Stdio.h>

typedef struct _BELOW {
    _BELOW() : One(1) {}
    ULONG One;
} BELOW, *PBELOW;

typedef struct _TOP {
    _TOP(PBELOW Below) : Three(3), Pointer(Below) { Embedded.Two = 2; }

    struct {
        ULONG Two;
    } Embedded;

    PBELOW Pointer;

    ULONG Three;
} TOP, *PTOP;

int _cdecl main(int argc, char *argv[])
{
    BELOW below;
    TOP top(&below);
    ULONG values[4], i;

    for (i = 0; i < sizeof(values)/sizeof(values[0]); i++) { values[i] = i+1; }

    return 0;
}

dt (which stands for display type) is a very powerful command which can perform a lot of expression evaluation for you. You can have it simply dump a local variable [1]. You can refine the output to a specific field [2] or substructure [3] and [4]. Note the difference between the output of [3] and [4], by including the ".", dt will dump all subfields of the structure.

 [1] 0:000> dt top
   +0x000 Embedded         : _TOP::<unnamed-tag>
   +0x004 Pointer          : 0x01002034 _BELOW
   +0x008 Three            : 3

[2] 0:000> dt top Three
   +0x008 Three : 3

[3] 0:000> dt top Embedded
   +0x000 Embedded : _TOP::<unnamed-tag>

[4] 0:000> dt top Embedded.
   +0x000 Embedded  : 
      +0x000 Two       : 2

Even better, dt iterate over an array [5] and can follow pointers from the structure [6]. But what if you want to dump all the fields of the pointer? dt top Pointer->. doesn't work (because it is not a valid C expression). The "??" command comes to the rescue here; you can use it to evaluate the pointer value [7]. Not only will ?? evaluate C or C++ expresssions that contain variables, it can also evaluate expressions using types [8].

 [5] 0:000> dt -a values
     Local var @ 0x6ff68 Type unsigned long[]
     [0] @ 0006ff68
     ---------------------------------------------
     1

     [1] @ 0006ff6c
     ---------------------------------------------
     2

     [2] @ 0006ff70
     ---------------------------------------------
     3

     [3] @ 0006ff74
     ---------------------------------------------
     4

[6] 0:000> dt top Pointer->One
   +0x004 Pointer      : 
      +0x000 One          : 1

[7] 0:000> ?? top.Pointer
struct _BELOW * 0x01002034
   +0x000 One              : 1

[8] 0:000> ?? sizeof(top)
unsigned int 0xc
    0:000> ?? sizeof(_TOP)
unsigned int 0xc

This is just the tip of the iceburg with these commands. I suggest that you open up the debugger help (c:\debuggers\debugger.chm) and look up these commands and their syntax...it is pretty powerful stuff!