原文链接:http://msdn.microsoft.com/en-us/library/windows/desktop/ms681675%28v=vs.85%29.aspx
本文链接:http://blog.csdn.net/wlsgzl/article/details/18571559
The debugger uses the WaitForDebugEvent function at the beginning of its main loop. 调试器在主循环的开始使用WaitForDebugEvent函数。This function blocks the debugger until a debugging event occurs.这个函数锁住了调试器知道一个调试事件发生。 When the debugging event occurs, the system suspends all threads in the process being debugged and notifies the debugger of the event.当调试事件发生了,系统挂起被调试进程的所有线程,通知调试器发生的事件。
The debugger can interact with the user, or manipulate the state of the process being debugged, by using the GetThreadContext, GetThreadSelectorEntry, ReadProcessMemory, SetThreadContext, and WriteProcessMemory functions. 调试器可以和用户互动,或者操作被调试进程的状态,通过调用这些函数:GetThreadContext、GetThreadSelectorEntry、ReadProcessMemory、SetThreadContext和WriteProcessMemory。GetThreadSelectorEntry returns the descriptor table entry for a specified selector and thread.GetThreadSelectorEntry函数返回一个指定选择器和线程的描述表入口。 Debuggers use the descriptor table entry to convert a segment-relative address to a linear virtual address.调试器使用描述表入口,将段相关地址转换为线性虚拟地址。 The ReadProcessMemory and WriteProcessMemory functions require linear virtual addresses.ReadProcessMemory和WriteProcessMemory函数要求线性虚拟地址。
Debuggers frequently read the memory of the process being debugged and write the memory that contains instructions to the instruction cache. After the instructions are written, the debugger calls the FlushInstructionCache function to execute the cached instructions.调试器经常读取被调试进程的内存,向指令缓存写指令。写完指令之后,调试器通过调用FlushInstructionCache函数来指令缓存指令。
The debugger uses the ContinueDebugEvent function at the end of its main loop.调试器在主循环的末尾使用ContinueDebugEvent函数。This function allows the process being debugged to continue executing.这个函数允许被调试的进程继续执行。
The following example uses the WaitForDebugEvent and ContinueDebugEvent functions to illustrate how a simple debugger might be organized.下面的例子使用WaitForDebugEvent和ContinueDebugEvent函数展示了如何构造组织一个简单的调试器。
#include <windows.h>
DWORD OnCreateThreadDebugEvent(const LPDEBUG_EVENT);
DWORD OnCreateProcessDebugEvent(const LPDEBUG_EVENT);
DWORD OnExitThreadDebugEvent(const LPDEBUG_EVENT);
DWORD OnExitProcessDebugEvent(const LPDEBUG_EVENT);
DWORD OnLoadDllDebugEvent(const LPDEBUG_EVENT);
DWORD OnUnloadDllDebugEvent(const LPDEBUG_EVENT);
DWORD OnOutputDebugStringEvent(const LPDEBUG_EVENT);
DWORD OnRipEvent(const LPDEBUG_EVENT);
void EnterDebugLoop(const LPDEBUG_EVENT DebugEv)
{
DWORD dwContinueStatus = DBG_CONTINUE; // exception continuation
for(;;)
{
// Wait for a debugging event to occur. The second parameter indicates
// that the function does not return until a debugging event occurs.
WaitForDebugEvent(DebugEv, INFINITE);
// Process the debugging event code.
switch (DebugEv->dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
// Process the exception code. When handling
// exceptions, remember to set the continuation
// status parameter (dwContinueStatus). This value
// is used by the ContinueDebugEvent function.
switch(DebugEv->u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
// First chance: Pass this on to the system.
// Last chance: Display an appropriate error.
break;
case EXCEPTION_BREAKPOINT:
// First chance: Display the current
// instruction and register values.
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
// First chance: Pass this on to the system.
// Last chance: Display an appropriate error.
break;
case EXCEPTION_SINGLE_STEP:
// First chance: Update the display of the
// current instruction and register values.
break;
case DBG_CONTROL_C:
// First chance: Pass this on to the system.
// Last chance: Display an appropriate error.
break;
default:
// Handle other exceptions.
break;
}
break;
case CREATE_THREAD_DEBUG_EVENT:
// As needed, examine or change the thread's registers
// with the GetThreadContext and SetThreadContext functions;
// and suspend and resume thread execution with the
// SuspendThread and ResumeThread functions.
dwContinueStatus = OnCreateThreadDebugEvent(DebugEv);
break;
case CREATE_PROCESS_DEBUG_EVENT:
// As needed, examine or change the registers of the
// process's initial thread with the GetThreadContext and
// SetThreadContext functions; read from and write to the
// process's virtual memory with the ReadProcessMemory and
// WriteProcessMemory functions; and suspend and resume
// thread execution with the SuspendThread and ResumeThread
// functions. Be sure to close the handle to the process image
// file with CloseHandle.
dwContinueStatus = OnCreateProcessDebugEvent(DebugEv);
break;
case EXIT_THREAD_DEBUG_EVENT:
// Display the thread's exit code.
dwContinueStatus = OnExitThreadDebugEvent(DebugEv);
break;
case EXIT_PROCESS_DEBUG_EVENT:
// Display the process's exit code.
dwContinueStatus = OnExitProcessDebugEvent(DebugEv);
break;
case LOAD_DLL_DEBUG_EVENT:
// Read the debugging information included in the newly
// loaded DLL. Be sure to close the handle to the loaded DLL
// with CloseHandle.
dwContinueStatus = OnLoadDllDebugEvent(DebugEv);
break;
case UNLOAD_DLL_DEBUG_EVENT:
// Display a message that the DLL has been unloaded.
dwContinueStatus = OnUnloadDllDebugEvent(DebugEv);
break;
case OUTPUT_DEBUG_STRING_EVENT:
// Display the output debugging string.
dwContinueStatus = OnOutputDebugStringEvent(DebugEv);
break;
case RIP_EVENT:
dwContinueStatus = OnRipEvent(DebugEv);
break;
}
// Resume executing the thread that reported the debugging event.
ContinueDebugEvent(DebugEv->dwProcessId,
DebugEv->dwThreadId,
dwContinueStatus);
}
}