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 在调用多个子例程(包括 printffgets)之前执行 105 条指令,然后在调用这些函数后但在发出更多调用之前执行 54545 条其他指令。 但是,在最终计数中,显示显示 myFunction 执行 112,379 条指令,因为此计数包括 myFunction 及其子项执行的所有指令。 (myFunction级是从 myFunction 直接或间接调用的函数 )

在前面的示例中,另请注意 ,ILT+1440 (__isatty) 被调用 21 次。 在最终计数中,此函数行为的摘要显示调用它的次数、任何单个执行中最少的指令数、任何单个执行中的最大指令数以及每个执行的平均指令数。

如果进行了任何系统调用,它们将显示在计数器中,并在命令输出的末尾再次列出。