Debugging Tools for Windows

dt (Display Type)

dt命令显示局部变量、全局变量或数据类型的信息。它也可以仅显示数据类型。即结构和联合(union)的信息。

语法

用户模式语法

dt [-DisplayOpts] [-SearchOpts] [module!]Name [[-SearchOptsField] [Address] [-l List
dt [-DisplayOptsAddress [-l List
dt -h 

内核模式语法

[Processordt [-DisplayOpts] [-SearchOpts] [module!]Name [[-SearchOptsField] [Address] [-l List
dt [-DisplayOptsAddress [-l List
dt -h 

参数

Processor
指定运行包含需要的信息的进程的处理器。更多信息,查看多处理器语法。处理器只能在内核模式时指定。
DisplayOpts
指定下表中给定的一个或多个选项。这些选项以连字符开头。
选项 说明
-a[quantity] 在新行中显示每个数组成员和它的序号。共显示quantity 个成员。在aquantity 间不能加入空格。如果-a后面没有跟数字,则数组中的所有成员都会显示出来。-a[quantity]开关必须紧跟在每个希望按这种方式显示的类型名或字段名后面。
-b 递归的显示块。如果被显示的结构包含子结构,它的所有层次也会被递归的展开并完整显示出来。指针仅在原始结构中显示出来,而不当作子结构展开。
-c 紧凑输出。如果可能的话将所有字段都显示到一行中。(当和-a开关一起使用时,每个数组元素都占据一行而不是被格式化为一个多行的块。)
-d When used with a Name that is ended with an asterisk, display verbose output for all types that begin with Name. If Name does not end with an asterisk, display verbose output.
-e 强制dt枚举类型。该选项仅在dt错误的将NAME当作一个实例而不是类型时使用。
-i 不对子类型进行缩进。
-o 省略掉结构字段的偏移值。
-p Address是一个物理地址,而不是虚拟地址。
-r[depth] 递归的转储子类型字段。如果给定了depth ,递归达到一定深度时就会停止。depth 必须是1到9之间的数字,并且在rdepth 之间不能包含空格。-r[depth] 必须紧靠在地址的前面现。
-s size 仅列举大小的字节数等于size 值的类型。-s 仅在枚举类型时有用。当指定了-s 时,-e 也被隐含的指定了。
-t 仅列举类型。
-v 详细输出。这会输出结构的总大小和字段数量这样的附加信息。当它和-y选项一起使用时,所有的符号都会被显示出来,即使他们没有任何关联的类型信息。

SearchOpts
指定下表中的一个或多个选项。这些选项以连字符开头。
选项 说明
-n 表明下个参数是一个名字。当下一个参数完全由16进制字符组成时使用,否则它会被当作一个地址。
-y 表明下一个参数是一个名字的开头,而不一定是整个名字。包含-y时,所有匹配项都会列出来,并在列表中第一个匹配项后面显示详细信息。如果没有包含-y,只有精确匹配的项会显示。

module
用于指定定义该结构的模块的可选参数。如果有一个局部变量或类型的名字和全局变量或类型的名字相同,则需要包含module 来表明它是全局变量。否则,dt命令会显示局部变量,即使和局部变量是不区分大小写的匹配而全局变量是区分大小写的匹配。
Name
指定类型或全局变量的名字。如果Name以星号(*),结尾,所有匹配项都会被列举出来。因此,dt A*会显示所有以"A"开头的数据类型、局部变量和静态变量,但是不会显示这些类型实际的实例。(如果同时使用了-v 显示选项,所有符号都会被显示出来 — 不只是具有关联的类型信息的。)也可以将NAME用一个点号(.)代替来说明想使用上一次用过的 NAME 值。如果NAME包含空格,需要用圆括号括起来。
Field
指定要显示的一个或多个字段。如果省略掉Field ,则显示所有字段。如果Field 后跟一个点号(.),则该字段的第一级子字段也会被显示出来。如果Field 后跟一系列的点号,则子字段显示的深度等于点号的个数。任何后面跟有点号的字段名都被当作一个前缀匹配,就像使用了-y搜索选项一样。如果Field后面跟一个星号(*),则它仅被当作字段的开头,而不是整个字段,并且所有匹配的字段都会被显示出来。
Address
指定要显示的结构的地址。如果省略掉Name,则必须包含Address 并且必须指定全局变量的地址。Address如果没有进行其它指示,则被当作一个虚拟地址。使用-p选项来指定物理地址。用"at" 号( @ )来指定寄存器(例如@eax)。
List

指定连接到一个链表的字段名。必须包含有Address 参数。

环境

模式 用户模式、内核模式
目标 活动目标、崩溃转储
平台 所有

注释

dt 命令的输出总是用10进制显示有符号数,16进制显示无符号数。

dt的所有参数都可以使用符号值,也可以使用字符串通配符。查看字符串通配符语法获得详细信息。

任何NAMEField之前都可以有-y -n选项。-y选项使得可以指定类型或结构名的开始部分。例如,dt -y ALLEN 将显示类型ALLENTOWN 的数据。但是,不能使用dt -y A 来显示ALLENTOWN,而因该使用dt -ny A,因为A是一个合法的16进制值,如果没有-n的话会被当作地址

如果Name指定了一个结构,它的所有字段都会显示出来(例如,dt myStruct)。如果只需要一个特定的字段,可以使用dt myStruct myField。这样会显示C中称为myStruct.myField的成员。但是,注意命令dt myStruct myField1 myField2显示myStruct.myField1myStruct.myField2,而不是显示myStruct.myField1.myField2

如果结构名或字段后跟一个下标,则表示一个数组的单个实例。例如,dt myStruct myFieldArray[3] 将显示要查询的数组中第四个成员。但是如果是类型名后跟下标,则指定整个数组。例如,dt CHAR[8] myPtr 将显示一个8字符的字符串。不管当前基数是什么,下表总是10进制数,使用0x前缀会产生错误。

由于该命令使用.pdb 文件中的类型信息,所以可以自由的调试任何CPU平台。

代码中所有使用typedef定义的类型就都会存在,只要程序中实际使用过的话。但是,头文件中定义过但没有实际使用过的类型不会包含在.pdb符号文件中。要想在调试器中使用这种类型,可以将它作为typedef声明的输入。例如,如果代码中有下面这样的语句,MY_DATA 就会被包含在.pdb文件中并且可以用dt命令查看:

typedef struct _MY_DATA {
    . . .
    } MY_DATA;
typedef  MY_DATA *PMY_DATA; 

另一方面,下面的代码就不行,因为MY_DATA和PMY_DATA都是在初始的typedef中定义的,所以MY_DATA本身并没有被作为任何typedef定义的输入:

typedef struct _MY_DATA {
    . . .
    } MY_DATA, *PMY_DATA; 

任何情况下,类型信息都只会包含在完整符号文件中,而不会存在于已经移除了私有符号信息的文件中。更多信息,查看公共和私有符号

如果要显示unicode字符串,需要首先使用.enable_unicode (Enable Unicode Display)令。可以通.enable_long_status (Enable Long Integer Display)命令来控制长整形的显示。

下面的例子中,dt显示一个全局变量:

0:000> dt mt1
   +0x000 a                : 10
   +0x004 b                : 98 'b'
   +0x006 c                : 0xdd
   +0x008 d                : 0xabcd
   +0x00c gn               : [6] 0x1
   +0x024 ex               : 0x0

下例中,dt显示数组字段gn

0:000> dt mt1 -a gn 
   +0x00c gn : 
    [00] 0x1
    [01] 0x2
    [02] 0x3
    [03] 0x4
    [04] 0x5
    [05] 0x6

下面的命令显示变量的一些子字段:

0:000> dt mcl1 m_t1 dpo 
   +0x010 dpo  : DEEP_ONE
   +0x070 m_t1 : MYTYPE1

这个命令显示m_t1子字段。因为点号自动产生前缀匹配,所以也会显示所有以"m_t1"开头的子字段:

0:000> dt mcl1 m_t1. 
   +0x070 m_t1  : 
      +0x000 a     : 0
      +0x004 b     : 0 ''
      +0x006 c     : 0x0
      +0x008 d     : 0x0
      +0x00c gn    : [6] 0x0
      +0x024 ex    : 0x0

可以重复任意深度。例如命令dt mcl1 a..c. 会显示深度为4的所有字段,并且第一个字段名以a开头,第三个字段名以c开头。

这里是如何显示子字段的一个更详细的示例。首先显示Ldr域:

0:000> dt nt!_PEB Ldr 7ffdf000
   +0x00c Ldr : 0x00191ea0

然后展开该指针类型的字段:

0:000> dt nt!_PEB Ldr Ldr. 7ffdf000 
   +0x00c Ldr  : 0x00191ea0
      +0x000 Length : 0x28
      +0x004 Initialized : 0x1 ''
      +0x008 SsHandle : (null)
      +0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x191ee0 - 0x192848 ]
      +0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x191ee8 - 0x192850 ]
      +0x01c InInitializationOrderModuleList : _LIST_ENTRY [ 0x191f58 - 0x192858 ]
      +0x024 EntryInProgress : (null)

现在显示CriticalSectionTimeout字段:

0:000> dt nt!_PEB CriticalSectionTimeout 7ffdf000 
   +0x070 CriticalSectionTimeout : _LARGE_INTEGER 0xffffe86d`079b8000

在第一级深度展开CriticalSectionTimeout结构的子字段:

0:000> dt nt!_PEB CriticalSectionTimeout. 7ffdf000 
   +0x070 CriticalSectionTimeout  :  0xffffe86d`079b8000
      +0x000 LowPart                 : 0x79b8000
      +0x004 HighPart                : -6035
      +0x000 u                       : __unnamed
      +0x000 QuadPart                : -25920000000000

现在展开CriticalSectionTimeout 结构的第二级子字段:

0:000> dt nt!_PEB CriticalSectionTimeout.. 7ffdf000 
   +0x070 CriticalSectionTimeout   :  0xffffe86d`079b8000
      +0x000 LowPart                  : 0x79b8000
      +0x004 HighPart                 : -6035
      +0x000 u                        :
         +0x000 LowPart                  : 0x79b8000
         +0x004 HighPart                 : -6035
      +0x000 QuadPart                 : -25920000000000

下面的命令显示位于0x0100297C 的一个MYTYPE1 的数据类型的示例:

0:000> dt 0x0100297c MYTYPE1 
   +0x000 a                : 22
   +0x004 b                : 43 '+'
   +0x006 c                : 0x0
   +0x008 d                : 0x0
   +0x00c gn               : [6] 0x0
   +0x024 ex               : 0x0

下面的命令显示地址0x01002BE0处的10个ULONG的数组:

0:000> dt -ca10 ULONG 01002be0 
[0] 0x1001098
[1] 0x1
[2] 0xdead
[3] 0x7d0
[4] 0x1
[5] 0xcd
[6] 0x0
[7] 0x0
[8] 0x0
[9] 0x0

这个命令在另一个地址继续使用上面的显示。注意不需要再重新输入"ULONG":

0:000> dt -ca4 . 01002d00 
Using sym ULONG
[0] 0x12
[1] 0x4ac
[2] 0xbadfeed
[3] 0x2

这是一些类型显示的示例。下面的命令显示thismodule中所有以"MY"开头的类型和全局变量。具有地址前缀的是实际的实例,而没有地址的是类型定义:

0:000> dt thismodule!MY*
010029b8  thismodule!myglobal1
01002990  thismodule!myglobal2
          thismodule!MYCLASS1
          thismodule!MYCLASS2
          thismodule!MYCLASS3
          thismodule!MYTYPE3::u
          thismodule!MYTYPE1
          thismodule!MYTYPE3
          thismodule!MYTYPE3
          thismodule!MYFLAGS

当进行类型显示时,-v 选项可以用来显示每个项目的大小。-s size 选项用来仅枚举指定大小的项。同样,有地址前缀的表示实例,没有地址的表示是类型定义:

0:001> dt -s 2 -v thismodule!*
Enumerating symbols matching thismodule!*, Size = 0x2
Address   Size Symbol
           002 thismodule!wchar_t
           002 thismodule!WORD
           002 thismodule!USHORT
           002 thismodule!SHORT
           002 thismodule!u_short
           002 thismodule!WCHAR
00427a34   002 thismodule!numberOfShips
00427a32   002 thismodule!numberOfPlanes
00427a30   002 thismodule!totalNumberOfItems

这是一个使用-b选项的示例。结构被展开并且结构中的OwnerThreads 数组也被展开,但是并不跟踪FlinkBlink链表指针:

kd> dt nt!_ERESOURCE -b 0x8154f040
   +0x000 SystemResourcesList :  [ 0x815bb388 - 0x816cd478 ]
      +0x000 Flink            : 0x815bb388
      +0x004 Blink            : 0x816cd478
   +0x008 OwnerTable       : (null)
   +0x00c ActiveCount      : 1
   +0x00e Flag             : 8
   +0x010 SharedWaiters    : (null)
   +0x014 ExclusiveWaiters : (null)
   +0x018 OwnerThreads     :
    [00]
      +0x000 OwnerThread      : 0
      +0x004 OwnerCount       : 0
      +0x004 TableSize        : 0
    [01]
      +0x000 OwnerThread      : 0x8167f563
      +0x004 OwnerCount       : 1
      +0x004 TableSize        : 1
   +0x028 ContentionCount  : 0
   +0x02c NumberOfSharedWaiters : 0
   +0x02e NumberOfExclusiveWaiters : 0
   +0x030 Address          : (null)
   +0x030 CreatorBackTraceIndex : 0
   +0x034 SpinLock         : 0

这是一个内核模式的dt示例。下面的命令处理结果类似!process 0 0

kd> dt nt!_EPROCESS -l ActiveProcessLinks.Flink -y Ima -yoi Uni 814856f0
ActiveProcessLinks.Flink at 0x814856f0
---------------------------------------------
UniqueProcessId : 0x00000008
ImageFileName : [16] "System"

ActiveProcessLinks.Flink at 0x8138a030
---------------------------------------------
UniqueProcessId : 0x00000084
ImageFileName : [16] "smss.exe"

ActiveProcessLinks.Flink at 0x81372368
---------------------------------------------
UniqueProcessId : 0x000000a0
ImageFileName : [16] "csrss.exe"

ActiveProcessLinks.Flink at 0x81369930
---------------------------------------------
UniqueProcessId : 0x000000b4
ImageFileName : [16] "winlogon.exe"

....

如果要对列表中的每一项执行命令,使用!list扩展。

最后,dt -h 命令可以显示dt语法的简短帮助文本。

附加信息

关于内存操作和内存相关的命令的概述,查看读写内存

Build machine: CAPEBUILD