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 (Step) 命令。 但是,如果指定 EndAddress,则执行会一直持续到达到该地址,即使此执行涉及许多程序步骤和函数调用。
在源模式下调试时,应仅跟踪函数,直到看到函数正文的左括号。 然后,可以使用 wt 命令。 (通常,在函数的第一行插入断点或使用 Debug |运行到游标,然后使用 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 次。 在最终计数中,此函数行为的摘要显示调用它的次数、任何单个执行中最少的指令数、任何单个执行中的最大指令数以及每个执行的平均指令数。
如果进行了任何系统调用,它们将显示在计数器中,并在命令输出的末尾再次列出。
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈