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!

Comments (4)

  1. Mark Steward says:

    dump/display type, surely?  Or is it historically dump tmp, and corrected to display type?

  2. fixed.  thanks for catching the typo, i meant type.

  3. Mark Steward says:

    darn… I thought there’d be some interesting history there.

    Keep up the good blogging!

  4. history of what? the debuggers or WDM?