?? lion-tut-c28.htm
字號(hào):
<調(diào)試事件處理><br>
invoke ContinueDebugEvent, DebugEvent.dwProcessId, DebugEvent.dwThreadId,
DBG_EXCEPTION_NOT_HANDLED <br>
.endw </b><br>
</p>
<p>就是說,當(dāng)開始調(diào)試程序時(shí),我們的程序不能和debuggee分開直到它結(jié)束.</p>
</li>
</ol>
<p>我們?cè)賮砜偨Y(jié)一下這些步驟:</p>
<ol>
<li><b>創(chuàng)建一個(gè)進(jìn)程或捆綁我們的程序到運(yùn)行中的進(jìn)程上</b>.</li>
<li><b>等待調(diào)試事件</b></li>
<li><b>響應(yīng)調(diào)試事件</b>.</li>
<li><b>繼續(xù)執(zhí)行debuggee</b>.</li>
<li><b>繼續(xù)這一無盡循環(huán)直到debuggee進(jìn)程結(jié)束</b></li>
</ol>
<h3>例子:</h3>
<p>這個(gè)例子調(diào)試一個(gè)win32程序并顯示諸如進(jìn)程句柄,進(jìn)程Id,映象基址等.</p>
<p>.386 <br>
.model flat,stdcall <br>
option casemap:none <br>
include \masm32\include\windows.inc <br>
include \masm32\include\kernel32.inc <br>
include \masm32\include\comdlg32.inc <br>
include \masm32\include\user32.inc <br>
includelib \masm32\lib\kernel32.lib <br>
includelib \masm32\lib\comdlg32.lib <br>
includelib \masm32\lib\user32.lib <br>
.data <br>
AppName db "Win32 Debug Example no.1",0 <br>
ofn OPENFILENAME <> <br>
FilterString db "Executable Files",0,"*.exe",0 <br>
db
"All Files",0,"*.*",0,0 <br>
ExitProc db "The debuggee exits",0 <br>
NewThread db "A new thread is created",0 <br>
EndThread db "A thread is destroyed",0 <br>
ProcessInfo db "File Handle: %lx ",0dh,0Ah <br>
db "Process
Handle: %lx",0Dh,0Ah <br>
db "Thread
Handle: %lx",0Dh,0Ah <br>
db "Image
Base: %lx",0Dh,0Ah <br>
db "Start
Address: %lx",0 <br>
.data? <br>
buffer db 512 dup(?) <br>
startinfo STARTUPINFO <> <br>
pi PROCESS_INFORMATION <> <br>
DBEvent DEBUG_EVENT <> <br>
.code <br>
start: <br>
mov ofn.lStructSize,sizeof ofn <br>
mov ofn.lpstrFilter, offset FilterString <br>
mov ofn.lpstrFile, offset buffer <br>
mov ofn.nMaxFile,512 <br>
mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER
or OFN_HIDEREADONLY <br>
invoke GetOpenFileName, ADDR ofn <br>
.if eax==TRUE <br>
invoke GetStartupInfo,addr startinfo <br>
invoke CreateProcess, addr buffer, NULL, NULL, NULL, FALSE, DEBUG_PROCESS+ DEBUG_ONLY_THIS_PROCESS,
NULL, NULL, addr startinfo, addr pi <br>
.while TRUE <br>
invoke WaitForDebugEvent, addr DBEvent, INFINITE <br>
.if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT <br>
invoke MessageBox, 0, addr ExitProc, addr
AppName, MB_OK+MB_ICONINFORMATION <br>
.break <br>
.elseif DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT <br>
invoke wsprintf, addr buffer, addr ProcessInfo,
DBEvent.u.CreateProcessInfo.hFile, DBEvent.u.CreateProcessInfo.hProcess, DBEvent.u.CreateProcessInfo.hThread,
DBEvent.u.CreateProcessInfo.lpBaseOfImage, DBEvent.u.CreateProcessInfo.lpStartAddress
<br>
invoke MessageBox,0, addr buffer, addr
AppName, MB_OK+MB_ICONINFORMATION <br>
.elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT <br>
.if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT
<br>
invoke ContinueDebugEvent,
DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE <br>
.continue <br>
.endif <br>
.elseif DBEvent.dwDebugEventCode==CREATE_THREAD_DEBUG_EVENT <br>
invoke MessageBox,0, addr NewThread, addr
AppName, MB_OK+MB_ICONINFORMATION <br>
.elseif DBEvent.dwDebugEventCode==EXIT_THREAD_DEBUG_EVENT <br>
invoke MessageBox,0, addr EndThread, addr
AppName, MB_OK+MB_ICONINFORMATION <br>
.endif <br>
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId,
DBG_EXCEPTION_NOT_HANDLED <br>
.endw <br>
invoke CloseHandle,pi.hProcess <br>
invoke CloseHandle,pi.hThread <br>
.endif <br>
invoke ExitProcess, 0 <br>
end start </p>
<h3>分析:</h3>
<p>程序首先填充OPENFILENAME結(jié)構(gòu),調(diào)用GetOpenFileName讓用戶選擇要調(diào)試的程序.</p>
<p>invoke GetStartupInfo,addr startinfo <br>
invoke CreateProcess, addr buffer, NULL, NULL, NULL, FALSE, DEBUG_PROCESS+ DEBUG_ONLY_THIS_PROCESS,
NULL, NULL, addr startinfo, addr pi </p>
<p>當(dāng)接收用戶選擇后,調(diào)用<b>CreateProcess</b>裝載程序.并調(diào)用<b>GetStartupInfo</b>以默認(rèn)值填充<b>STARTUPINFO</b>結(jié)構(gòu).注意我們將<b>DEBUG_PROCESS</b>標(biāo)志與<b>DEBUG_ONLY_THIS_PROCESS</b>標(biāo)志組合來僅調(diào)試這個(gè)程序,不包括子進(jìn)程.</p>
<p>.while TRUE <br>
invoke WaitForDebugEvent, addr DBEvent, INFINITE <br>
</p>
<p>在debuggee被裝入后,我們調(diào)用<b>WaitForDebugEvent</b>進(jìn)入無盡的調(diào)試循環(huán),<b>WaitForDebugEvent</b>在debuggee中發(fā)生調(diào)試事件時(shí)返回,因?yàn)槲覀冎付?lt;b>INFINITE</b>作為第二個(gè)參數(shù).當(dāng)調(diào)試事件發(fā)生時(shí),
<b>WaitForDebugEvent </b>返回并填充DBEvent結(jié)構(gòu).</p>
<p> .if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT <br>
invoke MessageBox, 0, addr ExitProc, addr
AppName, MB_OK+MB_ICONINFORMATION <br>
.break </p>
<p>我們要先檢查<b>dwDebugEventCode</b>的值, 如果是<b>EXIT_PROCESS_DEBUG_EVENT,</b>用一個(gè)消息框顯示"The
debuggee exits" 并退出調(diào)試循環(huán).</p>
<p> .elseif DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT
<br>
invoke wsprintf, addr buffer, addr ProcessInfo,
DBEvent.u.CreateProcessInfo.hFile, DBEvent.u.CreateProcessInfo.hProcess, DBEvent.u.CreateProcessInfo.hThread,
DBEvent.u.CreateProcessInfo.lpBaseOfImage, DBEvent.u.CreateProcessInfo.lpStartAddress
<br>
invoke MessageBox,0, addr buffer, addr
AppName, MB_OK+MB_ICONINFORMATION </p>
<p>如果<b>dwDebugEventCode</b> 的值為<b>CREATE_PROCESS_DEBUG_EVENT</b>,我們就在消息框中顯示一些感興趣的底層信息.這些信息從<b>u.CreateProcessInfo</b>獲得.
CreateProcessInfo是一個(gè)<b>CREATE_PROCESS_DEBUG_INFO</b>類型的結(jié)構(gòu)體.你可以查閱Win32 API獲得它的更多信息e.
</p>
<p> .elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT <br>
.if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT
<br>
invoke ContinueDebugEvent,
DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE <br>
.continue <br>
.endif </p>
<p>如果<b>dwDebugEventCode</b> 的值為<b>EXCEPTION_DEBUG_EVENT</b>,我們就要更進(jìn)一步檢查異常類型.它是一大堆的結(jié)構(gòu)嵌套,但我們可以從<b>ExceptionCode</b>成員獲得異常類型.如果<b>ExceptionCode</b>的值為
<b>EXCEPTION_BREAKPOINT</b>并且是第一次發(fā)生(或者我們已知道deuggee中沒有int 3h指令),我們可以安全地假定在debuggee要執(zhí)行第一條指令時(shí)發(fā)生這一異常.在我們完成這些處理后,就可以用
<b>DBG_CONTINUE</b>調(diào)用<b>ContinueDebugEvent</b>來繼續(xù)執(zhí)行debuggee.接著我們繼續(xù)等待下一個(gè)調(diào)試事件的發(fā)生.</p>
<p> .elseif DBEvent.dwDebugEventCode==CREATE_THREAD_DEBUG_EVENT <br>
invoke MessageBox,0, addr NewThread, addr
AppName, MB_OK+MB_ICONINFORMATION <br>
.elseif DBEvent.dwDebugEventCode==EXIT_THREAD_DEBUG_EVENT <br>
invoke MessageBox,0, addr EndThread, addr
AppName, MB_OK+MB_ICONINFORMATION <br>
.endif </p>
<p>如果<b>dwDebugEventCode</b> 的值為<b>CREATE_THREAD_DEBUG_EVENT</b>或<b>EXIT_THREAD_DEBUG_EVENT</b>,
我們的程序顯示一個(gè)消息框.</p>
<p> invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId,
DBG_EXCEPTION_NOT_HANDLED <br>
.endw </p>
<p>除了上面討論過的<b> EXCEPTION_DEBUG_EVENT</b>,用<b>DBG_EXCEPTION_NOT_HANDLED</b>標(biāo)志調(diào)用<b>ContinueDebugEvent</b>函數(shù)恢復(fù)debuggee的執(zhí)行.</p>
<p>invoke CloseHandle,pi.hProcess <br>
invoke CloseHandle,pi.hThread </p>
<p>當(dāng)debuggee結(jié)束時(shí),我們就跳出了調(diào)試循環(huán),這時(shí)要關(guān)閉 debuggee的線程和進(jìn)程句柄.關(guān)閉這些句柄并不意味著要關(guān)閉這些進(jìn)程和線程.只是說不再用這些句柄罷了.
</p>
<HR SIZE=1>
<DIV align=center>
<SCRIPT language=JavaScript1.1 src="../lion-tut-c13.files/textclick"></SCRIPT>
<BR>
</DIV>
<!-- 10:1 文本廣告交換 -->
<DIV align=center>
<SCRIPT language=JavaScript1.1 src="../lion-tut-c13.files/c21.htm"></SCRIPT>
<!-- 10:1 文本廣告交換 --></DIV>
<HR SIZE=1>
<DIV align=center>校對(duì):LuoYunBin's Win32 ASM Page, <A
href="http://asm.yeah.net/">http://asm.yeah.net</A></DIV>
</BODY></HTML>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -