Special Command—Tracing Applications Using wt

wt [WatchOptions] [= StartAddress] [EndAddress]

Transcribing the WinDbg documentation, this command runs through the whole function and then displays statistics when executed at the beginning of a function call. Thus, this command can be used just when doing live debugging, not post mortem debugging (dump analysis).

Think about Watch and Trace.

The WinDbg help file describes all options for WatchOptions. Usually we use the simplest form, not these options.

To demonstrate this command, let’s use this simple Visual C++ application that recursively calculates the Fibonacci from a specific number:

#include "stdafx.h"

using namespace std;

// Recursive function.

unsigned FiboRecursive(unsigned n, int nNum = 0)

{

          if(n <= 1)

          {

                    return n;

          }

                   

          return FiboRecursive(n - 1, 1) + FiboRecursive(n - 2, 2);

}

int _tmain(int argc, _TCHAR* argv[])

{

          cout << FiboRecursive(5) << endl;

          return 0;

}

Now we run the application from WinDbg and insert a breakpoint in the beginning of _tmain() .

After hitting the breakpoint, we disassemble the function:

0:000> uf Fibo!wmain

Fibo!wmain [c:\development\my tools\book\fibo\fibo\fibo.cpp @ 20]:

   20 001b1440 55 push ebp

   20 001b1441 8bec mov ebp,esp

   20 001b1443 81ecc0000000 sub esp,0C0h

   20 001b1449 53 push ebx

   20 001b144a 56 push esi

   20 001b144b 57 push edi

   20 001b144c 8dbd40ffffff lea edi,[ebp-0C0h]

   20 001b1452 b930000000 mov ecx,30h

   20 001b1457 b8cccccccc mov eax,0CCCCCCCCh

   20 001b145c f3ab rep stos dword ptr es:[edi]

   21 001b145e 8bf4 mov esi,esp

   21 001b1460 a198821b00 mov eax,dword ptr [Fibo!_imp_?endlstdYAAAV?$basic_ostreamDU?$char_traitsDstd (001b8298)]

   21 001b1465 50 push eax

   21 001b1466 6a00 push 0

   21 001b1468 6a05 push 5

   21 001b146a e89bfbffff call Fibo!ILT+5(?FiboRecursiveYAIIHZ) (001b100a)

   21 001b146f 83c408 add esp,8

   21 001b1472 8bfc mov edi,esp

   21 001b1474 50 push eax

   21 001b1475 8b0d90821b00 mov ecx,dword ptr [Fibo!_imp_?coutstd (001b8290)]

   21 001b147b ff1594821b00 call dword ptr [Fibo!_imp_??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01IZ (001b8294)]

   21 001b1481 3bfc cmp edi,esp

   21 001b1483 e8d1fcffff call Fibo!ILT+340(__RTC_CheckEsp) (001b1159)

   21 001b1488 8bc8 mov ecx,eax

   21 001b148a ff159c821b00 call dword ptr [Fibo!_imp_??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01P6AAAV01AAV01ZZ (001b829c)]

   21 001b1490 3bf4 cmp esi,esp

   21 001b1492 e8c2fcffff call Fibo!ILT+340(__RTC_CheckEsp) (001b1159)

   23 001b1497 33c0 xor eax,eax

   24 001b1499 5f pop edi

   24 001b149a 5e pop esi

   24 001b149b 5b pop ebx

   24 001b149c 81c4c0000000 add esp,0C0h

   24 001b14a2 3bec cmp ebp,esp

   24 001b14a4 e8b0fcffff call Fibo!ILT+340(__RTC_CheckEsp) (001b1159)

   24 001b14a9 8be5 mov esp,ebp

   24 001b14ab 5d pop ebp

   24 001b14ac c3 ret

Let’s use the address right before the recursive function call as the Start address and the address right after it as the End address of wt. Note the “ = ” right before the first address.

0:000> wt =001b1468 001b146f

    2 0 [ 0] Fibo!wmain

    1 0 [ 1] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

   64 0 [ 1] Fibo!FiboRecursive

    1 0 [ 2] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

   64 0 [ 2] Fibo!FiboRecursive

    1 0 [ 3] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

   64 0 [ 3] Fibo!FiboRecursive

    1 0 [ 4] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

   64 0 [ 4] Fibo!FiboRecursive

    1 0 [ 5] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

   67 0 [ 5] Fibo!FiboRecursive

  1 0 [ 6] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 6] Fibo!_RTC_CheckEsp

   70 3 [ 5] Fibo!FiboRecursive

   71 74 [ 4] Fibo!FiboRecursive

    1 0 [ 5] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

   67 0 [ 5] Fibo!FiboRecursive

    1 0 [ 6] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 6] Fibo!_RTC_CheckEsp

   70 3 [ 5] Fibo!FiboRecursive

   79 148 [ 4] Fibo!FiboRecursive

    1 0 [ 5] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 5] Fibo!_RTC_CheckEsp

   82 151 [ 4] Fibo!FiboRecursive

   71 234 [ 3] Fibo!FiboRecursive

    1 0 [ 4] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

   67 0 [ 4] Fibo!FiboRecursive

    1 0 [ 5] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 5] Fibo!_RTC_CheckEsp

   70 3 [ 4] Fibo!FiboRecursive

   79 308 [ 3] Fibo!FiboRecursive

    1 0 [ 4] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 4] Fibo!_RTC_CheckEsp

   82 311 [ 3] Fibo!FiboRecursive

   71 394 [ 2] Fibo!FiboRecursive

    1 0 [ 3] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

   64 0 [ 3] Fibo!FiboRecursive

    1 0 [ 4] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

   67 0 [ 4] Fibo!FiboRecursive

    1 0 [ 5] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 5] Fibo!_RTC_CheckEsp

   70 3 [ 4] Fibo!FiboRecursive

   71 74 [ 3] Fibo!FiboRecursive

    1 0 [ 4] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

   67 0 [ 4] Fibo!FiboRecursive

    1 0 [ 5] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 5] Fibo!_RTC_CheckEsp

   70 3 [ 4] Fibo!FiboRecursive

   79 148 [ 3] Fibo!FiboRecursive

    1 0 [ 4] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 4] Fibo!_RTC_CheckEsp

   82 151 [ 3] Fibo!FiboRecursive

   79 628 [ 2] Fibo!FiboRecursive

    1 0 [ 3] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 3] Fibo!_RTC_CheckEsp

   82 631 [ 2] Fibo!FiboRecursive

   71 714 [ 1] Fibo!FiboRecursive

    1 0 [ 2] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

   64 0 [ 2] Fibo!FiboRecursive

    1 0 [ 3] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

   64 0 [ 3] Fibo!FiboRecursive

    1 0 [ 4] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

  67 0 [ 4] Fibo!FiboRecursive

    1 0 [ 5] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 5] Fibo!_RTC_CheckEsp

   70 3 [ 4] Fibo!FiboRecursive

   71 74 [ 3] Fibo!FiboRecursive

    1 0 [ 4] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

   67 0 [ 4] Fibo!FiboRecursive

    1 0 [ 5] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 5] Fibo!_RTC_CheckEsp

   70 3 [ 4] Fibo!FiboRecursive

   79 148 [ 3] Fibo!FiboRecursive

    1 0 [ 4] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 4] Fibo!_RTC_CheckEsp

   82 151 [ 3] Fibo!FiboRecursive

   71 234 [ 2] Fibo!FiboRecursive

    1 0 [ 3] Fibo!ILT+5(?FiboRecursiveYAIIHZ)

   67 0 [ 3] Fibo!FiboRecursive

    1 0 [ 4] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 4] Fibo!_RTC_CheckEsp

   70 3 [ 3] Fibo!FiboRecursive

   79 308 [ 2] Fibo!FiboRecursive

    1 0 [ 3] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 3] Fibo!_RTC_CheckEsp

   82 311 [ 2] Fibo!FiboRecursive

   79 1108 [ 1] Fibo!FiboRecursive

    1 0 [ 2] Fibo!ILT+340(__RTC_CheckEsp)

    2 0 [ 2] Fibo!_RTC_CheckEsp

   82 1111 [ 1] Fibo!FiboRecursive

1196 instructions were executed in 1195 events (0 from other threads)

Function Name Invocations MinInst MaxInst AvgInst

Fibo!FiboRecursive 15 70 82 75

Fibo!ILT+340(__RTC_CheckEsp) 15 1 1 1

Fibo!ILT+5(?FiboRecursiveYAIIHZ) 15 1 1 1

Fibo!_RTC_CheckEsp 15 2 2 2

Fibo!wmain 1 2 2 2

0 system calls were executed

eax=00000005 ebx=7efde000 ecx=00000000 edx=00000001 esi=00000000 edi=00000000

eip=001b146f esp=0045f914 ebp=0045f964 iopl=0 nv up ei pl zr na pe nc

cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246

Fibo!wmain+0x2f:

001b146f 83c408 add esp,8

Notice that the first number right below the command specifies the number of instructions that were executed, the second number specifies the number of instructions executed by child calls of the function, and the third number (in brackets) is the depth of the function in the stack.

MinInst, MaxInst and AvgInst mean the number of instructions by call.