dt(显示类型)
dt 命令显示有关局部变量、全局变量或数据类型的信息。 这可以显示有关简单数据类型以及结构和联合的信息。
用户模式语法
dt [-DisplayOpts] [-SearchOpts] [module!]Name [[-SearchOpts] Field] [Address] [-l List]
dt [-DisplayOpts] Address [-l List]
dt -h
内核模式语法
[Processor] dt [-DisplayOpts] [-SearchOpts] [module!]Name [[-SearchOpts] Field] [Address] [-l List]
dt [-DisplayOpts] Address [-l List]
dt -h
参数
处理器
指定运行包含所需信息的进程的处理器。 有关详细信息,请参阅 多处理器语法。 处理器只能在内核模式下指定。
DisplayOpts
指定下表中提供的一个或多个选项。 这些选项前面有连字符。
选项 | 说明 |
---|---|
-a[quantity] |
在新行上显示每个数组元素及其索引。 将显示总 数量 元素。 a 和数量之间不得有空格。 如果 -a 不后跟数字,则显示数组中的所有项。 -a[quantity] 开关应立即显示在要以这种方式显示的每种类型名称或字段名称之前。 |
-b |
以递归方式显示块。 如果显示的结构包含子结构,则以递归方式将其扩展为任意深度并完全显示。 仅当指针位于原始结构中,而不是子结构中时,指针才会展开。 |
-c |
压缩输出。 如果可能,所有字段都显示在一行上。 (与 -a 开关一起使用时,每个数组元素采用一行,而不是格式化为多行块)。 |
-d |
与以星号结尾的名称一起使用时,显示以 Name 开头的所有类型的详细输出。 如果 Name 不以星号结尾,则显示详细输出。 |
-e |
强制 dt 枚举类型。 仅当 dt 错误地将 Name 值解释为实例而不是类型时,才需要此选项。 |
-i |
不要缩进子类型。 |
-o |
省略结构字段的偏移值。 |
-p |
地址 是物理地址,而不是虚拟地址。 |
-r[depth] |
以递归方式转储子类型字段。 如果给出深度,此递归将在深度级别后停止。 深度必须是介于 1 和 9 之间的数字,r 和深度之间不得有空格。 -r[depth] 开关应紧邻地址前显示。 |
-s 大小 |
仅枚举其大小(以字节为单位) 等于大小的类型。 仅当枚举类型时,-s 选项才有用。 指定 -s 时,也始终隐含 -e。 |
-t |
仅枚举类型。 |
-v |
详细输出。 这提供了其他信息,例如结构的总大小及其元素数。 当与 -y 搜索选项一起使用时,将显示所有符号,即使没有关联的类型信息。 |
SearchOpts
指定下表中提供的一个或多个选项。 这些选项前面有连字符。
选项 | 说明 |
---|---|
-n |
这表示下一个参数是一个名称。 如果下一项完全由十六进制字符组成,则应使用此项,因为否则将用作地址。 |
-y |
这表示下一个参数是名称的开头,不一定是整个名称。 如果 包含 -y ,则会列出所有匹配项,然后列出列表中第一个匹配项的详细信息。 如果未 包含 -y ,则只会显示完全匹配项。 |
模块
一个可选参数,用于指定定义此结构的模块。 如果有与全局变量或类型同名的局部变量或类型,则应包含 模块 以指定表示全局变量。 否则, dt 命令将显示局部变量,即使局部变量不区分大小写,全局变量也是区分大小写的匹配。
名字
指定类型或全局变量的名称。 如果 Name 以星号 {结尾,则会显示所有匹配项的列表。 因此, dt A\* 将列出以“A”开头的所有数据类型、全局和静态,但不显示这些类型的实际实例。 (如果同时使用 -v 显示选项,则会显示所有符号,而不仅仅是具有关联类型信息的符号。还可以将 Name 替换为句点(.),以表示要重复最近使用过的名称值。
如果 Name 包含空格,则应用括号括起来。
田
指定要显示的字段。 如果 省略 Field ,则会显示所有字段。 如果 字段 后跟句点(.),则还会显示此字段的第一级子字段。 如果 字段 后跟一系列句点,则子字段将显示为等于句点数的深度。 后跟句点的任何字段名称都将被视为前缀匹配,就像 使用了 -y 搜索选项一样。 如果 Field 后跟星号 \,则它只被视为字段的开头,不一定是整个字段,并且将显示所有匹配字段。
地址
指定要显示的结构的地址。 如果 省略 Name , 则必须包含 Address ,并且必须指定全局变量的地址。 除非另有指定,否则地址 将设置为虚拟地址。 使用 -p 选项指定物理地址。 使用“at”符号( @ )指定寄存器(例如, @eax)。
列表
指定链接列表的字段名称。 必须包含 Address 参数。
环境
项 | 说明 |
---|---|
模式 | 用户模式、内核模式 |
目标 | 实时、崩溃转储 |
平台 | 全部 |
其他信息
有关内存操作的概述和其他与内存相关命令的说明,请参阅读取和写入内存。
注解
dt 命令输出将始终在 base 10 中显示有符号数字,以及十六进制中的无符号数字。
允许符号值的所有 dt 参数也允许字符串通配符。 有关详细信息,请参阅 字符串通配符语法 。
-y 和 -n 选项可以位于任何名称或字段前面。 使用 -y 选项可以指定类型或结构名称的开头。 例如,dt -y ALLEN 将显示有关 ALLENTOWN 类型的数据。 但是,不能使用 dt -y A 显示 ALLENTOWN 类型。相反,必须使用 dt -ny A,因为 A 是有效的十六进制值,并且将被解释为没有 -n 选项的地址。
如果 Name 指示结构,将显示所有字段(例如 dt myStruct)。 如果只需要一个特定字段,则可以执行 dt myStruct myField。 这会显示 C 将调用 myStruct.myField 的成员。 但是,请注意,命令 dt myStruct myField1 myField2 显示 myStruct.myField1 和 myStruct.myField2。 它不显示 myStruct.myField1.myField2。
如果结构名称或字段后跟下标,则指定数组的单个实例。 例如, dt myStruct myFieldArray[3] 将显示数组的第四个元素。 但是,如果类型名称后跟下标,则指定整个数组。 例如, dt CHAR[8] myPtr 将显示一个八个字符的字符串。 无论当前基数如何,下标始终都被视为小数: 0x 前缀将导致错误。
因为该命令使用来自 .. 的类型信息。pdb 文件,可用于调试任何 CPU 平台。
dt 使用的类型信息包括使用 typedef 创建的所有类型名称,包括所有 Windows 定义的类型。 例如, 无符号长 字符 和字符 不是有效的类型名称,但 ULONG 和 CHAR 是。 有关所有 Windows 类型名称的完整列表,请参阅 Microsoft Windows SDK。
只要已在程序中实际使用 typedefs,你自己的代码中创建的所有类型都将存在。 但是,在标头中定义但从未实际使用过的类型不会存储在 .pdb 符号文件中,并且调试器无法访问。 若要使此类类型可供调试器使用,请使用它作为 typedef 语句的输入。 例如,如果代码中出现以下内容,则结构MY_DATA将存储在 .pdb 符号文件中,并且可以由 dt 命令显示:
typedef struct _MY_DATA {
. . .
} MY_DATA;
typedef MY_DATA *PMY_DATA;
另一方面,由于初始 typedef 定义了MY_DATA和PMY_DATA,因此,MY_DATA本身未用作任何 typedef 语句的输入,因此,以下代码将不足够:
typedef struct _MY_DATA {
. . .
} MY_DATA, *PMY_DATA;
在任何事件中,类型信息仅包含在完整的符号文件中,而不是已剥离所有私有符号信息的符号文件。 有关详细信息,请参阅公共符号和专用符号。
如果要显示 unicode 字符串,则需要首先使用 .enable_unicode(启用 Unicode 显示) 命令。 可以使用.enable_long_status(启用长整型显示)命令控制长整数的显示。
在以下示例中, 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. 将显示所有字段以深度四,以便第一个字段名称以 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
下面是显示类型的一些示例。 以下命令显示以此 模块中的字符串“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 大小选项可用于仅枚举特定大小的项。 同样,那些以地址为前缀的实例是实际实例;没有地址的那些是类型定义:
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 数组已展开,但 Flink 和 Blink 列表指针不遵循:
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 语法的简短帮助文本。