ほっしーの技術ネタ備忘録

技術ネタの備忘録です。基本的に私が忘れないためのものです。他の人の役にも立つといいなぁ。

シングルステップ実行の仕方

x86 系 CPU のフラグレジスタには、Trap Flag というフラグがあって、
これを立てると次の1命令を実行してトラップ例外を起こします。

void SetSingleStepMode( HANDLE hThread )
{
	CONTEXT ctx = { CONTEXT_CONTROL };
	GetThreadContext( hThread, &ctx );
	ctx.EFlags |= 0x00000100; // TrapFlag
	SetThreadContext( hThread, &ctx );
}

スレッドのコンテキストには、その時の CPU のレジスタなどの
情報が格納されています。EFlags がフラグレジスタ
CONTEXT_INTEGER を付けるとおなじみ EAX〜EDX レジスタも見れます。


さて、TrapFlag を立てておくと1命令実行後、EXCEPTION_SINGLE_STEP 例外が発生するので

	case EXCEPTION_DEBUG_EVENT:
		if( evDebug.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP ) {
			SetSingleStepMode( hThread );
		}
		break;

こんな風に拿捕します。
一回発生するとフラグが落ちるので、毎回設定しなおします。


ほんとは Get/SetThreadContext する前に Suspend する必要がありますが、
WaitForDebugEvent ループ中は実行停止されているので問題なし。
CreateProcess 直後にするなら CREATE_SUSPENDED フラグを。