WinDbgを使用して関数の引数・戻り値をデバッガに出力する方式について
WinDbgでは、ブレークポイントヒット時に新たなブレークポイントを作成することが出来ます。
また、関数のリターンアドレスにブレークポイントを設置することにより、関数から復帰した直後にブレークさせることが出来ます。
本機能を用いて、C言語の関数の引数及び戻り値をデバッガに出力させてみます。
##デバッグ対象コード
階乗を求めるプログラム(factorial.exe)となります。
factorial.c
#include <stdio.h>
// 階乗を求める
int factorial(int n)
{
return n > 0 ? n * factorial(n - 1) : 1;
};
int main()
{
int n = 6;
int m = factorial(n);
printf("%d!=%d\n", n, m);
return 0;
}
##ブレークポイント設定方式
factorial.exeのfactorial 関数に下記のブレークポイントを設定し、ヒット時に関数のリターンアドレスにブレークポイントを作成するようにしています。
第1引数の値はesp+4、戻り値はeaxで取得するようにしています。
bp factorial!factorial "bp poi(esp) \" .printf /D \\\"[factorial]\\\\t%p\\\\t終了\\\\t%p\\\\n\\\", esp, eax;g\"; .printf /D \"[factorial]\\t%p\\t開始\\t%p\\n\", esp+4, poi(esp+4); g"
x64ビルドの場合はrsp、ecx等のレジスタを使用します。
bp factorial!factorial "bp poi(rsp) \" .printf /D \\\"[factorial]\\\\t%p\\\\t終了\\\\t%p\\\\n\\\", rsp, eax;g\"; .printf /D \"[factorial]\\t%p\\t開始\\t%p\\n\", rsp+8, ecx; g"
デバッガ出力結果
デバッグ対象コードをVisual Studio 2013でデバッグビルドし、WinDbgでブレークポイントを設定して実行させます。
CommandLine: "C:\Users\r\Documents\Visual Studio 2013\Projects\factorial\Debug\factorial.exe"
************* Symbol Path validation summary **************
Response Time (ms) Location
Deferred srv*c:\symbols*http://msdl.microsoft.com/downloads/symbols
Symbol search path is: srv*c:\symbols*http://msdl.microsoft.com/downloads/symbols
Executable search path is:
ModLoad: 01180000 0119c000 factorial.exe
ModLoad: 77090000 771fe000 ntdll.dll
ModLoad: 76e70000 76fb0000 C:\Windows\SysWOW64\KERNEL32.DLL
ModLoad: 75170000 75247000 C:\Windows\SysWOW64\KERNELBASE.dll
ModLoad: 77620000 777df000 C:\Windows\SysWOW64\MSVCR120D.dll
(c48.1a64): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000000 ecx=cb780000 edx=00000000 esi=7f29f000 edi=00000000
eip=77143bad esp=0046f428 ebp=0046f454 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!LdrpDoDebuggerBreak+0x2b:
77143bad cc int 3
0:000> bp factorial!factorial "bp poi(esp) \" .printf /D \\\"[factorial]\\\\t%p\\\\t終了\\\\t%p\\\\n\\\", esp, eax;g\"; .printf /D \"[factorial]\\t%p\\t開始\\t%p\\n\", esp+4, poi(esp+4); g"
*** WARNING: Unable to verify checksum for factorial.exe
0:000> g
[factorial] 0046f77c 開始 00000006
[factorial] 0046f6a0 開始 00000005
breakpoint 2 redefined
[factorial] 0046f5c4 開始 00000004
breakpoint 2 redefined
[factorial] 0046f4e8 開始 00000003
breakpoint 2 redefined
[factorial] 0046f40c 開始 00000002
breakpoint 2 redefined
[factorial] 0046f330 開始 00000001
breakpoint 2 redefined
[factorial] 0046f254 開始 00000000
[factorial] 0046f254 終了 00000001
[factorial] 0046f330 終了 00000001
[factorial] 0046f40c 終了 00000002
[factorial] 0046f4e8 終了 00000006
[factorial] 0046f5c4 終了 00000018
[factorial] 0046f6a0 終了 00000078
[factorial] 0046f77c 終了 000002d0
eax=00000000 ebx=7718f820 ecx=00000000 edx=00000000 esi=00000000 edi=01191109
eip=770cc73c esp=0046f71c ebp=0046f7e8 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
ntdll!NtTerminateProcess+0xc:
770cc73c c20800 ret 8
factorial関数の引数・戻り値がデバッガに出力されました。
本出力結果は下記の様な表として纏めることが出来ます。