本文介紹windbg動態調試過程中一個非常有用的命令,wt的用法。
wt命令
wt命令之所以稱為wt是因為它是watch and trace的簡稱,即用來觀察和跟蹤的命令。這個命令一般用在動態調試而不是dump分析中。他的作用是跟蹤程序的執行過程,並將每個執行的調用打印到輸出。
我們先准備一個簡單的斐波那契計算代碼,然后通過wt命令來追蹤這個程序的執行。
#include "tchar.h" #include <iostream> using namespace std; unsigned Fibonacci(unsigned n) { if(n <= 1) { return n; } return Fibonacci(n-1) + Fibonacci(n-2); } int _tmain(int argc, _TCHAR* argv[]) { cout << Fibonacci(5) << endl; return 0; }
將以上代碼編譯之后通過windbg打開運行,然后通過x命令查找入口函數main的地址,
0:000> x fibo!main
00391a40 fibo!main (int, char **)
通過uf命令反編譯該函數,找出遞歸開始和結束的地址,
0:000> uf 00391a40
fibo!main [c:\users\aaronzh\desktop\fibo.cpp @ 16]:
16 00391a40 55 push ebp
16 00391a41 8bec mov ebp,esp
17 00391a43 684c143900 push offset fibo!ILT+1095(?endlstdYAAAV?$basic_ostreamDU?$char_traitsDstd (0039144c)
17 00391a48 6a0a push 0Ah
17 00391a4a e8acfaffff call fibo!ILT+1270(?FibonacciYAIIZ) (003914fb)
17 00391a4f 83c404 add esp,4
17 00391a52 50 push eax
17 00391a53 b9f0ad4000 mov ecx,offset fibo!std::cout (0040adf0)
17 00391a58 e870f6ffff call fibo!ILT+200(??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01IZ) (003910cd)
17 00391a5d 8bc8 mov ecx,eax
17 00391a5f e895f7ffff call fibo!ILT+500(??6?$basic_ostreamDU?$char_traitsDstdstdQAEAAV01P6AAAV01AAV01ZZ) (003911f9)
18 00391a64 33c0 xor eax,eax
19 00391a66 5d pop ebp
19 00391a67 c3 ret
通過wt命令來查看整個的遞歸調用過程,=后面是起始地址。
0:000> wt =00391a48 00391a4f 2 0 [ 0] fibo!main 1 0 [ 1] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 1] fibo!Fibonacci 1 0 [ 2] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 2] fibo!Fibonacci 1 0 [ 3] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 3] fibo!Fibonacci 1 0 [ 4] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 4] fibo!Fibonacci 1 0 [ 5] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 5] fibo!Fibonacci 1 0 [ 6] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 6] fibo!Fibonacci 1 0 [ 7] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 7] fibo!Fibonacci 1 0 [ 8] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 8] fibo!Fibonacci 1 0 [ 9] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 9] fibo!Fibonacci 1 0 [ 10] fibo!ILT+1270(?FibonacciYAIIZ) 10 0 [ 10] fibo!Fibonacci 15 11 [ 9] fibo!Fibonacci 1 0 [ 10] fibo!ILT+1270(?FibonacciYAIIZ) 10 0 [ 10] fibo!Fibonacci 20 22 [ 9] fibo!Fibonacci 15 43 [ 8] fibo!Fibonacci 1 0 [ 9] fibo!ILT+1270(?FibonacciYAIIZ) 10 0 [ 9] fibo!Fibonacci 20 54 [ 8] fibo!Fibonacci 15 75 [ 7] fibo!Fibonacci 1 0 [ 8] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 8] fibo!Fibonacci 1 0 [ 9] fibo!ILT+1270(?FibonacciYAIIZ) 10 0 [ 9] fibo!Fibonacci 15 11 [ 8] fibo!Fibonacci 1 0 [ 9] fibo!ILT+1270(?FibonacciYAIIZ) 10 0 [ 9] fibo!Fibonacci 20 22 [ 8] fibo!Fibonacci 20 118 [ 7] fibo!Fibonacci 15 139 [ 6] fibo!Fibonacci 1 0 [ 7] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 7] fibo!Fibonacci 1 0 [ 8] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 8] fibo!Fibonacci 1 0 [ 9] fibo!ILT+1270(?FibonacciYAIIZ) 10 0 [ 9] fibo!Fibonacci 15 11 [ 8] fibo!Fibonacci 1 0 [ 9] fibo!ILT+1270(?FibonacciYAIIZ) 10 0 [ 9] fibo!Fibonacci 20 22 [ 8] fibo!Fibonacci 15 43 [ 7] fibo!Fibonacci 1 0 [ 8] fibo!ILT+1270(?FibonacciYAIIZ) 10 0 [ 8] fibo!Fibonacci 20 54 [ 7] fibo!Fibonacci 20 214 [ 6] fibo!Fibonacci 15 235 [ 5] fibo!Fibonacci 1 0 [ 6] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 6] fibo!Fibonacci 1 0 [ 7] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 7] fibo!Fibonacci 1 0 [ 8] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 8] fibo!Fibonacci 1 0 [ 9] fibo!ILT+1270(?FibonacciYAIIZ) 10 0 [ 9] fibo!Fibonacci 15 11 [ 8] fibo!Fibonacci 1 0 [ 9] fibo!ILT+1270(?FibonacciYAIIZ) 10 0 [ 9] fibo!Fibonacci 20 22 [ 8] fibo!Fibonacci 15 43 [ 7] fibo!Fibonacci 1 0 [ 8] fibo!ILT+1270(?FibonacciYAIIZ) 10 0 [ 8] fibo!Fibonacci 20 54 [ 7] fibo!Fibonacci 15 75 [ 6] fibo!Fibonacci 1 0 [ 7] fibo!ILT+1270(?FibonacciYAIIZ) 9 0 [ 7] fibo!Fibonacci 1 0 [ 8] fibo!ILT+1270(?FibonacciYAIIZ) 10 0 [ 8] fibo!Fibonacci 15 11 [ 7] fibo!Fibonacci 1 0 [ 8] fibo!ILT+1270(?FibonacciYAIIZ) 10 0 [ 8] fibo!Fibonacci 20 22 [ 7] fibo!Fibonacci 20 118 [ 6] fibo!Fibonacci 20 374 [ 5] fibo!Fibonacci
....
....省略部分輸出
.... 2829 instructions were executed in 2828 events (0 from other threads) Function Name Invocations MinInst MaxInst AvgInst fibo!Fibonacci 177 10 20 14 fibo!ILT+1270(?FibonacciYAIIZ) 177 1 1 1 fibo!main 1 2 2 2 0 system calls were executed eax=00000037 ebx=00000003 ecx=00000000 edx=00000000 esi=00000000 edi=003900d8 eip=00391a4f esp=0055f838 ebp=0055f868 iopl=0 nv up ei pl nz na po nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202 fibo!main+0xf: 00391a4f 83c404 add esp,4
這個命令對於並不熟悉代碼的調用過程的時候非常有用,通過這個方法調用跟蹤,對於整個過程的方法調用過程就有了一個完整的概念,之后我們就可以根據相應的函數調用來設置相應的斷點來查看我們關心的邏輯。
另外wt命令本身支持很多選項,常用的如下,
- -l,指定要追蹤的調用深度(注意后面的數字默認16進制)
- -m,指定要追蹤的特定模塊,其他的模塊調用會被忽略
- -i,指定要被忽略的模塊
- -oR,顯示函數調用返回值,這個選項對於你已知某個函數調用返回值的含義(例如access denied)時非常有用,通過這個選項追蹤特定函數調用,然后直接全局搜索輸出,來查看特定值是否被輸出,結果就一目了然了。
希望以上內容對您有所幫助
Aaron Zhang