wt(跟踪和监视数据)
当 在函数调用开始时执行此命令时,wt 命令将运行整个函数,然后显示统计信息。
wt [WatchOptions] [= StartAddress] [EndAddress]
参数
WatchOptions
指定如何修改显示。 可以使用以下任一选项。
选项 | 效果 |
---|---|
-l 深度 |
(仅限用户模式)指定要显示的调用的最大深度。 以无提示方式执行至少深度级别高于起点的任何调用。 |
-m 模块 |
(仅限用户模式)将显示限制为指定模块内的代码,以及从该模块发出的第一级调用。 可以包含多个 -m 选项来显示来自多个模块的代码,而没有其他模块。 |
-i 模块 |
(仅限用户模式)忽略指定模块中的任何代码。 可以包含多个 -i 选项来忽略多个模块中的代码。 如果使用 -m 选项,调试器将忽略所有 -i 选项。 |
-镍 |
(仅限用户模式)由于 -m 或 -i 选项,不会显示被忽略的代码中的任何条目。 |
-数控 |
不显示单个呼叫信息。 |
-ns |
不显示摘要信息。 |
-西北 |
在跟踪期间不显示警告。 |
-oa |
(仅限用户模式)显示呼叫网站的实际地址。 |
-or |
(仅限用户模式)使用默认基数显示所调用函数的返回寄存器值。 |
-或 |
(仅限用户模式)在每个返回值的相应类型中显示所调用函数的返回寄存器值。 |
StartAddress
指定调试器开始执行的地址。 如果不使用 StartAddress,则执行从指令指针指向的指令开始。 有关语法的详细信息,请参阅地址和地址范围语法。
EndAddress
指定跟踪结束的地址。 如果不使用 EndAddress,将执行单个指令或函数调用。
环境
模式 |
用户模式、内核模式 |
目标 |
仅限实时调试 |
平台 |
用户模式: 所有 内核模式: 仅基于 x86 |
其他信息
有关发出 wt 命令和相关命令概述的详细信息,请参阅 控制目标。
注解
如果想要有关特定函数的行为的信息,但不希望单步执行函数,则 wt 命令非常有用。 而是转到该函数的开头,然后发出 wt 命令。
如果程序计数器位于对应于某个符号(如函数的开头或模块入口点)的点,则 wt 命令将跟踪,直到到达当前返回地址。 如果程序计数器位于调用指令中,则 wt 命令将跟踪,直到它返回到当前位置。 此跟踪在 调试器命令窗口中 进行分析,以及描述命令遇到的各种调用的输出。
如果在函数开头以外的某个位置发出 wt 命令,则命令的行为类似于 p (步骤) 命令。 但是,如果指定 EndAddress,则执行会一直持续到达到该地址,即使此执行涉及许多程序步骤和函数调用。
在源模式下调试时,应仅跟踪到函数正文的左括号的点。 然后,可以使用 wt 命令。 (通常更容易在函数的第一行插入断点,或使用 调试 |运行到 Cursor,然后使用 wt 命令。
由于 wt 的输出可能很长,因此可能需要使用日志文件来记录输出。
以下示例显示了典型的日志文件。
0:000> l+ Source options set to show source lines
Source options are f:
1/t - Step/trace by source line
2/l - List source line for LN and prompt
4/s - List source code at prompt
8/o - Only show source code at prompt
0:000> p Not yet at the function call: use "p"
> 44: minorVariableOne = 12;
0:000> p
> 45: variableOne = myFunction(2, minorVariable);
0:000> t At the function call: now use "t"
MyModule!ILT+10(_myFunction):
0040100f e9cce60000 jmp MyModule!myFunction (0040f6e0)
0:000> t
> 231: {
0:000> wt At the function beginning: now use "wt"
Tracing MyModule!myFunction to return address 00401137
105 0 [ 0] MyModule!myFunction
1 0 [ 1] MyModule!ILT+1555(_printf)
9 0 [ 1] MyModule!printf
1 0 [ 2] MyModule!ILT+370(__stbuf)
11 0 [ 2] MyModule!_stbuf
1 0 [ 3] MyModule!ILT+1440(__isatty)
14 0 [ 3] MyModule!_isatty
50 15 [ 2] MyModule!_stbuf
17 66 [ 1] MyModule!printf
1 0 [ 2] MyModule!ILT+980(__output)
59 0 [ 2] MyModule!_output
39 0 [ 3] MyModule!write_char
111 39 [ 2] MyModule!_output
39 0 [ 3] MyModule!write_char
....
11 0 [ 5] kernel32!__SEH_epilog4
54 11675 [ 4] kernel32!ReadFile
165 11729 [ 3] MyModule!_read
100 11895 [ 2] MyModule!_filbuf
91 11996 [ 1] MyModule!fgets
54545 83789 [ 0] MyModule!myFunction
1 0 [ 1] MyModule!ILT+1265(__RTC_CheckEsp)
2 0 [ 1] MyModule!_RTC_CheckEsp
54547 83782 [ 0] MyModule!myFunction
112379 instructions were executed in 112378 events (0 from other threads)
Function Name Invocations MinInst MaxInst AvgInst
MyModule!ILT+1265(__RTC_CheckEsp) 1 1 1 1
MyModule!ILT+1440(__isatty) 21 1 1 1
MyModule!ILT+1540(__ftbuf) 21 1 1 1
....
ntdll!memcpy 24 1 40 19
ntdll!memset 2 29 29 29
23 system calls were executed
Calls System Call
23 ntdll!KiFastSystemCall
在跟踪列表中,第一个数字指定所执行的指令数,第二个数字指定函数的子进程执行的指令数,第三个数字(括号中)指定堆栈中函数的深度(以初始函数为零)。 函数名称的缩进显示调用深度。
在前面的示例中, MyModule!myFunction 在调用多个子例程(包括 printf 和 fgets)之前执行 105 个指令,然后在调用这些函数之后执行 54545 个附加指令,但在发出更多调用之前。 但是,在最终计数中,显示 myFunction 执行 112,379 个指令,因为此计数包括 myFunction 及其子级执行的所有指令。 (myFunction 的子级是直接或间接从 myFunction 调用的函数。
在前面的示例中,另请注意, ILT+1440 (__isatty) 被调用 21 次。 在最终计数中,此函数行为的摘要显示调用的次数、任何单个执行中的最小指令数、任何单个执行中的指令数最大以及每个执行的平均指令数。
如果进行了任何系统调用,它们会显示在计数器中,并在命令输出末尾再次列出。